토큰 기반 인증(JWT) — HTTP부터 JWT까지 (5)
JWT(JSON Web Token)를 중심으로 한 토큰 기반 인증의 개념과 구조를 이해합니다. 세션 방식과의 차이, 보안 이슈, Refresh Token 도입까지 실무에 필요한 인증 전략을 정리한 글입니다.
토큰 기반 인증(JWT) — HTTP부터 JWT까지 (5)
토큰 기반 인증이란?
토큰 기반 인증은 서버가 사용자 상태를 저장하지 않고도 인증을 유지할 수 있도록 해주는 구조입니다.
가장 대표적인 방식으로 JWT (JSON Web Token)이 사용되며,
분산 서버 구조와 모바일 환경에서 매우 적합합니다.
토큰 기반 인증 흐름 요약
- 사용자가 로그인 요청 (ID/PW)
- 서버가 인증 성공 시 Access Token (필요 시 Refresh Token도) 발급
- 클라이언트는 토큰을 저장 (예: localStorage, cookie 등)
- 이후 요청 시 Authorization: Bearer <token> 형식으로 전송
- 서버는 토큰의 유효성과 서명을 검증하여 사용자 식별
JWT (JSON Web Token) 구성
JWT는 Header.Payload.Signature 세 부분으로 구성됩니다:
구성요소 | 설명 |
---|---|
Header | 알고리즘 정보, 타입 (typ: JWT) |
Payload | 사용자 정보 (ID, 권한 등) + 만료 시간 등 클레임 데이터 |
Signature | 서버의 Secret Key로 서명 → 위/변조 방지 |
⚠Payload는 Base64 인코딩만 되어 있어 암호화되지 않음
→ 민감 정보는 절대 포함하지 말 것
JWT 인증 흐름 요약
1
2
3
4
[로그인 요청] → 서버에서 자격 검증
→ Access Token 발급 → 클라이언트에 저장
→ 클라이언트가 이후 요청 시 Authorization 헤더에 토큰 포함
→ 서버가 토큰 검증 후 응답 처리
서버는 별도의 사용자 상태 저장 없이 토큰 검증만으로 인증 처리 가능
→ Stateless 구조 유지
🆚 세션 & 쿠키 vs JWT
항목 | 세션 & 쿠키 | JWT |
---|---|---|
상태 관리 | 서버가 세션 저장 | 서버는 상태 저장 없음 |
인증 저장 위치 | 서버 (세션) + 클라이언트 (쿠키) | 클라이언트 (토큰 저장) |
인증 전달 | 쿠키 자동 포함 | Authorization 헤더에 수동 포함 |
확장성 | 서버 간 세션 동기화 필요 | 어느 서버든 토큰만 있으면 인증 가능 |
로그아웃 처리 | 세션 제거로 즉시 무효 | 토큰은 만료 전까지 유효 (블랙리스트 필요) |
보안 측면 비교
항목 | 세션 & 쿠키 | JWT |
---|---|---|
탈취 대응 | 서버에서 세션 삭제 가능 | 탈취 시 유효기간 동안 유효함 |
XSS 위험 | HttpOnly 쿠키로 보호 가능 | localStorage 사용 시 더 취약 |
CSRF 위험 | 쿠키 자동 전송으로 CSRF 취약 | 수동 전송으로 상대적 안전 (단, 쿠키 저장 시 동일 위험) |
민감 정보 처리 | 서버에 보관 → 안전 | Payload 노출 가능 → 포함 금지 |
언제 무엇을 쓸까?
조건 | 추천 방식 | 이유 |
---|---|---|
단일 서버 / 간단 서비스 | 세션 & 쿠키 | 구현이 간단, 제어 쉬움 |
마이크로서비스 / 확장 필요 | JWT | 서버 간 인증 공유가 쉬움 |
민감 정보 다수 | 세션 | 서버가 정보를 보관하므로 안전 |
외부 서비스 연동 (OAuth 등) | JWT | 연동에 적합한 토큰 기반 구조 |
JWT의 주요 단점
1. 회수 불가
- 토큰 자체를 무효화할 방법이 없음
- 탈취 시 만료 전까지 계속 유효
2. Payload 노출
- Base64로 인코딩되어 있어 누구나 디코딩 가능
- 사용자 정보가 외부에 노출될 수 있음
3. 서버 자원 소모
- 매 요청마다 서명 검증 → 연산 비용 발생
해결책: Access Token + Refresh Token 구조
토큰 | 저장 위치 | 유효기간 | 관리 주체 | 역할 |
---|---|---|---|---|
Access Token | 클라이언트 (localStorage 등) | 짧음 (15분) | 클라이언트 | API 요청 인증 |
Refresh Token | 클라이언트 + 서버 DB | 김 (7일 이상) | 서버 | Access Token 재발급 |
Access Token
- 탈취되어도 짧은 시간 후 자동 만료 → 위험 축소
Refresh Token
- 서버 DB에서 관리 → 재발급 시 검증 가능
🧭 이중 토큰 구조 흐름
1
2
3
4
5
6
7
8
9
10
11
12
13
[로그인 시]
→ 서버가 Access + Refresh Token 발급
→ 클라이언트 저장
[요청 시]
→ Access Token 포함
→ 유효 시 정상 응답
→ 만료 시 401 Unauthorized
[재발급 요청]
→ Refresh Token 포함
→ 서버 DB에서 검증
→ 새로운 Access Token 발급
🔐 이 구조는 탈취 위험을 줄이면서도 사용자 경험(UX)을 해치지 않음
요약
- JWT는 서버 상태를 저장하지 않는 인증 방식으로 확장성과 효율성에 강점
- 민감 정보는 절대 Payload에 포함 ❌
- 보안을 위해 반드시 Refresh Token 관리 및 만료 정책 필요
- Access + Refresh 구조로 보안성과 UX를 동시에 확보할 수 있음
마무리
이로써 HTTP부터 시작한 인증의 흐름을 정리했습니다:
- HTTP는 Stateless하다
- 상태 유지를 위해 세션 & 쿠키가 등장
- 확장성과 분산 환경을 위해 JWT 기반 인증으로 발전
- JWT의 한계를 보완하기 위해 Refresh Token 구조 도입
다음에는 Spring Boot에서 JWT 기반 인증을 어떻게 구현하는지 실습 코드로 정리해보겠습니다.
This post is licensed under CC BY 4.0 by the author.