BioPlayground

🧬
목록으로

쿠키와 세션으로 로그인 이해하기

쿠키, 세션, 로그인의 동작 원리를 실험실 비유로 설명합니다. HTTP 무상태의 의미와 인증 메커니즘의 기초를 배웁니다.

입문
|
45
|
검증 완료 (2026-06)
쿠키세션인증로그인HTTP개인화
트랙 진행률0/11 (0%)

쿠키와 세션으로 로그인 이해하기

지금까지 만든 시료 관리 API 서버에는 한 가지 큰 문제가 있습니다. 누구나 시료를 등록하고, 수정하고, 삭제할 수 있다는 것입니다. 실험실에서 장비실 출입에 카드키가 필요하듯, 웹 서비스에도 "이 사람이 누구인지 확인하는 절차" — **인증(Authentication)**이 필요합니다.

로그인은 어떻게 동작할까요? 이 질문에 답하려면 먼저 웹의 근본적인 특성을 이해해야 합니다.

HTTP는 기억하지 못한다

웹의 통신 프로토콜인 HTTP는 **무상태(stateless)**입니다. 서버는 요청을 처리하고 응답을 보낸 순간, 그 사용자가 누구였는지 즉시 잊어버립니다.

비유하면 — 접수 데스크에서 담당자가 5초마다 기억이 리셋되는 상태입니다. "제 시료 S001 결과 알려주세요" → 결과 전달 → (리셋) → "제가 아까 시료 S001 물어봤는데요" → "누구시죠?"

매 요청마다 "저 김연구입니다"라고 다시 말해야 합니다. 이 불편함을 해결하기 위해 1994년에 **쿠키(Cookie)**가 발명되었습니다.

쿠키: 브라우저에 붙이는 이름표

쿠키는 서버가 브라우저에게 건네주는 작은 텍스트 데이터입니다. 브라우저는 이 데이터를 저장해두었다가, 같은 서버에 요청할 때마다 자동으로 함께 보냅니다.

text
[1] 로그인 요청
  브라우저 → 서버: "아이디 kim, 비밀번호 1234"
  서버 → 브라우저: "확인 완료! 이 쿠키를 갖고 다녀"
                   Set-Cookie: user=kim

[2] 이후 요청 (자동)
  브라우저 → 서버: "시료 목록 줘" + Cookie: user=kim
  서버: "아, kim 연구원이구나. 시료 목록 보내줄게"

[3] 또 다른 요청 (자동)
  브라우저 → 서버: "S001 상세정보" + Cookie: user=kim
  서버: "kim 연구원의 요청이네. S001 정보 보내줄게"

실험실 출입증과 같습니다. 한 번 발급받으면 매번 신분을 다시 증명할 필요 없이, 출입증만 보여주면 됩니다.

Express에서 쿠키 다루기

javascript
const express = require("express");
const app = express();

app.get("/login", function(req, res) {
  res.setHeader("Set-Cookie", "user=kim; Path=/");
  res.send("로그인 완료");
});

app.get("/whoami", function(req, res) {
  const cookies = req.headers.cookie;
  res.send("현재 쿠키: " + cookies);
});

app.listen(3000);

/login에 접속하면 서버가 Set-Cookie 헤더로 쿠키를 보내고, 이후 /whoami에 접속하면 브라우저가 자동으로 쿠키를 보내는 것을 확인할 수 있습니다.

쿠키의 한계: 왜 세션이 필요한가

쿠키만으로 인증하면 심각한 문제가 있습니다. 쿠키는 브라우저에 저장됩니다. 브라우저 개발자 도구를 열면 누구나 쿠키 내용을 볼 수 있고, 수정할 수도 있습니다.

만약 Cookie: user=kim 이런 식으로 사용자 이름을 직접 쿠키에 넣으면, 누군가 Cookie: user=admin으로 바꿔서 관리자 행세를 할 수 있습니다.

실험실 비유로 — 출입증에 "이름: 김연구"라고 적혀있는데, 누구나 수정 테이프로 이름을 바꿀 수 있다면 출입 통제가 무의미합니다.

**세션(Session)**은 이 문제를 해결합니다.

세션: 서버가 관리하는 출입 기록

세션의 핵심 아이디어 — 민감한 정보는 서버에 저장하고, 브라우저에는 식별 번호만 준다.

text
[1] 로그인 성공
  서버 내부: { session_abc123: { user: "kim", role: "researcher" } }
  서버 → 브라우저: Set-Cookie: session_id=abc123

[2] 이후 요청
  브라우저 → 서버: Cookie: session_id=abc123
  서버: abc123 세션 찾기 → { user: "kim", role: "researcher" }
       → "kim 연구원이구나"

브라우저가 가진 것은 abc123이라는 의미 없는 번호뿐입니다. 이 번호를 바꿔봤자 서버에 등록된 세션이 아니면 무효합니다.

실험실 비유로 — 출입증에 바코드만 찍혀있고, 실제 신원 정보는 보안실 컴퓨터에 있는 것과 같습니다. 출입증을 복사해도 바코드가 데이터베이스에 없으면 문이 열리지 않습니다.

쿠키만 사용세션 (쿠키 + 서버 저장소)
데이터 위치브라우저서버
보안사용자가 수정 가능 (위험)서버만 수정 가능 (안전)
용량4KB 제한서버 메모리/DB 기반 (제한 없음)
비유이름이 적힌 출입증바코드만 있는 출입증 + 보안실 DB

쿠키의 보안 옵션

쿠키 자체에도 보안 장치를 설정할 수 있습니다:

text
Set-Cookie: session_id=abc123; HttpOnly; Secure; Path=/; Max-Age=3600
옵션의미왜 필요한가
HttpOnlyJavaScript에서 쿠키에 접근 불가악성 스크립트(XSS)가 쿠키를 훔치는 것을 방지
SecureHTTPS에서만 쿠키 전송네트워크 도청으로 쿠키가 노출되는 것을 방지
Max-Age=36003600초(1시간) 후 자동 삭제오래된 로그인 상태가 무한히 유지되는 것을 방지
Path=/이 경로 이하의 요청에서만 쿠키 전송불필요한 쿠키 전송 범위 제한

Max-Age가 없는 쿠키는 브라우저를 닫으면 사라집니다 — 이것을 **세션 쿠키(Session Cookie)**라고 합니다. Max-Age가 있는 쿠키는 브라우저를 닫아도 남아 있습니다 — 이것을 **영속 쿠키(Permanent Cookie)**라고 합니다.

현대의 인증: 토큰 기반

현대 웹 서비스에서는 세션 ID 대신 **JWT(JSON Web Token)**라는 토큰을 사용하는 경우가 많습니다. BioPlayground가 사용하는 Supabase도 JWT 기반 인증입니다.

원리는 세션과 비슷하지만, 차이가 있습니다:

세션 방식토큰(JWT) 방식
서버 상태세션 저장소 필요서버에 저장 불필요
검증세션 DB 조회토큰 자체에 서명 검증
확장성서버가 여러 대면 세션 공유 필요서버 간 공유 불필요

깊은 구현은 이 단계에서 다루지 않습니다. 중요한 것은 메커니즘을 이해하는 것입니다:

  1. 사용자가 아이디/비밀번호를 보냄
  2. 서버가 확인하고, 식별자(세션 ID 또는 토큰)를 발급
  3. 브라우저가 이후 요청에 식별자를 자동 첨부
  4. 서버가 식별자로 "이 사람이 누구인지" 확인

모든 로그인 시스템은 이 4단계의 변형입니다.

직접 해보기 (Faded Example)

아래 빈칸을 채워 쿠키 기반 인증의 흐름을 완성하세요.

빈칸 채우기javascript
// 1. 로그인: 서버가 쿠키를 발급
app.post("/login", function(req, res) {
res.setHeader("", "session_id=xyz789; HttpOnly; Path=/");
res.json({ message: "로그인 성공" });
});
// 2. 보호된 API: 쿠키로 사용자 확인
app.get("/my-samples", function(req, res) {
const cookies = req.headers.;
if (!cookies || !cookies.includes("session_id")) {
return res.status().json({ error: "로그인 필요" });
}
res.json({ samples: ["S001", "S002"] });
});

흔한 에러 & 해결법

Q: 쿠키가 전송되지 않습니다 (req.headers.cookie가 undefined)

브라우저의 개발자 도구(F12) → Application → Cookies에서 해당 도메인의 쿠키가 있는지 확인하세요. Secure 옵션이 켜져 있으면 HTTP(localhost)에서는 전송되지 않습니다. 개발 중에는 Secure를 빼거나 HTTPS를 사용하세요.

Q: Set-Cookie 헤더를 보냈는데 브라우저가 쿠키를 저장하지 않습니다

프론트엔드와 백엔드의 도메인(또는 포트)이 다르면 CORS 정책에 의해 쿠키가 차단됩니다. fetch 호출 시 credentials: 'include' 옵션을 추가하고, 서버에서 Access-Control-Allow-Credentials: true 헤더를 설정해야 합니다.

Q: 세션과 쿠키의 차이를 한 문장으로 설명해주세요

쿠키는 "브라우저에 저장되는 데이터"이고, 세션은 "서버에 저장되는 데이터를 쿠키의 ID로 찾는 시스템"입니다. 세션은 쿠키 위에 올라가는 개념입니다.