JWT

Yong Lee·2025년 8월 11일

JSON Web Token

1. JWT란?

JSON 포맷을 이용해 정보를 안전하게 전달하기 위한 토큰 기반 인증 방식입니다.
주로 서버와 클라이언트 간 인증 정보를 주고받을 때 사용됩니다.

2. JWT를 쓰는 이유이자 강점

  • 무상태(Stateless) 인증 가능
    • 무상태란? 클라이언트에서 보낸 데이터를 서버 측에서 따로 저장하지 않는다는 소리
    • 서버에서는 JWT 암호를 복호화하는 작업을 하여 데이터를 추출
    • 데이터가 토큰 안에 있어 DB 조회 x -> 빠른 인증 처리
    • Restful Api에 적합: 무상태성을 유지하는 API에 유리
  • 확장성 좋음
    • 서버가 여러 대여도 서명(signature)를 알고 있으면 다른 서버에서도 복호화하여 사용가능
  • 자체 검증 가능
    • 토큰에 서명이 포함되어 있어 위변조 여부 쉽게 검사 가능
    • 서명은 탈취 절대 불가능하게 할 것!
  • 다양한 클라이언트 환경 지원
    • 웹, 모바일, API 등 여러 환경에서 동일하게 사용 가능
  • 다양한 클레임 포함 가능: 사용자 정보, 권한, 만료시간 등 넣을 수 있음

3. 약점

  • 토큰 탈취 위험: 탈취되면 만료 전까지 악용 가능
  • 토큰 무효화 어려움: 서버가 상태를 관리하지 않아 특정 토큰을 강제로 만료시키기 힘듦
  • 토큰 크기 큼: 쿠키나 헤더에 많이 쓰면 네트워크 부담 증가
  • 보안 주의 필요: HTTPS 사용 필수, 서명 키 관리 중요
  • 갱신 관리 번거로움: 보통 리프레시 토큰 별도 관리 필요

그럼 이 약점들을 어떻게 극복해야할까?

  1. 토큰 탈취 위험 & 보안 강화
  • HTTPS 사용 필수
  • HttpOnly, Secure 쿠키 사용
    • JWT를 클라이언트 저장소(LocalStorage 등)가 아니라, 브라우저 쿠키에 HttpOnly 및 Secure 옵션을 줘서 자바스크립트로 접근 불가능하게 만들면 XSS 공격 위험 감소.
  • 짧은 액세스 토큰 수명
    • 액세스 토큰 만료 시간을 짧게 설정해서 탈취 후 악용 가능 시간을 최소화.
  1. 토큰 무효화 어려움 & 갱신 관리
  • 리프레시 토큰 사용

    • 위에서 엑세스 토큰 수명을 짧게 하라고 했다. 그런데 매번 인증하려고 유저가 로그인을 계속해야한다면? UX적으로 최악일 것이다.
    • 그렇기 때문에 액세스 토큰과 별개로 상대적으로 만료 기간이 긴 리프레시 토큰을 발급하고, 액세스 토큰이 만료되면 리프레시 토큰으로 재발급 받게 함.
    • 리프레시 토큰은 서버에서 관리(저장 및 검증)해 강제 만료 가능.
  • 블랙리스트(Blacklist) 구현

    • 탈취된 토큰이나 로그아웃된 토큰을 서버에서 별도 저장소에 기록해서, 토큰 검증 시 블랙리스트에 있으면 거부.
    • 다만 서버 상태 관리가 필요해서 무상태 JWT의 장점이 줄어들 수 있으므로 일반적인 RDB에 저장하는 것보단 Redis같은 곳에 저장해보는것도 좋을 것 같다.
  • 토큰 버전 관리

    • 유저 데이터에 토큰 버전을 저장해, 서버에서 현재 토큰 버전과 일치하지 않으면 무효 처리하는 방법.
  1. 토큰 크기 문제 완화
  • 페이로드 최소화
    • 토큰에 꼭 필요한 정보만 담고, 불필요한 클레임은 제거해서 크기 축소.
  • 압축(Compression) 적용
    • JWT에 압축 알고리즘을 적용하는 방법도 있으나, 구현 복잡도가 올라감.
  1. 기타 보안 강화
  • 서명 키 주기적 교체
    • 비밀 키를 주기적으로 변경해서 오래된 키로 서명된 토큰을 무효화.
  • CORS 정책 강화
    • API 서버에 엄격한 CORS 설정으로 권한 없는 출처에서의 요청 차단.

4. JWT 외에 인증 방식

  • 세션 기반 인증 (Session + Cookie)
    • 서버가 세션 상태를 메모리/DB에 저장하고, 클라이언트는 세션 ID를 쿠키로 보냄
      → 서버가 상태를 유지해야 해서 확장성이 떨어짐
  • OAuth / OAuth2
    • 주로 제3자 인증 시 사용, 복잡하지만 권한 위임에 강점
  • API Key
    • 간단하지만 보안 취약점 많음
  • Basic Auth
    • 사용자명/비밀번호를 매 요청마다 전송, 보안에 취약함

5. JWT vs session 기반 인증

구분JWT세션 기반 인증
상태무상태 (stateless)상태 유지 (stateful)
서버 부담낮음세션 저장으로 부하 존재
확장성매우 좋음확장에 불리함
보안토큰 탈취 시 위험, 무효화 어려움서버에서 세션 만료 관리 가능
사용 환경SPA, 모바일, 마이크로서비스, API 인증 등에 주로 사용전통적인 웹사이트 로그인, 서버 렌더링 기반 앱에 적합

6. JWT의 구조

  • alg: 토큰을 서명하는데 사용할 알고리즘 종류 (예: HS256, RS256 등)
  • typ: 토큰 타입 (보통 "JWT"라고 명시)
    {
  	  "alg": "HS256",
	  "typ": "JWT"
     }

Payload

  • 실제 데이터(Claims)가 담기는 부분.
  • 등록된 클레임(Registered Claims)
    • JWT 표준에서 미리 정의한 예약된 키들이에요.
      주로 토큰 발급자, 만료시간, 대상자 등 토큰의 기본 정보입니다.
{
// 등록된 클레임 예시
  "iss": "auth.myapp.com",     // 토큰 발급자 (issuer)
  "sub": "user123",            // 토큰 주제 (subject), 주로 사용자 ID
  "aud": "myapp.com",          // 토큰 대상자 (audience)
  "exp": 1700000000,           // 토큰 만료시간 (expiration, Unix timestamp)
  "nbf": 1699990000,           // 토큰 사용 가능 시작 시간 (not before)
  "iat": 1699980000,           // 토큰 발행 시간 (issued at)
  "jti": "unique-token-id-123" // JWT 고유 ID (JWT ID)
}
  • 공개 클레임(Public Claims)

    • 표준에 정의된 것은 아니지만, 충돌 방지를 위해 IANA JSON Web Token Registry 같은 곳에 등록하거나, URL 형식으로 네임스페이스를 넣어 사용합니다.
  • 비공개 클레임(Private Claims)

    • 발급자와 소비자(서버, 클라이언트) 간에 약속된 임의의 키-값 쌍이에요.
{
  "userId": "123456",
  "isPremiumUser": true,
  "department": "engineering"
}

모든 클레임을 다 쓰면 이런 모습입니다.

{
  "iss": "auth.myapp.com",
  "sub": "user123",
  "aud": "myapp.com",
  "exp": 1700000000,
  "iat": 1699980000,
  "https://myapp.com/roles": ["admin", "editor"],
  "userId": "123456",
  "isPremiumUser": true
}

허나 다 쓸 필요 없습니다. 필요하다 느끼는 것만 적절히 쓰면 좋습니다.

Signature (서명)

  • 서버가 Header와 Payload를 비밀키(secret key)를 이용해 서명한 값이에요.
  • 서명을 만드는 과정 (예: HMAC SHA-256 알고리즘):
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key
)

7. JWT 생성 & 검증 흐름

  1. 서버가 Header와 Payload를 만들어서 Base64Url로 인코딩
  2. 인코딩된 Header와 Payload를 합쳐서 비밀키로 서명
  3. HEADER.PAYLOAD.SIGNATURE 형태의 토큰 발급
  4. 클라이언트가 토큰을 저장하고 요청 시마다 전달
  5. 서버가 토큰의 서명을 검증하고, Payload를 읽어 인증 처리

정리

부분내용역할
Header토큰 타입, 서명 알고리즘 정보서명 만들 때 사용되는 메타정보
Payload사용자 정보, 권한, 만료 시간 등실제 인증/인가에 필요한 데이터
SignatureHeader와 Payload를 비밀키로 서명토큰 변조 방지 및 신뢰성 확보
profile
오늘은 어떤 새로운 것이 나를 즐겁게 할까?

0개의 댓글