WeeklyPaper: 세션 기반 인증과 토큰 기반 인증의 차이점과 각각의 보안 고려사항에 대해 설명하세요.
배경
로그인 후 유저의 인증 상태를 유지하기 위해 세션 또는 토큰 방식을 사용한다.
- 이렇게 해야 하는 이유는 HTTP 프로토콜의 속성 때문이다.
- 기본적으로 서버는 각 HTTP 요청을 독립적 사건으로 취급한다. 그래서 이전 요청의 맥락 (로그인 여부, 유저 정보 등)을 자동으로 기억하지 않는다.
- HTTP 1.1에서 keep-alive가 있어도, 이는 TCP 소켓 재사용일 뿐 응용 계층의 인증상태를 보장하지 않는다.
- 또한, 실제 서비스는 로드 밸런서, 다수의 서버, 캐시, 프록시가 개입한다. 서버 로컬 메모리에만 의존한다면 다른 서버로 라우팅되는 순간 인증 상태를 잃어버린다. 중앙 저장소 (세션 스토어)나, 클라이언트가 들고 다니는 증표 (토큰)가 필요하다!
세션은 전통적인 웹 환경에 적합하고, 토큰은 모바일/분산 시스템 환경에 적합하다.
세션 기반 방식 (쿠키)


- 로그인 성공 시 서버가 세션 ID를 생성하고, 이를 쿠키로 포장해 클라이언트에게 전달한다. 이후, 요청마다 쿠키로 세션을 찾아 사용자 신원을 복원한다.
- 구성 요소
- 세션 저장소(메모리, Redis, DB), 쿠키 설정(HttpOnly, Secure, SameSite)가 있다.
- 장단점
- 장점: 구현이 비교적 단순, 서버가 세션을 제어하므로 즉시 강제 로그아웃 가능(세션 삭제).
- 단점: 서버 측 상태를 유지하므로 확장 시 저장소 일관성 필요(공유 저장소 필수).
쿠키란?
쿠키는 브라우저가 보관하고 요청마다 자동 전송하는 작은 데이터다. 서버는 쿠키를 활용해 무상태(stateless)인 HTTP에서 사용자의 상태(로그인 여부 등)를 복원한다.
- 위에 언급했듯이 쿠키는 서버가 생성하고 클라이언트에게 전달한다.
기본 형태는 Name=Value고 (플래그라고 불림), 세미콜론(;)으로 구분된다.
Set-Cookie: SESSIONID=abc123;
Path=/;
Domain=example.com;
Max-Age=1800;
HttpOnly; Secure;
SameSite=Lax
쿠키 속성 (Attribute) 종합 테이블
| 속성 (Attribute) | 의미 및 설명 | 주요 포인트 / 권장 사항 |
| Name=Value | 쿠키의 이름과 값을 지정한다. | 값에는 공백, 세미콜론 같은 특수 문자를 사용할 수 없으므로, 필요 시 URL 인코딩을 사용하는 것이 좋다. |
| Domain | 쿠키가 전송될 도메인을 제한한다. | 설정하지 않으면 쿠키를 생성한 호스트에만 전송된다. 특정 도메인 및 그 하위 도메인으로 범위를 넓힐 수 있으며, 서비스 도메인으로 제한하는 것을 권장한다. |
| Path | 쿠키가 전송될 서버의 경로를 제한한다. | 지정된 경로와 그 하위 경로 요청 시에만 쿠키가 전송된다. 일반적으로 /로 설정하여 사이트 전체에서 사용 가능하도록 하는 것을 권장한다. |
| Expires | 쿠키의 만료 날짜와 시각을 절대적인 시간으로 설정한다. | 표준화된 GMT 형식의 날짜 문자열을 사용한다. (Wed, 21 Oct 2025 07:28:00 GMT) |
| Max-Age | 쿠키가 만료되기까지 남은 시간을 초(second) 단위의 상대적인 시간으로 설정한다. | Expires와 Max-Age가 모두 있으면 Max-Age가 우선된다. |
| Secure | HTTPS 프로토콜을 사용하는 암호화된 요청에만 쿠키를 전송하도록 제한한다. | 개인정보 등 민감한 데이터를 다루는 쿠키에는 반드시 true로 설정해야 한다. |
| HttpOnly | JavaScript의 document.cookie API를 통한 쿠키 접근을 차단한다. | XSS(Cross-Site Scripting) 공격을 완화하는 데 매우 효과적이다. 특히 인증 관련 쿠키에는 강력히 true로 설정할 것을 권장한다. |
| SameSite | 다른 출처(Cross-site)에서 요청이 발생할 때 쿠키 전송 여부를 제어한다. | Lax가 기본값이며, CSRF(Cross-Site Request Forgery) 공격을 방어한다. SSO나 외부 결제 연동처럼 제3자 쿠키가 필요하면 None으로 설정하되, 반드시 Secure 옵션을 함께 사용해야 한다. |
| Priority | 브라우저의 쿠키 저장 공간이 가득 찼을 때 어떤 쿠키를 먼저 제거할지에 대한 힌트를 제공한다. | Low, Medium, High 중 하나로 설정할 수 있으며, 중요한 쿠키가 삭제되지 않도록 우선순위를 지정하는 데 사용된다. (브라우저별 지원 상이) |
- 민감한 정보가 담긴 쿠키에는 HttpOnly + Secure + SameSite를 기본값으로 적용해야 한다.
브라우저의 쿠키 처리 흐름:

- 도메인/경로 매칭에 부합하는 요청에만 자동 전송된다.
- 동일 이름의 쿠키가 경로나 도메인에 따라 여러개 존재할 수 있다.
세션이란?
세션은 클라이언트(사용자)가 서버에 접속한 순간부터 접속을 끊을 때까지의 연결 상태를 의미한다.
세션은 사용자의 상태 정보를 서버에 저장해 두고, 이를 세션 ID(Session ID)라는 키로 식별하는 방식을 사용한다.
- 세션은 서버에 저장된다 -> 메모리, DB, Redis 등
- 동작 방식 요약
- 세션 생성과 전달
- 사용자가 로그인 시 서버는 아이디/비밀번호 검증을 수행한다.
- 검증에 성공하면 서버는 새로운 세션 객체(Session) 를 생성하고, 사용자 ID와 관련 정보를 세션 저장소에 저장한다.
- 서버는 해당 세션을 식별할 수 있는 세션 ID를 생성한다.
- 이 세션 ID를 Set-Cookie 헤더에 담아 브라우저에 전달한다.
-
HTTP/1.1 200 OK Set-Cookie: SESSION=abc123; Path=/; HttpOnly; Secure; Max-Age=1800 - 브라우저는 이 Set-Cookie 값을 저장하고, 이후 동일한 도메인 요청마다 자동으로 전송한다!
-
- 세션 확인 과정
- 사용자가 보호된 페이지에 접근하면 브라우저는 자동으로 요청에 Cookie 헤더를 포함한다.
- 서버는 요청 헤더의 세션 ID(abc123)를 확인한다.
- 서버는 세션 저장소에서 해당 세션 ID를 찾아, 사용자 정보를 복원한다.
- 세션이 유효하면 요청을 정상 처리하고 응답한다.
- 세션 생성과 전달
| Set-Cookie | 서버 → 브라우저 | 서버가 쿠키를 생성/수정하도록 지시 | Set-Cookie: SESSION=abc123; Path=/; HttpOnly; Secure |
| Cookie | 브라우저 → 서버 | 브라우저가 저장한 쿠키 값을 전송 | Cookie: SESSION=abc123 |
*다중 서버 환경에서는 스티키 세션 대신 공유 세션 저장소(예: Redis) 사용을 권장한다.
Redis란?
- Redis(레디스)는 Key-Value 구조의 데이터를 디스크가 아닌 메모리에 저장하고 조회하는 비관계형 데이터베이스 관리 시스템(NoSQL)이다. 빠른 속도가 장점이라 캐시, 실시간 순위표, 세션 관리 등에 주로 사용된다.
- https://github.com/redis/redis
스키티 세션이란?
- 스티키 세션(Sticky Session)은 로드 밸런싱 환경에서 특정 사용자의 첫 요청을 처리한 서버로만 이후의 모든 요청이 계속해서 전송되도록 고정(stick)하는 기술이다. 특정 세션 정보를 한 서버가 독점하게 만들어 데이터 정합성을 유지할 때 사용된다.
보안 고려사항
1. 세션 하이재킹 (Session Hijacking)
- 공격자가 사용자의 세션 Id를 훔쳐서 정상 사용자인 것처럼 서버에 접은하는 공격이다. 주로 XSS (Cross-Site Scripting) 공격으로 쿠키를 탈취하거나 암호화되지 않은 네트워크 (HTTP) 통신을 엿보는 방식으로 발생한다.
- 대응책
- HttpOnly 쿠키 옵션: JavaScript가 쿠키에 접근하지 못하게 막아 XSS 공격으로 세션 ID를 탈취하는 것을 방지할 수 있다.
- Secure 쿠키 옵션: HTTPS 연결에서만 쿠키가 전송되도록 할 수 있다.
- 로그인 세션의 유효 기간을 짧게 설정해서 탈취된 세션 ID의 사용시간을 최소화할 수 있다.
2. CSRF (Cross-Site Request Forgery)
- 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동(글쓰기, 정보 수정 등)을 하도록 만드는 공격이다. 브라우저는 인증된 사이트에 요청을 보낼 때 자동으로 세션 쿠키를 첨부하기 때문에 이 공격에 취약한다고 한다.
- 대응책
- 서버는 매 요청마다 임의의 토큰을 생성하여 사용자에게 보내고, 다음 요청 시 이 토큰을 함께 보내도록 요구하게 할 수 있다다. 공격자는 이 토큰 값을 알 수 없으므로 요청을 위조하기 어렵다.
- SameSite 쿠키 옵션: 다른 도메인에서 요청이 시작될 때 쿠키 전송을 제한하여 CSRF 공격을 효과적으로 방어할 수 있다. (Lax 또는 Strict로 설정)
토큰 기반 인증 (JWT 등)

- 로그인 성공시, 서명이 포함된 토큰을 발급한다.
- 토큰은
- 클라이언트는 이후 요청마다 토큰을 Authorization header로 전송하고, 서버는 서명 검증으로 신원을 확인한다.
- 구성 요소
- Access Token
- 실제 데이터 접근 권한을 증명하는 데 사용하는 단기 암호화 키다.
- 사용자가 API를 호출하거나 보호된 리소스에 접근할 때마다 이 토큰을 HTTP 헤더에 담아 보내야 한다. 보안을 위해 유효 기간이 보통 몇 분에서 몇 시간으로 짧게 설정되며, 탈취되더라도 피해를 최소화하는 역할을 한다.
- Refresh Token
- 액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급받기 위해 사용하는 장기 인증용 키다.
- 액세스 토큰보다 훨씬 긴 유효 기간(며칠에서 몇 달)을 가지며, 안전한 곳에 저장해야 한다.
- 이 토큰 덕분에 사용자는 매번 아이디와 비밀번호로 로그인하지 않고도 로그인 상태를 유지할 수 있다.
- 키 관리
-
액세스 토큰과 리프레시 토큰을 생성하고 검증하는 데 사용되는 비밀 키(Secret Key)를 안전하게 관리하는 모든 과정을 의미한다.이 비밀 키가 유출되면 공격자가 유효한 토큰을 무제한으로 만들어낼 수 있으므로, 토큰 인증 시스템의 보안 수준을 결정하는 가장 중요한 요소다.
- Access Token
- 장단점
- 장점: 서버가 인증 상태를 저장하지 않아 수평 확장이 쉽다.
- 단점: 발급된 토큰은 유효기간 동안 기본적으로 유효하다. 강제 만료가 필요하면 블랙리스트나 토큰 버전 필드 등을 도입해야 한다.
Authorization header란?
HTTP 요청에서 인증 정보를 서버로 전달하기 위해 사용하는 표준 헤더다.
HTTP 요청의 헤더 부분에 포함되고, 서버가 클라이언트의 신원을 확인하고 보호된 리소스 접근 권한을 부여하는 데 사용된다.
Authorization 헤더를 사용하여 Basic 인증 자격 증명을 보낸 요청 예시:
GET /protected-resource HTTP/1.1
Host: example.com
Authorization: Basic dXNlcjpwYXNz
기본적인 형태:
Authorization: <인증방식> <인증정보>
// Basic 인증
Authorization: Basic dXNlcjpwYXNz
// Bearer 토큰 인증 (JWT 포함) - 표준 + 가장 많이 사용됨
Authorization: Bearer eyJhbGciOi...
// Digest 인증
Authorization: Digest username="Mufasa", realm="testrealm@host.com", ...
JWT란? (JSON Web Token)
JWT는 데이터를 안전하고 간결하게 전송하기 위해 고안된 인터넷 표준 인증 방식이다. 특히, 토큰 기반 인증(Token-based Authentication) 에서 가장 범용적으로 사용된다.
구조 (.으로 구분)

- Header (헤더) : 어떤 알고리즘으로 서명했는지, 어떤 타입의 토큰인지 정의
- Payload (페이로드) : 사용자 정보와 클레임(Claim) 데이터가 담김
- Signature (서명) : 헤더와 페이로드가 변조되지 않았음을 검증
- 이 3가지가 합쳐져서 Authorization header에 담김
- Base64URL(Header) + . + Base64URL(Payload) + . + Signature
- 예: Authorization: Bearer eyJhbGciOi...
JWT 핵심 클레임 정리:
| 클레임 | 의미 | 비고 |
| sub | 주체 ID(유저 식별자) | 필수에 가깝게 사용 |
| iss | 발급자 | 서비스 식별 |
| aud | 대상자 | 특정 클라이언트 제한 |
| exp | 만료 시간 | 반드시 짧게 설정(예: 15분) |
| iat | 발급 시간 | 토큰 생성 시각 |
| jti | 토큰 식별자 | 재사용 감지, 블랙리스트 키로 활용 |
- 얘네들은 Payload에 들어간다.
변환 과정 정리 (서버가 로그인 요청을 받을 때):
- 1단계: 재료(JSON)를 암호화된 문자열로 변환 (인코딩)
- 먼저 서버는 Header와 Payload라는 두 개의 JSON 객체를 각각 읽기 힘든 Base64URL 문자열로 변환한다. 암호화처럼 보이지만, 사실은 정해진 규칙에 따라 문자를 바꾸는 인코딩 과정이다.
- Header (JSON) { "alg": "HS256", "typ": "JWT" } -> 인코딩 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
- Payload (JSON) { "sub": "user123", "name": "Alice" } -> 인코딩 eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIn0
- 먼저 서버는 Header와 Payload라는 두 개의 JSON 객체를 각각 읽기 힘든 Base64URL 문자열로 변환한다. 암호화처럼 보이지만, 사실은 정해진 규칙에 따라 문자를 바꾸는 인코딩 과정이다.
- 2단계: 위조 방지 서명(Signature) 제작
- 1단계에서 만들어진 두 개의 문자열을 점(.)으로 합친 뒤, 서버만 아는 비밀 키(Secret Key)를 이용해 암호화하여 서명(Signature)을 만든다. 이 서명은 토큰이 중간에 위조되지 않았음을 증명하는 역할을 한다.
- 인코딩된Header + . + 인코딩된Payload + 비밀키 = 서명(Signature)
- 3단계: 최종 토큰 조립
- 이제 1, 2단계에서 만든 세 조각을 점(.)으로 이어 붙이면 드디어 하나의 완성된 JWT(액세스 토큰)가 된다.
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIn0 . TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
- 완성된 JWT를 브라우저에게 응답으로 보내준다.
- 이렇게 완성된 JWT 문자열은 앞으로 API를 요청할 때 HTTP 요청 헤더(Request Header)의 Authorization 필드에 담겨 서버로 전송된다.
-
GET /api/user-profile HTTP/1.1 Host: my-service.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIn0.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ - 브라우저는 단순히 토큰을 전달받아 사용만 한다! 출입증을 받아 앞으로 사용하는 거라고 생각하면 쉽다.
-
보안 고려사항
1. 토큰 탈취 (Token Hijacking)
- 세션 ID와 마찬가지로 공격자가 토큰을 탈취할 수 있다. 토큰은 주로 브라우저의 Local Storage에 저된다.
- 대응책
- Refresh Token 활용: 유효 기간이 짧은 Access Token과 유효 기간이 긴 리프레시 토큰을 함께 사용해서, 액세스 토큰이 탈취되어도 피해 시간을 최소화할 수 있고, 민감한 리프레시 토큰은 HttpOnly 속성을 가진 쿠키에 저장하여 보안을 강화할 수 있다.
2. 비밀 키 관리 (Secret Key Management)
- 토큰의 서명(Signature)을 생성하고 검증하는 데 사용되는 비밀 키(Secret Key)가 유출되면, 공격자가 마음대로 유효한 토큰을 무한정 생성할 수 있게 된다. 이는 시스템 전체의 인증 체계가 붕괴되는 것과 같습니다.
- 대응책
- 강력한 키 사용: 추측하기 어려운 복잡하고 긴 문자열을 비밀 키로 사용해야 한다.
- 안전한 키 관리: 비밀 키를 소스 코드에 하드코딩하지 않고, 환경 변수나 외부 보안 저장소를 통해 안전하게 관리해야 한다.
세션 VS 토큰 정리
| 설명 | 장점 | 단점 | 적용 사례 | |
| 세션 | 서버 메모리에 인증 정보 저장 | 단순, 안정적 | 서버 부하 증가 | 소규모 웹 서비스 |
| 토큰 | 클라이언트에 토큰 저장 후 매 요청마다 전달 | 확장성 높음 | 토큰 탈취 시 위험 | 모바일, 분산 환경 |
'CS > Security' 카테고리의 다른 글
| [Security] JWT(JSON Web Token)의 구조와 구성 요소 (0) | 2025.09.30 |
|---|---|
| [Security] OAuth 2.0의 주요 컴포넌트와 Authorization Code Grant 흐름 (0) | 2025.09.25 |