인증과 상태 관리의 필요성
웹은 본래 무상태(Stateless) 프로토콜인 HTTP 위에서 동작,
즉 클라이언트가 요청을 보낼 때마다 서버는 이 요청이 누구로부터 왔는지를 기본적으로 알 수 없다.(검증 안됨)
사용자가 로그인을 해도 다음 요청에서 서버는 그 사용자가 여전히 로그인 상태인지 알 수 없다.
따라서, 인증 상태를 유지하기 위한 메커니즘을 필요로 한다.
→ 쿠키, 세션, JWT
쿠키(Cookie)
브라우저가 저장하는 작은 데이터. 상태 유지의 기본 단위,
상태 유지를 위해 사용한다. (Session ID 보관, 로그인 상태 유지, 사용자 설정 값 저장 등)
서버가 응답 시 Set-Cookie 헤더를 내려주면, 브라우저는 이후 해당 도메인 요청마다
자동으로 Cookie 헤더를 붙인다.
장점
- 브라우저에 표준 기능으로 내장되어 있다. 즉, 별도의 구현이 필요없다.
- 서버와 클라이언트 간 상태 공유가 간단함.
단점
- 용량 제한(4KB), 도메인별 개수 제한.
- 민감한 정보 저장 시 보안 취약함.(XSS, 탈취)
- 클라이언트에서 수정이 가능함
세션(Session)
서버에서 관리하는 사용자 상태.
안정적이지만 확장성에는 한계가 존재한다.
보통 서버는 사용자가 로그인하면 고유한 세션 ID를 발급,
이 세션 ID는 클라이언트의 쿠키에 저장되고, 요청 시 함께 전송된다.
서버는 이 세션 ID를 조회하여 해당 사용자의 로그인 상태나 데이터를 확인한다.
장점
- 실제 중요한 데이터를 서버에 저장하면 클라이언트 유출 위험이 낮다
- 서버가 세션 만료, 강제 로그아웃 등을 제어할 수 있다.
단점
- 서버 메모리/스토리지를 점유 → 트래픽이 많으면 확장성 문제가 생김.
- 서버 간 세션 공유가 필요 → Redis 같은 중앙 저장소 필요.
- 서버리스, 무상태 아키텍처에서는 현실적으로 어렵다.
JWT(JSON Web Token)
세션을 서버에 저장하지 않고, 토큰 자체에 사용자 상태를 담는 방식.
상태를 토큰 자체에 담기 때문에 서버 확장성에 유리하지만 탈취 시 위험할 수 있음.
로그인 성공 시 서버가 서명된 JWT를 발급,
클라이언트는 JWT를 로컬 스토리지, 세션 스토리지, 혹은 쿠키에 저장. 이후 API 요청시, 헤더에 포함
서버는 서명만 검증하면 요청자 식별 가능.
Authorization: Bearer <token>장점
- 무상태(Stateless) → 서버 확장성에 유리.
- 다양한 서비스/도메인 간 인증 공유(SSO)에 유용함
- JSON 포맷 → 읽기/파싱 쉬움.
단점
- 토큰 자체가 길다. 즉, HTTP 헤더 부담.
- 토큰이 탈취되면 만료될 때까지 악용이 가능함(서버에서 강제 폐기 어려움)
- 로컬 스토리지/세션 스토리지 저장 시 XSS 공격에 취약.
HttpOnly ?
쿠키를 안전하게 지키는 최소한의 보안 옵션,
쿠키를 사용할 때 보안을 강화하려면 HttpOnly 옵션을 반드시 고려해야 한다.
HttpOnly 쿠키는 자바스크립트(document.cookie)로 접근할 수 없고,
오직 HTTP 요청에만 자동으로 첨부된다.
→ 즉, XSS 공격자가 자바스크립트를 주입하더라도 쿠키 값을 읽어내기 어렵다.
보통 세션 ID나 JWT Access Token을 쿠키에 저장할 때
HttpOnly + Secure 옵션을 함께 설정한다.
*Secure: HTTPS에서만 전송
*SameSite: 크로스사이트 요청 시 쿠키 전송 제한(CSRF 방어)
실무에서 사용할 때
소규모 서비스에서 인증 메커니즘
단순 로그인 유지에서는 다음과 같이 안전하고 간단하게 설계할 수 있다
→ 세션 기반 + HttpOnly 쿠키
대규모/분산 아키텍처 서비스에서의 인증 메커니즘
JWT 기반 토큰 인증으로 설계하면 서버 확장성에 유리.
단, Refresh Token + 짧은 Access Token 주기로 보완해야 보안을 강화할 수 있음
보안 강화에 있어서 필요한 부분
- 민감한 데이터는 쿠키/스토리지에 직접 저장하지 않도록 할 것.
- HttpOnly, Secure, SameSite 옵션을 적극 사용
- JWT는 꼭 짧은 수명 + Refresh Token 구조로 운영하도록 한다.
 
