JWT(JSON Web Token)란?
이 글의 목차19개
- 📌 JWT란?
- 🧩 JWT의 등장 배경은 무엇일까?
- 🌐 Stateless란 무엇일까?
- ✅ 상태를 가진다 = 서버가 기억한다 (Stateful)
- ❌ Stateless = 서버가 기억 안 한다
- 🧐 간단한 비유!
- ✅ Stateful한 놀이동산
- ❌ Stateless한 놀이동산
- 🔁 Stateful vs Stateless 비교
- ✨ Stateless의 장점
- ⚠️ Stateless의 단점 또는 고려사항
- 🧱 JWT는 어떻게 생겼을까?
- 🔐 JWT는 어떻게 만들어지고, 동작할까?
- ✅ 1. 로그인 시 토큰 발급
- ✅ 2. 클라이언트는 매 요청마다 JWT를 첨부
- ✅ 3. 서버는 Signature를 검증해서 위조 여부 확인
- 🧠 JWT의 암호화 방식 (Signature)
- ⚠️ JWT를 사용할 때 주의할 점
- ✅ 정리하며
📌 JWT란?
JWT는 **JSON Web Token**의 줄임말로, JSON 기반의 가볍고 독립적인 인증 정보 전달 방식이다.
JWT와 서버의 관계를 놀이공원에 비교하면 쉽게 이해할 수 있다.
✅ 놀이공원에서는 티켓을 가지고 있어야 놀이기구에 탑승할 수 있다.
- 놀이공원에서 발급한 티켓 -> JWT
- 놀이기구 탑승 -> 클라이언트가 서버에 보내는 요청
즉, 서버는 클라이언트가 인증(로그인)되면 JWT토큰을 만들어서 발급하고,
매 요청마다 Header에 JWT를 첨부하게 하여 사용자의 인증을 검증할 수 있다.
🧩 JWT의 등장 배경은 무엇일까?
전통적인 인증 방식인 Session-Cookie 기반 인증 흐름은 다음과 같다.
- 로그인 → 서버가 세션 생성
- 세션 ID를 클라이언트에 쿠키로 전달
- 클라이언트가 세션 ID를 매 요청에 포함
- 서버는 DB나 메모리에서 세션을 조회
하지만 이 방식은…
- 서버가 세션 상태를 기억해야 한다.
- 서버 간 세션 공유가 필요하다.
- 메모리 사용 증가 등 고려할 부분이 많다.
JWT는 이런 문제를 해결하기 위해 개발된
Stateless 인증 방식!!
- 토큰 안에 정보를 넣고, 서버는 토큰만 검증
- 세션 저장소가 필요 없어지고, 확장성이 증가
🌐 Stateless란 무엇일까?
JWT를 설명할 때 말하는 **Stateless(상태 없음)**이란 건 정확히 무슨 뜻일까?
✅ 상태를 가진다 = 서버가 기억한다 (Stateful)
전통적인 Session 기반 인증은 Stateful 방식이다.
- 사용자가 로그인하면 서버가 세션을 만들고,
- 사용자 정보를 서버 메모리나 DB에 저장
- 클라이언트는 세션 ID만 들고 다니고,
- 서버는 매 요청마다 이 ID가 누구인지를 확인!
이 방식은 서버가 사용자의 상태(인증 정보 등)를 계속 기억하고 있어야 한다.
❌ Stateless = 서버가 기억 안 한다
JWT 인증은 Stateless 방식이다.
- 로그인 시 JWT 발급 (사용자 정보와 만료시간을 토큰 안에 포함)
- 서버는 그걸 기억하지 않고 클라이언트에게 넘김
- 이후 요청에서는 클라이언트가 JWT를 매번 보내고,
- 서버는 그냥 검증만 한다 (서명 확인 → OK or 거절)
✅ 서버는 토큰을 따로 저장하지도 않고, 사용자 상태를 기억하지도 않는다.
✅ 오직 토큰만 믿고 동작한다 → 그래서 Stateless
🧐 간단한 비유!
✅ Stateful한 놀이동산
손님은 대기번호가 적힌 번호표만 가지고 있고, 손님에 대한 정보는 모두 놀이공원이 가지고 있다.
- 직원은 손님의 번호표를 받는다.
- 직원은 컴퓨터에 손님의 번호표를 검색한다.
- 이름, 생년월일, 이용권 정보 등을 확인한다.
Stateful한 놀이동산은 DB에 손님의 정보가 모두 저장되어 있어야 한다.
❌ Stateless한 놀이동산
손님은 자신에 대한 정보가 모두 담긴 티켓을 가지고 있다. 티켓에는 손님의 정보와 QR코드가 그려져있다.
- 직원은 손님의 QR코드를 확인한다.
- QR코드가 정상일 시에 손님의 티켓에 적힌 정보를 신뢰한다.
Stateless한 놀이동산은 QR코드만 확인하면 된다.
🔁 Stateful vs Stateless 비교
| 항목 | Session (Stateful) | JWT (Stateless) |
|---|---|---|
| 서버 상태 기억 | O (세션 저장) | ❌ (기억 안 함) |
| 서버 저장소 | 필요함 (메모리/DB 등) | 필요 없음 |
| 인증 방식 | 세션 ID → 서버가 조회 | 토큰 자체가 인증 정보 |
| 확장성 | 서버 간 세션 공유 필요 | 서버 수평 확장 용이 |
| 보안 리스크 | 세션 탈취 | 토큰 탈취 (따라서 HTTPS 필수) |
✨ Stateless의 장점
- 서버가 가볍고 확장성이 좋다
- 서버 재시작에도 인증 상태가 유지된다 (세션처럼 날아가지 않음)
- 마이크로서비스 구조에서 통합 인증 토큰으로 활용 가능
⚠️ Stateless의 단점 또는 고려사항
- 토큰 만료/갱신 전략 필요
- 서버가 토큰을 저장하지 않기 때문에 강제 로그아웃 불가
- 토큰 탈취 시 막을 방법이 없음 (재발급 전에 차단 어렵다)
🧱 JWT는 어떻게 생겼을까?
JWT는 점(.)으로 구분된 세 부분으로 구성된다:
[Header].[Payload].[Signature]
예시:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkxFRSIsImlhdCI6MTYyMDAwMDAwMH0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
| 파트 | 설명 |
|---|---|
| Header | 어떤 알고리즘을 사용할 건지 (alg, typ) |
| Payload | 사용자 정보, 클레임(Claim) 등 실제 내용 |
| Signature | 위 2개를 기반으로 암호화된 서명 |
✅ 이 세 부분은 Base64로 인코딩된 문자열이며,
헤더와 페이로드는 디코딩하면 누구나 읽을 수 있다!
🔐 JWT는 어떻게 만들어지고, 동작할까?
✅ 1. 로그인 시 토큰 발급
Header:
{
"alg": "HS256",
"typ": "JWT"
}
Payload:
{
"sub": "user123",
"name": "LEE",
"exp": 1718000000
}
서버는 이 데이터를 바탕으로 Signature를 생성하고, 토큰을 클라이언트에 넘겨준다.
✅ 2. 클라이언트는 매 요청마다 JWT를 첨부
Authorization: Bearer eyJhbGciOiJIUzI1...
Authorization 헤더에 Bearer 타입으로 넣는 게 표준 방식!
✅ 3. 서버는 Signature를 검증해서 위조 여부 확인
- 서명이 유효하면 Payload 안의 정보를 바탕으로 인증 성공
- 만료 시간(
exp) 확인, 토큰 조작 여부 검사 등
🧠 JWT의 암호화 방식 (Signature)
JWT 자체는 암호화된 게 아니라 인코딩(Base64) 되어 있다.
핵심은 Signature 생성에 있다.
서버는 secret key를 사용해서 Header + Payload를 기반으로 서명을 만든다:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
✅ 이 서명(Signature)이 위조 방지의 핵심
※ alg는 HMAC(SHA256), RSA, ES256 등 다양하게 선택 가능
⚠️ JWT를 사용할 때 주의할 점
| 위험 요소 | 설명 |
|---|---|
| ❌ 민감 정보 포함 | Payload는 디코딩 가능 → 개인정보 노출 주의 |
| ❌ 토큰 탈취 | 탈취되면 누구나 인증된 척 가능 → HTTPS 필수 |
| ⌛ 만료 시간 관리 | exp, iat, nbf 등의 클레임을 잘 설정해야 보안 유지 |
| 🔄 토큰 재발급 | 만료된 토큰에 대한 리프레시 전략 필요 (refresh token 패턴) |
| ❗ 알고리즘 none 취약점 | alg: none 허용하면 서명 없이 통과 → 절대 막아야 함 |
✅ 정리하며
- JWT는 인증 정보를 담은 디지털 토큰
- 세션 기반 인증의 단점을 보완해 등장
- 구조는 Header + Payload + Signature
- Base64 인코딩이고, 서명을 통해 위조 방지
- 민감 정보는 넣지 말고, 항상 HTTPS를 사용해야 함