반응형
JWT 토큰 인증 방식과 보안 고려사항
오늘은 백엔드 개발에서 가장 많이 사용되는 인증 방식 중 하나인 JWT(JSON Web Token) 토큰 인증에 대해 정리해보겠습니다.
JWT의 정의 → 사용 방식 → Access/Refresh 토큰 구조 → 관리 방법 → 보안 고려사항까지 단계별로 살펴보겠습니다.
JWT(JSON Web Token) 토큰이란?
- JSON 형식으로 인코딩된 사용자 인증 정보를 포함하는 토큰입니다.
- 주로 클라이언트-서버 간 인증을 위해 사용되며, 세션을 서버에 저장하지 않고도 인증 상태를 유지할 수 있습니다.
JWT는 크게 세 부분으로 구성됩니다:
Header.Payload.Signature
예시:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- Header: 토큰 타입(JWT), 알고리즘(예: HS256)
- Payload: 사용자 정보(Claims: userId, role 등)
- Signature: 비밀 키로 서명, 변조 방지
JWT 인증 방식의 흐름
- 로그인 요청: 사용자가 아이디/비밀번호로 로그인
- 토큰 발급: 서버가 Access Token(+Refresh Token)을 발급하여 클라이언트에 전달
- 인증 요청: 클라이언트가 API 호출 시
Authorization: Bearer <Access Token>헤더에 포함 - 서버 검증: 서버는 토큰을 검증하여 권한 확인 후 응답
- 토큰 갱신: Access Token 만료 시, Refresh Token으로 새로운 Access Token 발급
이 과정에서 서버는 세션을 저장하지 않아 확장성(Scalability)이 뛰어납니다.
Access Token과 Refresh Token
| 구분 | Access Token | Refresh Token |
| 목적 | API 요청 시 인증/인가 수행 | Access Token 만료 시 갱신 |
| 유효기간 | 짧음 (분~시간 단위) | 김 (일~주 단위) |
| 저장 위치 | 보통 브라우저 메모리/앱 내부 | HttpOnly 쿠키 또는 안전한 DB |
| 보안 리스크 | 탈취 시 즉시 API 접근 가능 | 탈취 시 장기 인증 위험 |
| 관리 방법 | 빠른 만료, 정기 재발급 | 안전한 저장 + 재발급 시 무효화 정책 |
즉, Access Token은 짧게, Refresh Token은 길게 가져가면서 보안을 강화하는 구조가 일반적입니다.
JWT 관리 전략
- 토큰 저장 위치
- Access Token → 메모리, 혹은 localStorage (단, XSS 취약점 고려)
- Refresh Token → HttpOnly Secure 쿠키 권장
- 토큰 만료 전략
- Access Token: 수 분 ~ 수 시간 단위
- Refresh Token: 수 일 ~ 수 주 단위
- 토큰 탈취 위험을 최소화하려면 짧게 설정하는 것이 핵심
- 토큰 무효화(Invalidate)
- 사용자가 로그아웃할 때 Refresh Token DB에서 삭제
- Refresh Token 블랙리스트 관리(중앙 집중 저장소 or Redis 활용)
- 재발급 로직
- Access Token 만료 시 Refresh Token을 사용해 새 Access Token 발급
- Refresh Token도 만료되면 재로그인 요구
JWT 보안 고려사항
1. 토큰 탈취 방지
- HTTPS 사용: 중간자 공격 방지
- HttpOnly 쿠키: JS 접근 차단 → XSS 완화
- Secure 옵션: HTTPS 연결에서만 전송
2. 짧은 만료 시간 설정
- Access Token은 최대 수 시간, Refresh Token은 며칠~몇 주 단위
- 너무 길면 탈취 시 위험이 커짐
3. 토큰 무효화 정책
- 강제 로그아웃/권한 변경 시 즉시 블랙리스트 처리 필요
- Redis 같은 중앙 저장소 활용
4. Payload에 민감정보 저장 금지
- JWT는 클라이언트에서도 디코딩 가능(Base64 URL Safe 인코딩)
- 비밀번호, 카드번호 같은 민감정보는 절대 넣지 말 것
5. 서명 키 관리
- 대칭키(HS256): 키가 노출되면 심각한 위험
- 비대칭키(RS256): 공개키/개인키 분리로 안전성↑
6. Refresh Token 보안
- DB에 안전하게 저장하고, 기기별 Refresh Token을 별도로 관리
- 재발급 시 기존 토큰 폐기
예제 코드 (Spring Boot + JWT)
1) JWT 발급 유틸
public class JwtUtil {
private static final String SECRET = "mySecretKey";
private static final long EXPIRATION = 1000 * 60 * 15; // 15분
public static String generateToken(String userId) {
return Jwts.builder()
.setSubject(userId)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
}
public static Claims validateToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
}
}
2) 컨트롤러 예제
@RestController
public class AuthController {
@PostMapping("/login")
public Map<String, String> login(@RequestBody Map<String, String> body) {
String userId = body.get("userId");
// 비밀번호 검증 로직 생략
String token = JwtUtil.generateToken(userId);
return Map.of("accessToken", token);
}
@GetMapping("/secure")
public String secure(@RequestHeader("Authorization") String authHeader) {
String token = authHeader.replace("Bearer ", "");
Claims claims = JwtUtil.validateToken(token);
return "Hello " + claims.getSubject();
}
}
정리
- JWT 토큰은 세션 저장소가 필요 없는 인증 방식으로 확장성과 편의성을 제공.
- Access Token은 짧게, Refresh Token은 길게 가져가면서 보안을 강화.
- 보안 고려사항: HTTPS, HttpOnly 쿠키, 짧은 만료시간, 블랙리스트, 민감정보 금지, 키 관리.
- 대규모 서비스에서는 반드시 Refresh Token 관리 정책과 토큰 무효화 전략을 함께 설계해야 함.
반응형
'Backend > Study' 카테고리의 다른 글
| [Study] JWT 활용 및 예제 코드 (0) | 2025.10.03 |
|---|---|
| [Study] JWT 동작방식 깊게 살펴보기 (0) | 2025.10.02 |
| [Study] 서버 다운 없이 배포하는 방법 (무중단 배포) (0) | 2025.09.30 |
| [Study] Nginx 리버스 프록시 설정 예제 (502/504 에러 해결) (0) | 2025.09.29 |
| [Study] Redis 캐시 적용 방법 (Spring Boot 실전 예제) (0) | 2025.09.25 |