JWT (JSON Web Token)란?
JWT는 JSON 형식으로 데이터를 안전하게 전송하기 위해 사용되는 토큰 기반 인증 방식입니다.
주로 웹 애플리케이션과 API 인증에서 사용되며, 클라이언트-서버 간 상태 정보를 간단하고 안전하게 유지할 수 있습니다.
JWT의 구조
JWT는 .
(점)으로 구분된 3개의 부분으로 구성됩니다:
Header.Payload.Signature
JWT의 타입과 서명 알고리즘을 정의합니다.
{
"alg": "HS256", // 서명 알고리즘 (예: HMAC SHA-256)
"typ": "JWT" // 토큰 타입
}
2. Payload (페이로드)
인코딩된 사용자 데이터(Claim)를 포함하며, 토큰의 주요 정보가 여기에 저장됩니다.
페이로드에는 등록된 클레임(Registered Claims), 공개 클레임(Public Claims), 비공개 클레임(Private Claims)이 포함될 수 있습니다.
{
"sub": "1234567890", // 사용자 ID
"name": "John Doe", // 사용자 이름
"iat": 1516239022 // 토큰 발급 시간 (Issued At)
}
- 등록된 클레임 (Registered Claims): 표준화된 키 값 (
sub
, iat
, exp
등).
- 공개 클레임 (Public Claims): 사용자가 정의한 공개 데이터.
- 비공개 클레임 (Private Claims): 클라이언트-서버 간 비공개 데이터.
3. Signature (서명)
헤더와 페이로드를 특정 알고리즘으로 해시한 후, 비밀키로 서명하여 생성됩니다.
서명은 토큰이 변조되지 않았음을 검증합니다.
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload), secret
)
JWT의 작동 원리
-
클라이언트 인증
- 사용자가 로그인하면 서버는 사용자의 정보를 기반으로 JWT를 생성합니다.
- 생성된 JWT는 클라이언트에 전달됩니다.
-
JWT 저장
- 클라이언트는 JWT를 로컬 스토리지 또는 쿠키에 저장합니다.
-
서버 인증 및 요청 처리
JWT의 장점
-
상태를 저장하지 않음 (Stateless)
- 서버는 토큰만 검증하면 되므로, 별도의 세션 저장소가 필요 없습니다.
-
확장성
- 분산 시스템에서 여러 서버가 JWT를 공유할 수 있어 확장성이 뛰어납니다.
-
유연성
- 다양한 클레임 정보를 담을 수 있어, 사용자 및 시스템 요구에 맞게 커스터마이징이 가능합니다.
-
쉽고 표준화된 형식
- JSON 기반으로 설계되어 다른 시스템과 쉽게 연동할 수 있습니다.
JWT의 단점 및 주의사항
-
크기 문제
- JWT는 자체적으로 데이터를 포함하므로 크기가 커질 수 있습니다.
-
보안 문제
- JWT 자체는 암호화되지 않으므로, 민감한 정보를 페이로드에 포함하면 안 됩니다.
- HTTP 요청 시 HTTPS를 사용해 전송을 보호해야 합니다.
-
토큰 무효화 어려움
- JWT는 서버에서 상태를 유지하지 않으므로, 특정 토큰을 강제로 무효화하기 어렵습니다.
(이를 해결하려면 블랙리스트를 사용하거나 짧은 만료 시간을 설정해야 함.)
-
만료 관리
- 토큰 만료 시간(
exp
)을 설정하지 않으면 보안 취약점이 생길 수 있습니다.
JWT의 사용 사례
-
사용자 인증
- 로그인 후 서버가 JWT를 발급하여 사용자를 인증.
- 이후 모든 요청에서 JWT를 사용해 인증 및 권한 확인.
-
API 인증
- API 요청 시, JWT로 클라이언트를 인증.
(예: OAuth 2.0)
-
마이크로서비스 통신
- 마이크로서비스 간 요청을 인증하기 위해 JWT를 사용.
JWT의 주요 옵션
JWT를 구성할 때 사용하는 옵션은 다음과 같습니다.
옵션 | 설명 |
---|
alg | 서명 알고리즘 (예: HS256, RS256) |
iat | 토큰 발급 시간 (Issued At) |
exp | 토큰 만료 시간 (Expiration Time) |
aud | 대상자 (Audience) |
iss | 발급자 (Issuer) |
sub | 주제 (Subject) |
JWT와 세션 기반 인증의 차이점
특징 | JWT | 세션 기반 인증 |
---|
저장 방식 | 클라이언트가 토큰을 저장 | 서버가 세션 데이터를 저장 |
확장성 | 분산 시스템에서 유리 | 확장성이 제한적 |
상태 관리 | 상태를 저장하지 않음 (Stateless) | 서버가 상태를 유지 |
무효화 | 복잡 (서버 상태 없음) | 쉽게 무효화 가능 (서버에서 세션 삭제) |
데이터 크기 | 비교적 크기 큼 | 비교적 크기 작음 |
Access Token과 Refresh Token의 역할
Access Token
- 역할: 리소스 서버(API 서버)에 요청을 보낼 때 사용.
- 특징:
- 상대적으로 짧은 유효 기간을 가짐. (예: 5분 ~ 1시간)
- 만료되기 전까지 리소스 서버에서 인증 및 권한 검증에 사용.
- 사용자 정보나 권한에 대한 데이터를 포함.
Refresh Token
- 역할: Access Token이 만료되었을 때, 새로운 Access Token을 발급받을 때 사용.
- 특징:
- 상대적으로 긴 유효 기간을 가짐. (예: 1주 ~ 1개월 이상)
- 클라이언트가 인증 서버와 통신할 때만 사용되며, 리소스 서버에 직접 사용되지 않음.
- 일반적으로 서버에서만 저장하거나 안전한 클라이언트 저장소에 보관.
Access Token과 Refresh Token을 나누는 이유**
1. 보안성 강화
2. 사용자 경험 개선
3. 토큰 관리를 체계적으로 수행
토큰 분리의 단점과 대책
단점
- 구현 복잡성 증가:
- Access Token과 Refresh Token의 생성, 검증, 갱신 로직을 추가로 개발해야 함.
- Refresh Token 탈취 시 위험:
- Refresh Token을 탈취하면 장기간 Access Token을 재발급받을 수 있는 위험이 있음.
대책
- Refresh Token 보호
- 서버에서만 저장하거나, 클라이언트의 안전한 저장소(예: Secure Cookie, Secure Storage) 사용.
- 짧은 유효 기간과 블랙리스트 사용
- Refresh Token의 유효 기간도 짧게 설정하고, 유출 시 블랙리스트 처리로 즉시 차단.
요약
- Access Token과 Refresh Token을 분리하면 보안성을 강화하면서도 사용자 경험을 개선할 수 있습니다.
- Access Token은 짧은 유효 기간으로 사용되며, Refresh Token은 새로운 Access Token을 발급하는 데 사용됩니다.
- 안전한 저장소와 유효 기간 설정 등을 통해 Refresh Token 관리에 주의해야 합니다.
추가 학습 자료