본문 바로가기
백엔드

[개념] JWT(JSON Web Token)에 대해

by zzingni 2025. 7. 7.

JWT의 정의


JSON 웹 토큰(JWT)은 JSON 객체 형태로 당사자 간에 정보를 안전하게 전송하는 간결하고 독립적인 방식을 정의하는 개방형 표준( RFC 7519 )이다. 이 정보는 디지털 서명되어 있으므로 검증 및 신뢰가 가능하다. JWT는 비밀 키( HMAC 알고리즘 사용) 또는 RSA 또는 ECDSA를 사용하는 공개/개인 키 쌍을 사용하여 서명할 수 있다.
 
JWT는 당사자 간 비밀 유지를 위해 암호화될 수 있지만, 여기서는 서명된 토큰 에 초점을 맞춘다. 서명된 토큰은 토큰에 포함된 클레임의 무결성을 검증할 수 있는 반면, 암호화된 토큰은 다른 당사자에게 해당 클레임을 숨긴다. 공개 키/개인 키 쌍을 사용하여 토큰에 서명하는 경우, 서명은 개인 키를 보유한 당사자만이 토큰에 서명했음을 증명한다.
 

JWT가 필요한 이유 (Session 기반 인증과의 차이점)


웹 애플리케이션에서 사용자 인증을 구현할 때 가장 흔히 떠올리는 방식은 세션(Session) 기반 인증이다. 그런데 왜 많은 개발자들이 JWT를 사용하고 있을까? 두 방식을 비교하면서 그 이유를 살펴보자.
 

Session 기반 인증 방식

 
 

  • 사용자가 로그인하면 서버는 인증 정보를 바탕으로 세션을 생성하고, 세션 ID를 브라우저의 쿠키에 저장한다.
  • 사용자는 이후 요청마다 쿠키에 포함된 세션 ID를 함께 보내고, 서버는 세션 ID로 저장된 정보를 찾아 인증을 처리한다.
  • 서버는 로그인한 사용자마다 세션 정보를 메모리나 DB에 유지해야 한다.

 

장점

 

  • 구현이 간단하고, 서버 쪽에서 세션을 관리하므로 보안이 비교적 강함
  • 세션 무효화가 쉬움 (ex. 서버에서 세션 삭제)

단점
 
 

  • 서버가 사용자 수만큼 세션을 저장해야 하므로 확장성이 떨어짐
  • 분산 서버 환경(로드밸런싱)에서는 세션 공유를 위해 별도 설정이 필요 (세션 클러스터링, Redis 사용 등)

 
 

JWT 기반 인증 방식

 
 

  • 로그인 성공 시 서버는 사용자 정보를 담은 JWT를 발급해서 클라이언트에게 전달한다.
  • 클라이언트는 JWT를 로컬 스토리지나 쿠키에 저장하고, 이후 요청의 Authorization 헤더에 JWT를 담아 전송한다.
  • 서버는 해당 JWT의 서명을 검증하고, 요청을 처리한다. 세션 저장이 필요 없다.

 

장점
 

  • 서버는 세션을 저장할 필요가 없어 무상태(Stateless) 구조
  • 서버 간 공유 없이도 인증 가능 → 분산 환경에서 유리
  • 다양한 플랫폼(웹, 모바일 등)에서 동일하게 사용 가능

 

단점

 

  • 토큰 자체에 정보가 들어있기 때문에 탈취 시 위험 (HTTPS 필수)
  • 서버에서 토큰을 강제로 무효화하기 어려움
  • 만료 전까지는 유효하므로 보안 사고 시 대응이 늦어질 수 있음

 
 

JWT 구조


 

JWT 구조 예시 (출처: BizSpring)

 
JWT(JSON Web Token)는 세 부분으로 구성된 문자열이다. 이 세 부분은 점(.)으로 구분되며, 각각 Header, Payload, Signature 역할을 한다.
 

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikdlbnl1cyIsImlhdCI6MTUxNjIzOTAyMn0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

 

Header

 
JWT의 헤더는 토큰의 타입서명에 사용할 알고리즘 정보를 담고 있다.
 

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

 

  • alg: 서명 알고리즘 (예: HS256, RS256 등)
  • typ: 토큰의 타입. 보통 "JWT"로 고정

이 내용은 Base64Url 인코딩되어 JWT의 첫 번째 부분이 된다.
 
 

Payload (페이로드)

 
페이로드는 실제 사용자 정보(클레임)가 담기는 부분이다. 이 정보는 암호화되지 않기 때문에 누구나 디코딩할 수 있다.
 

{
  "sub": "1234567890",
  "name": "Genyus",
  "admin": true,
  "iat": 1516239022
}

 
 

  • sub(Subject): 사용자 ID
  • name: 사용자 이름
  • admin: 사용자 권한
  • iat(Issued At): 발급 시간

 
JWT에서 사용할 수 있는 클레임은 다음과 같이 나뉜다:

등록 클레임 (Registered)iss, exp, sub, aud, nbf, iat, jti 등
공개 클레임 (Public)사용자 정의 가능, 충돌 피하기 위해 URI 명시 권장
비공개 클레임 (Private)발급자-수신자 간의 커스텀 정보

 
 

Signature (서명)

 
서명은 토큰의 위변조를 방지하기 위해 사용된다.
 

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

 
즉, 헤더와 페이로드를 인코딩한 후, 비밀 키로 서명한 값이 Signature다.
서버는 이 서명을 확인하여 토큰의 무결성을 검증한다.
 
 

JWT 발급 / 검증 예제 


 

1. 로그인시 JWT 발급

사용자가 ID/PW로 로그인에 성공하면, 서버는 해당 사용자의 정보를 기반으로 JWT를 생성해서 응답으로 보낸다.
 

// Node.js 예시 (jsonwebtoken 라이브러리 사용)
const jwt = require('jsonwebtoken');

const user = { id: 1, name: 'Genyus' };
const secret = 'my_secret_key';
const token = jwt.sign(user, secret, { expiresIn: '1h' });

console.log(token);

 

// Spring Boot 예시 (jjwt 사용)
String token = Jwts.builder()
    .setSubject("Genyus")
    .setIssuedAt(new Date())
    .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1시간
    .signWith(SignatureAlgorithm.HS256, "my_secret_key")
    .compact();

 
 

2. 클라이언트 저장 및 사용

 

  • 발급된 토큰은 클라이언트 측에서 로컬 스토리지, 또는 쿠키에 저장한다.
  • 이후 요청 시 Authorization 헤더에 Bearer <token> 형식으로 보낸다.

 

GET /api/userinfo HTTP/1.1
Authorization: Bearer eyJhbGciOi...

 
 

3. 서버에서 JWT 검증

서버는 요청 시 받은 JWT의 서명을 검증하고, 유효하면 해당 사용자로 인식한다.

const decoded = jwt.verify(token, secret);
console.log(decoded); // { id: 1, name: 'Genyus', iat: ..., exp: ... }

 

Claims claims = Jwts.parser()
    .setSigningKey("my_secret_key")
    .parseClaimsJws(token)
    .getBody();

System.out.println(claims.getSubject()); // Genyus

 
 

보안 고려사항


JWT는 편리하지만, 민감한 정보를 다루기 때문에 반드시 보안에 신경 써야 한다.
 

HTTPS 필수

 
 

  • JWT는 Payload가 암호화되지 않는다.
  • Base64 인코딩된 정보는 누구나 디코딩 가능하므로, HTTPS 없이 전송하면 탈취 위험이 크다.

 

토큰 만료시간 설정

 
 

  • exp 클레임을 활용해 토큰의 만료 시간을 짧게 설정하자.
  • 예: 15분~1시간
  • 짧은 토큰 + 리프레시 토큰 구조를 사용하는 게 일반적이다.

 
 

리프레시 토큰 사용

 
 

  • 액세스 토큰은 짧게, 리프레시 토큰은 길게 유효하도록 설정
  • 리프레시 토큰으로 만료된 액세스 토큰을 갱신

 

토큰 탈취 시 대응

 
 
 

  • 로그아웃 처리가 어렵다
  • 토큰 탈취 시 만료되기 전까지는 계속 유효

이를 보완하기 위해 다음 전략을 사용할 수 있다.
 
 

전략 설명
짧은 만료 시간액세스 토큰 자체를 자주 바꾼다
리프레시 토큰 블랙리스트서버에서 리프레시 토큰만 저장하고 무효화 가능하게 한다
Redis나 DB로 블랙리스트 관리JWT 무효화 처리를 위한 블랙리스트 테이블 운영

 

 

기타 고려사항

  
 

  • JWT에 민감한 정보(password, 주민번호 등)는 절대 포함하지 말 것
  • 서명 키는 외부에 노출되지 않도록 .env 등에서 관리
  • 필요 시 RS256 (비대칭키 방식) 도 검토

 
 
 

REFRENCE


 

JSON Web Token Introduction - jwt.io

Learn about JSON Web Tokens, what are they, how they work, when and why you should use them.

jwt.io