JWT(JSON Web Token)
- 두 개체 사이에서 정보를 안전하게 전송하기 위한 자체 검증된 JSON 문자열
Cookie와 Session
- 웹 애플리케이션의 초기에는 HTTP가 상태를 유지하지 않는(Stateless) 프로토콜이었기 때문에 사용자의 상태나 정보를 유지하기 위해 쿠키와 세션이 도입되었다.
Cookie
- 사용자의 브라우저에 저장되는 작은 데이터 조각이다.
- 사용자의 세션 ID나 언어 설정과 같은 사용자의 상태 정보를 저장하는데 사용된다.
Session
- 서버 측에서 사용자 정보를 저장하기 위한 메커니즘이다.
- 사용자별로 고유한 세션 ID가 생성되고, 이 ID는 쿠키를 통해 클라이언트에게 전달된다.
- 클라이언트는 다음 요청 시 이 세션 ID를 사용하여 자신을 식별한다.
요청/응답 과정
1. 클라이언트가 서버에 접속 시 서버에서 세션 ID를 발급
2. 서버는 응답을 클라이언트에게 전송하면서, 세션 ID를 쿠키로 저장
3. 클라이언트는 서버에 요청할 때, 이 쿠키의 세션 ID를 같이 전달
4. 서버는 세션 ID를 전달 받아 별다른 작업없이 클라이언트 정보를 응답

Cookie와 Session의 차이
- 결국 세션도 쿠키를 사용하지만 쿠키는 클라이언트에 정보를 저장하고, 세션은 서버에 정보를 저장한다.
- 세션은 서버 처리가 필요하기 때문에 요청 속도는 쿠키가 세션보다 더 빠르다.
- 쿠키는 로컬에 저장되기 때문에 변질되거나 스니핑 당할 우려가 있어서 보안에 취약하다.
- 세션은 쿠키를 이용하여 세션 ID만 저장하고 그것을 서버에서 처리하기 때문에 비교적 보안성이 좋다.
- 쿠키는 브라우저를 종료해도 만료시간 동안 파일로 저장되기 때문에 정보가 남아있다.
- 세션도 만료시간을 정할 수 있지만 브라우저가 종료되면 만료시간에 상관없이 삭제된다.
세션 사용의 주의
세션은 서버의 자원을 사용하기 때문에 무분별하게 사용되면 서버 메모리에 오버헤드가 발생한다.
Cookie와 Session의 문제점
- 세션은 서버에 저장되므로, 사용자가 많아질수록 추가적인 서버 자원이 필요하다.
- 클라이언트의 요청마다 쿠키 정보가 헤더에 포함되어 전송되므로, 네트워크 오버헤드가 발생할 수 있다.
- 세션 하이재킹(Session Hijacking)과 같이 쿠키에 저장된 세션 ID가 탈취되면, 공격자는 해당 ID를 사용하여 사용자를 흉내낼 수 있다.
- HTTP는 상태를 유지하지 않는(Stateless) 프로토콜이지만 세션은 서버에 상태를 유지하게 만들기 때문에, Stateless한 아키텍처 원칙을 위반한다.
JWT의 등장
- JSON Web Token의 줄임말로, Cookie와 Session의 문제점을 보완하기 위해 나타난 인터넷 표준 인증 방식이다.
- 인증에 필요한 정보들을 암호화시켜 사용하는 토큰이다.
JWT의 구성
- JWT는 Header, Payload, Signature 세 부분으로 구성되어 있다.
- 이 세 부분을 결합하면,
header.payload.signature 형식의 긴 문자열이 생성되는데, 이것이 바로 JWT이다.
- JWT의 메타데이터를 담고 있으며, 토큰의 유형과 사용하는 해시 알고리즘을 포함한다.
typ(Type)
- 토큰의 유형을 나타내는데, 대부분의 경우
JWT로 설정된다.
alg(Alogorithm)
- 토큰을 서명하는데 사용되는 암호화 알고리즘을 나타낸다.
{
"typ": "JWT",
"alg": "HS256"
}
Payload
- 토큰에 포함될 클레임(정보)들이 들어있는데, 사용자에 관한 정보나 권한 등이 포함될 수 있다.
Registered Claims
- JWT 표준에 정의된 속성으로, 이미 예약되어 있는 클레임이다.
iss : 발행자(Issuer)
sub : 주제 (Subject)
aud : 대상자 (Audience)
exp : 만료 시간 (Expiration time)
nbf : 어느 시점 이후에만 유효한 토큰임을 나타냄 (Not before)
iat : 발행 시간 (Issued at)
jti : 토큰 ID (JWT ID)
Public Claims
- 임의로 정의할 수 있는 클레임으로, 충동을 피하기 위해 IANA JSON Web Token Registry에 등록하는 것이 좋다.
Private Claims
- 서버와 클라이언트 사이에 합의된 클레임으로, 서로간의 필요한 정보를 전달하는데 사용된다.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Signature
- JWT의 보안을 강화하는 부분으로, Header, Payload, 서버의 비밀키를 사용하여 서버에서 생성된 디지털 서명이다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
JWT 인증 과정
- 사용자는 사용자 이름과 비밀번호를 이용하여 로그인을 요청한다.
- 서버는 제공된 사용자 이름과 비밀번호를 검증한 후 JWT를 생성한다.
- 서버는 생성된 JWT를 클라이언트에 반환하고, 클라이어언트는 이 JWT를 저장한다.
- 이후 클라이언트가 서버에 데이터를 요청할 때마다, JWT를 HTTP 요청 헤더의
Authorization 필드에 포함시켜 보낸다.
- 서버는 요청이 도착하면 JWT의 서명을 확인하여 토큰을 검증하고, 유효기간 등의 클레임을 검사하여 유효하지 않다면 요청을 거부한다.
- JWT가 유효하다면, 서버는 해당 사용자의 권한을 바탕으로 요청된 데이터나 서비스를 제공한다.
Access Token 만료 시
Access Token이 만료되면, 클리이언트는 저장해 둔 Refresh Token을 사용하여 새로운 Access Token을 요청할 수 있다. 서버는 Refresh Token을 검증하고, 새로운 Access Token을 발급한다.
JWT의 장점
- 클라이언트에 의해 저장되며, 서버는 이를 위한 별도의 세션 저장소를 유지할 필요가 없다.
- Signature 암호화를 통해 민감한 데이터를 안전하게 전송할 수 있다.
- API 서버와 다른 도메인에 있는 클라이언트 간에도 쉽게 인증을 구현할 수 있다.
JWT의 단점
- Base64 인코딩을 통해 정보를 전달하므로, 일반적인 세션 ID에 비해 데이터 크기가 크다.
- JWT는 중요한 데이터는 암호화되지 않기 때문에 민감 정보를 저장할 수 없다.
- 만약 Access Token이 유출되면, 해당 토큰의 만료 시간까지 악의적인 사용이 가능하다.