[WEB] Jwt 인증, 액세스 토큰만으로 충분할까?
Jwt 인증, 액세스 토큰만으로 충분할까?
이 글에서는 JWT(JSON Web Token)를 사용한 인증 아키텍처를 4단계로 나누어 분석하고, 각 단계의 문제점과 해결 방안을 제시하는 것을 목적으로 합니다. 최종적으로는 보안성, 확장성, 성능을 모두 충족하는 최적의 아키텍처를 도출합니다.
1단계: 단일 액세스 토큰 방식
문제점: 토큰의 강제 폐기 불가능
초기 JWT 구현은 긴 유효기간(예: 7~30일)을 가진 단일 액세스 토큰을 발급하는 방식을 채택하는 경우가 많습니다. 이 구조의 가장 심각한 취약점은 한번 발급된 토큰을 만료 전에는 폐기할 수 없다는 것입니다.
서버는 토큰을 검증할 때 오직 토큰 자체에 담긴 서명과 만료 시간 정보만을 신뢰합니다. 이는 서버가 토큰의 현재 유효 상태를 외부에서 확인할 방법이 없음을 의미합니다. 만약 XSS 공격, 악성 브라우저 확장 프로그램, 또는 HTTP 통신 감청 등으로 토큰이 탈취되면 공격자는 만료일까지 해당 사용자의 모든 권한을 합법적으로 행사할 수 있습니다. 사용자가 비밀번호를 변경하거나 관리자가 계정을 잠그는 등의 조치를 취해도, 이미 공격자의 손에 있는 토큰의 유효성에는 아무런 영향을 주지 못합니다.
해결책: 역할 분리를 통한 위험 감소
이 문제를 해결하기 위해서는 단일 토큰이 가진 과도한 권한과 긴 유효기간을 분리해야 합니다. 이것이 바로 다음 단계인 2-토큰 전략의 도입 배경입니다.
2단계: 리프레시 토큰 도입
문제점: 제한적 보안 개선
2-토큰 전략은 역할을 분리하여 보안을 개선합니다.
- 액세스 토큰: 유효기간을 15분~1시간으로 짧게 설정하여 실제 자원 접근에 사용합니다.
- 리프레시 토큰: 유효기간을 7일 이상으로 길게 설정하여 새로운 액세스 토큰을 발급받는 데 사용합니다.
이로써 액세스 토큰이 탈취되더라도 공격자가 활동할 수 있는 시간이 크게 줄어드는 효과를 얻습니다. 하지만 이는 미봉책에 가깝습니다. 만약 유효기간이 긴 리프레시 토큰 자체가 탈취된다면, 공격자는 지속적으로 새로운 액세스 토큰을 발급받을 수 있어 결국 1단계와 동일한 위험에 노출됩니다. 리프레시 토큰은 액세스 토큰보다 전송 빈도가 훨씬 낮아 탈취 위험이 적지만, 일단 탈취되면 그 피해는 동일하게 치명적입니다.
해결책: 리프레시 토큰의 상태 관리
근본적인 해결을 위해서는 리프레시 토큰을 더 이상 서버가 신뢰만 하는 대상이 아닌, 상태를 직접 관리하고 통제할 수 있는 대상으로 만들어야 합니다.
3단계: 데이터베이스를 이용한 상태 관리와 그 한계
해결책 도입: 리프레시 토큰 상태 저장
2단계에서 남겨진 ‘리프레시 토큰 탈취’ 문제를 해결하기 위해, 토큰의 상태를 관계형 데이터베이스(RDBMS)에 저장하는 방식을 도입합니다.
- 구현: 리프레시 토큰 발급 시, 해당 토큰의 해시(Hash) 값을 DB의
refresh_tokens테이블에 저장합니다. 재발급 요청 시에는 전달받은 토큰이 DB에 유효한 상태로 존재하는지 확인합니다. 로그아웃 등의 이벤트 발생 시에는 DB에서 해당 토큰 기록을 삭제하여 폐기합니다.
이로써 우리는 드디어 토큰을 선택적으로 폐기할 수 있는 중앙 통제 기능을 확보하게 되어, 리프레시 토큰 탈취 문제에 대응할 수 있게 됩니다.
새로운 문제점: 성능 병목
하지만 이 해결책은 새로운 문제를 야기합니다. 바로 성능입니다.
모든 토큰 재발급 요청마다 디스크(Disk) I/O에 기반한 RDBMS 조회 연산이 필요합니다. 서비스 규모가 커져 동시 접속자가 수만 명에 이르면, 이 잦은 DB 접근은 인증 서버의 응답 지연을 유발하고 전체 시스템의 병목 현상으로 이어질 수 있습니다. 보안성을 확보하는 대가로 성능을 희생하게 되는 트레이드오프가 발생하는 것입니다.
4단계: Redis를 활용한 성능 최적화
해결책: 인메모리(In-Memory) 저장소 활용
3단계의 성능 문제를 해결하기 위한 최종 해결책은 인메모리 데이터 저장소인 Redis를 도입하는 것입니다.
- 구현: 리프레시 토큰의 상태 정보를 RDBMS가 아닌 Redis에 저장합니다. Redis는 모든 데이터를 메모리에서 처리하므로 RDBMS에 비해 월등히 빠른 조회 속도를 보장합니다.
이로써 3단계에서 확보했던 강제 폐기 기능은 그대로 유지하면서, 인증 과정에서 발생했던 성능 병목 현상은 해결됩니다. Redis의 TTL(Time To Live) 기능을 사용하면 만료된 토큰을 자동으로 정리할 수 있어 관리 효율성도 높아집니다.
물론 Redis라는 새로운 인프라 구성요소가 추가되면서 초기 구축 및 유지보수의 복잡도가 소폭 증가한다는 점은 고려해야 할 사항입니다.
결론
아래는 각 인증 전략의 특징을 요약한 표입니다.
| 단계 | 전략 | 핵심 개념 | 장점 | 단점 |
|---|---|---|---|---|
| 1 | 단일 액세스 토큰 | Stateless | 구현 단순 | 토큰 폐기 불가, 보안 취약 |
| 2 | 액세스 + 리프레시 | 역할 분리 | 액세스 토큰 탈취 피해 최소화 | 리프레시 토큰 폐기 불가 |
| 3 | DB 기반 상태 관리 | Stateful, Revocation | 토큰 강제 폐기 가능 | 트래픽 증가 시 성능 저하 |
| 4 | Redis 기반 상태 관리 | In-Memory, High-Performance | 강제 폐기 가능, 고성능 | 아키텍처 복잡도 증가 |
4단계(Redis 기반 상태 관리) 방식이 보안, 확장성, 성능 측면에서 가장 균형 잡힌 아키텍처입니다. 따라서 신규 시스템을 설계하거나 기존 시스템을 개선할 때, 해당 방식을 도입하는 것을 최종적인 목표로 권장합니다. 시스템의 초기 트래픽이 적다면 3단계로 시작하여 추후 4단계로 전환하는 점진적 접근 또한 합리적인 대안이 될 수 있습니다.