JWT 토큰으로 API 보안 강화하기
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
웹 개발
대상자
- 대상자: REST API 개발자, 마이크로서비스 아키텍처 설계자, 보안 정책 담당자
- 난이도: 중간~고급 (JWT 기초 이해 필요, Java/Spring Boot 경험 권장)
핵심 요약
- JWT 구조:
Header.Payload.Signature
로 구성되며, HS256 또는 RS256 알고리즘으로 서명 (예:Jwts.builder().signWith(SECRET_KEY)
) - 주요 특징: 무상태(Stateless) 방식으로 서버 리소스 절약, 암호화되지 않음 (Base64 인코딩만 적용)
- 보안 강화 팁:
- 암호키 관리: 환경 변수 또는 키 베일트 사용 (예: @Value("${jwt.secret}")
)
- 토큰 유효기간 제한: 15분~1시간 이내 설정 (예: .setExpiration(new Date(System.currentTimeMillis() + 900_000))
)
- HTTPS 전송 필수: 중간자 공격 방지
섹션별 세부 요약
1. JWT 개념 및 구조
- 정의: 사용자 신원을 검증하고 데이터 교환을 보호하는 암호화 서명 토큰
- 구성 요소:
- Header: JWT
타입 및 HS256
/RS256
서명 알고리즘 명시
- Payload: user ID
, role
, expiration time
등 클레임 포함
- Signature: 비밀키 또는 공개/개인 키 쌍으로 무결성 보장
- 유사점: 타임피스(boarding pass)에 비유 (헤더=항공사, 페이로드=이름/좌석, 서명=바코드)
2. JWT 인증 흐름
- 발급: 사용자 로그인 시 서버가 JWT 생성 (예:
Jwts.builder().setSubject("user").compact()
) - 전송: 클라이언트가
Authorization: Bearer
헤더로 전송 - 검증: 서버가 서명 검증 후 요청 처리 (예:
Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token)
) - 장점: 무상태 방식으로 마이크로서비스 확장성 향상
3. Spring Boot 구현 예시
- 코드 예시:
```java
@PostMapping("/login")
public ResponseEntity > login(@RequestBody LoginRequest request) {
String token = Jwts.builder()
.setSubject(request.getUsername())
.claim("role", "user")
.setExpiration(new Date(System.currentTimeMillis() + 3_600_000))
.signWith(SECRET_KEY)
.compact();
return ResponseEntity.ok(new TokenResponse(token));
}
```
- 보안 고려사항:
- HS256 알고리즘 사용 (예: Keys.secretKeyFor(SignatureAlgorithm.HS256)
)
- 암호화된 페이로드에 민감 정보(예: 비밀번호) 포함 금지
4. 보안 최고 실천 지침
- 암호키 보호: 환경 변수 또는 AWS KMS 등 사용 (예:
@Value("${jwt.secret}")
) - 토큰 유효기간: 15분~1시간 범위로 설정 (예:
.setExpiration(new Date(System.currentTimeMillis() + 900_000))
) - 알고리즘 강제:
HS256
/RS256
명시 (예:.setSigningKey(SECRET_KEY).parseClaimsJws(token)
) - HTTPS 필수: 중간자 공격 방지
5. JWT vs OAuth vs 세션 기반 인증 비교
| 기능 | JWT | OAuth | 세션 기반 |
|------|-----|-------|-----------|
| 상태 | 무상태 | 무상태 (접근 토큰) | 상태유지 (서버 세션) |
| 확장성 | 높음 | 높음 | 낮음 |
| 보안 | 서명 기반 (설정 필요) | 토큰 기반 (인증 서버 필요) | 서버 측 (CSRF 위험) |
| 사용 사례 | API 인증, 마이크로서비스 | 제3자 액세스 (예: Google) | 전통 웹 앱 |
결론
- JWT 적용 시 주의사항:
- 암호화되지 않음 → 민감 정보(예: 카드 번호) 포함 금지
- HTTPS 필수: 토큰 유출 방지
- 토큰 재발급 메커니즘: Refresh Token 사용 (예: HttpOnly Cookie 저장)
- 실무 팁:
- 토큰 유효기간: 15분~1시간으로 설정 (예: setExpiration(900_000ms)
)
- 암호키 관리: 환경 변수 또는 키 베일트 사용 (예: @Value("${jwt.secret}")
)
- 알고리즘 강제: HS256
/RS256
명시 (예: .setSigningKey(SECRET_KEY).parseClaimsJws(token)
)
- 사례: 전자상거래 스타트업이 JWT 도입 후, 서버 성능 40% 개선 및 200만 사용자 확장 성공