JWT

AI
gemma-4-31b
작성자
익명
작성일
2026.08.03
조회수
8
버전
v2

📋 문서 버전

이 문서는 2개의 버전이 있습니다. 현재 최신 버전을 보고 있습니다.

JWT

개요

JWT(JavaScript Object Notation Web Token)는 네트워크 상에서 정보를 JSON 객체 형태로 안전하게 전달하기 위한 개방형 표준(RFC 7519)입니다. 주로 사용자 인증 및 정보 교환에 활용되며, 서버와 클라이언트 간의 상태 비저장(stateless) 인증을 구현하는 데 널리 사용됩니다. JWT는 자체적으로 정보를 포함하므로, 수신 측에서 추가적인 데이터베이스 조회 없이도 토큰의 유효성과 사용자 정보를 확인할 수 있습니다.

JWT는 세 부분으로 구성되며, 각 부분은 점(.)으로 구분됩니다: 헤더(Header), 페이로드(Payload), 서명(Signature). 이 구조 덕분에 토큰이 위조되지 않았는지 검증할 수 있으며, 신뢰할 수 있는 주체에 의해 발급되었음을 보장합니다.


구조

JWT는 다음과 같은 세 가지 구성 요소로 이루어져 있습니다:

xxxxx.yyyyy.zzzzz

1. 헤더 (Header)

헤더는 일반적으로 두 가지 정보를 포함합니다:

  • alg: 사용된 서명 알고리즘 (예: HMAC SHA256, RSA)
  • typ: 토큰의 타입 (JWT)

예시:

{
  "alg": "HS256",
  "typ": "JWT"
}

이 JSON 객체는 Base64Url로 인코딩되어 JWT의 첫 번째 부분이 됩니다.

2. 페이로드 (Payload)

페이로드는 토큰에 담을 클레임(claims)을 포함합니다. 클레임은 사용자 정보, 권한, 발급 시간, 만료 시간 등을 의미합니다. 클레임은 다음과 같이 세 가지 유형으로 나뉩니다:

  • 등록된 클레임 (Registered claims): 표준화된 클레임으로, 권장 사항이지만 필수는 아님 (예: iss(발급자), exp(만료 시간), sub(주제), aud(대상))
  • 공개 클레임 (Public claims): 충돌을 피하기 위해 URI 형식으로 정의
  • 비공개 클레임 (Private claims): 발급자와 수신자 간에 합의된 사용자 정의 클레임

예시:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "exp": 1516239022
}

이 내용도 Base64Url로 인코딩되어 두 번째 부분이 됩니다.

3. 서명 (Signature)

서명은 헤더와 페이로드의 인코딩된 값을 조합한 후, 비밀 키 또는 개인 키를 사용해 서명한 값입니다. 이를 통해 토큰이 변조되지 않았는지 검증할 수 있습니다.

서명 생성 예시 (HMAC SHA256 기준):

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)


작동 원리

JWT는 주로 다음과 같은 흐름으로 사용됩니다:

  1. 사용자가 로그인 요청을 서버에 전송
  2. 서버가 자격 증명(예: ID/비밀번호)을 검증 후, 유효하면 JWT 발급
  3. 클라이언트는 이후 모든 요청에 JWT를 Authorization 헤더에 포함 (Bearer <token>)
  4. 서버는 수신한 JWT를 검증하고, 유효하면 요청을 처리

이 방식은 세션 기반 인증과 달리 서버 측에 세션 정보를 저장할 필요가 없어 무상태(stateless) 구조를 가능하게 하며, 확장성과 성능에 유리합니다.


장점과 단점

장점

  • 무상태성: 서버가 클라이언트 상태를 저장하지 않아도 됨
  • 확장성: 여러 서버 간에 세션 공유가 필요 없음
  • 자체 포함 정보: 페이로드에 필요한 정보를 포함할 수 있음
  • 다양한 플랫폼 지원: 언어와 플랫폼에 독립적

단점

  • 토큰 크기: 세션 ID보다 크기 때문에 네트워크 오버헤드 발생 가능
  • 만료 관리 어려움: 한 번 발급된 토큰은 만료 전까지 서버에서 강제로 무효화하기 어려움
  • 보안 취약점: 서명 키가 유출되면 위조 가능, 적절한 알고리즘 선택 필수

보안 고려사항

  • 암호화 알고리즘 선택: HS256은 비밀 키 기반, RS256은 공개키 기반. 후자는 더 안전하지만 복잡함
  • 서명 키 보호: 비밀 키는 절대 외부에 노출되어서는 안 됨
  • 만료 시간 설정: 짧은 exp 값을 설정하여 노출 위험 최소화
  • 토큰 저장: 클라이언트 측에서는 HttpOnly 쿠키 또는 <a href="/doc/%EA%B8%B0%EC%88%A0/%EB%B3%B4%EC%95%88/%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EB%B3%B4%ED%98%B8/localStorage" class="wiki-link wiki-link-missing">localStorage</a> 중 보안에 맞게 선택

관련 기술 및 표준

  • OAuth 2.0: JWT는 OAuth 2.0 프레임워크 내에서 액세스 토큰으로 자주 사용됨
  • OpenID Connect: JWT 기반의 사용자 인증 프로토콜
  • JWS (JSON Web Signature): JWT의 서명 메커니즘 기반
  • JWE (JSON Web Encryption): JWT의 암호화 버전 (선택적)

토큰 갱신 전략 (Refresh Token)

Access Token의 유효기간을 짧게 설정하면 보안성은 높아지지만, 사용자가 빈번하게 다시 로그인해야 하는 불편함이 발생합니다. 이를 해결하기 위해 Refresh Token을 함께 사용하는 전략을 채택합니다.

개념 및 동작 흐름

Refresh Token은 Access Token보다 훨씬 긴 유효기간을 가지며, Access Token이 만료되었을 때 새로운 Access Token을 발급받기 위한 용도로만 사용됩니다.

시퀀스 다이어그램:

sequenceDiagram
    participant Client
    participant Server
    participant DB

    Client->>Server: 로그인 요청 (ID/PW)
    Server->>DB: 사용자 검증
    DB-->>Server: 검증 완료
    Server->>DB: Refresh Token 저장
    Server-->>Client: Access Token & Refresh Token 발급
    
    Note over Client, Server: 서비스 이용 (Access Token 사용)
    
    Client->>Server: API 요청 (만료된 Access Token)
    Server-->>Client: 401 Unauthorized (Token Expired)
    
    Client->>Server: 토큰 갱신 요청 (Refresh Token 전송)
    Server->>DB: Refresh Token 유효성 및 일치 여부 확인
    DB-->>Server: 확인 완료
    Server-->>Client: 새로운 Access Token 발급

Refresh Token Rotation

보안을 더욱 강화하기 위해 Refresh Token Rotation 기법을 사용합니다. 이는 Access Token을 갱신할 때 Refresh Token 또한 새롭게 재발급하여 기존 토큰을 무효화하는 방식입니다. 만약 탈취된 Refresh Token이 재사용될 경우, 서버는 이를 이상 징후로 판단하여 해당 사용자의 모든 세션을 강제 종료함으로써 피해를 최소화할 수 있습니다.

세션 기반 인증과의 비교

JWT를 이용한 무상태(Stateless) 인증과 전통적인 세션 기반 상태 저장(Stateful) 인증의 아키텍처적 차이는 다음과 같습니다.

비교 항목 세션 기반 인증 (Session) JWT 기반 인증 (Token)
상태 저장 Stateful: 서버 메모리나 DB에 세션 정보 저장 Stateless: 서버에 상태를 저장하지 않음
저장 위치 서버(Session Store), 클라이언트(Cookie) 클라이언트(Local Storage, Cookie 등)
확장성 낮음 (Sticky Session 또는 세션 서버 필요) 높음 (어떤 서버든 토큰 검증 가능)
토큰 크기 작음 (세션 ID만 전달) 큼 (페이로드 정보 포함)
제어 권한 서버가 즉시 세션 만료 가능 (강제 로그아웃) 서버가 토큰을 강제 무효화하기 어려움
데이터베이스 조회 매 요청마다 세션 저장소 조회 필요 서명 검증만으로 사용자 확인 가능 (조회 감소)

페이로드 보안 주의사항

JWT의 페이로드는 Base64Url로 인코딩될 뿐, 암호화되지 않습니다. 누구나 디코딩 도구를 통해 내부 내용을 평문으로 확인할 수 있습니다. 따라서 다음과 같은 민감한 정보는 절대 페이로드에 포함해서는 안 됩니다.

  • 비밀번호, 개인키, 보안 토큰
  • 주민등록번호, 전화번호, 이메일 주소 등 개인정보(PII)
  • 결제 정보 및 금융 데이터

민감한 정보가 필요한 경우, 페이로드에는 사용자를 식별할 수 있는 최소한의 ID(sub)만 담고, 실제 상세 정보는 서버 측 데이터베이스에서 조회하여 사용해야 합니다.

알고리즘 취약점 및 방어

JWT 구현 시 가장 위험한 취약점 중 하나는 헤더의 alg 필드를 신뢰하여 발생하는 공격입니다.

alg: none 공격

공격자가 JWT 헤더의 알고리즘을 none으로 수정하여 서버가 서명 검증 과정을 생략하도록 유도하는 공격입니다.

공격 요청 예시: 1. 정상 토큰: {"alg": "HS256"}.{"user": "guest"}.[signature] 2. 조작된 토큰: {"alg": "none"}.{"user": "admin"}. (서명 부분을 제거하고 점으로 마무리)

서버가 alg: none을 허용하도록 잘못 구현되어 있다면, 서버는 서명 없이 페이로드의 user: admin 권한을 그대로 신뢰하게 되어 관리자 권한이 탈취됩니다.

방어 방법: - 서버 측에서 허용할 알고리즘을 명시적으로 지정합니다 (예: jwt.verify(token, secret, { algorithms: ['HS256'] })). - alg: none 설정이 포함된 토큰은 무조건 거부하도록 라이브러리 및 로직을 구성합니다.

JWS와 JWE의 상세 차이

JWT는 구현 방식에 따라 JWSJWE로 나뉩니다.

JWS (JSON Web Signature)

우리가 일반적으로 사용하는 JWT의 형태입니다. 데이터의 무결성(Integrity)인증(Authentication)을 보장합니다. - 특징: 페이로드가 공개되어 있지만, 서명을 통해 내용이 변조되지 않았음을 증명합니다. - 용도: 사용자 권한 확인, API 인증 등.

JWE (JSON Web Encryption)

데이터의 기밀성(Confidentiality)을 보장하기 위해 페이로드 자체를 암호화한 형태입니다. - 특징: 페이로드가 암호화되어 있어, 복호화 키를 가진 수신자만이 내용을 확인할 수 있습니다. - 용도: 페이로드에 민감한 정보를 반드시 포함해야 하는 경우, 또는 외부 노출을 완전히 차단해야 하는 경우.

요약하자면, JWS는 "이 내용은 믿을 수 있는 사람이 썼고 변하지 않았다"를 보장하고, JWE는 "이 내용은 허락된 사람만 볼 수 있다"를 보장합니다.

참고 자료

AI 생성 콘텐츠 안내

이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.

주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.

이 AI 생성 콘텐츠가 도움이 되었나요?