JWT(Json Web Token)은 웹상에서 사용되는 토큰에 대한 표준 규격(RFC 7519)를 의미
JWT는 무상태성(stateless)으로 수평 확장이 용이하다.
기존의 인증방식인 Cookie와 Session에 대해 알아보자.
클라이언트(브라우저)에 인증 정보를 직접 저장 (예: ID, Password)
저장 위치: 브라우저의 텍스트 파일
단점:
보안 위험: 민감한 정보가 노출될 수 있음
조작 가능성: 위·변조된 Cookie를 서버가 식별하기 어려움
브라우저 간 공유 어려움
사이즈 제한(4KB)
서버는 매번 클라이언트의 Cookie를 분석해야 함
클라이언트에는 인증 토큰(세션 ID)만 저장
실제 인증 정보는 서버에 저장 및 관리
서버는 클라이언트로부터 받은 세션 ID를 기준으로 저장된 인증 정보를 확인
보안이 강화되었지만, 서버에서 상태(Session)을 유지해야 하므로 리소스 소모가 발생
Cookie만 사용하는 경우: 이름·전화번호가 적힌 입장권 → 분실 시 개인정보 유출 위험
Session 사용하는 경우: 식별 코드가 적힌 팔찌 → 개인정보는 서버에 안전하게 저장, 단 서버는 매번 확인해야 함
이렇게 Cookie와 Session을 함께 사용하면 보안측면에서 좀 더 나아집니다. Session ID를 탈취당했다고 해도 Session 저장소를 전부 지워버리면 서버 측에서 유효하지 않는 인증을 전부 차단할 수 있기 때문이죠. 하지만 매번 요청이 들어올 때마다 Cookie에 저장된 Session ID를 서버 쪽에서 데이터 조회를 통해 검증해야한다는 점이 조금 걸립니다.
서버에 상태를 저장 → 서버 확장(Scale-out) 시 복잡성 증가
세션 저장소 장애 시 전체 인증 영향
사용자 수 증가 시 저장소 부담 증가 및 성능 저하
매 요청마다 세션 조회 → 캐싱 어려움
항목 | Session | JWT |
---|---|---|
서버 상태 저장 | O (Stateful) | X (Stateless) |
서버 확장성 | 낮음 (동기화 필요) | 높음 (검증만 하면 됨) |
다양한 플랫폼 대응 | 어려움 (쿠키 기반) | 쉬움 (모든 플랫폼 동일 방식) |
CORS 이슈 | 발생 가능 | 상대적으로 자유로움 |
인증 속도 | 느림 (세션 조회 필요) | 빠름 (토큰 검증만) |
캐싱 | 어려움 | 쉬움 (JWT 기반 Key 활용) |
보안 대응 | 세션 삭제로 대응 가능 | 탈취 시 만료 전까지 대응 불가 |
🔸 단점: 토큰 탈취 시 서버 대응 불가
클라이언트가 토큰을 소유 → 탈취되면 만료 전까지 사용 가능
서버에서는 토큰 폐기 불가능 (세션 방식과의 가장 큰 차이점)
만료 시간 짧게 설정
Access Token은 짧은 유효기간 설정 → 탈취 피해 최소화
Refresh Token Rotation
Access Token 재발급 시 Refresh Token도 새로 발급
이전 Refresh Token은 즉시 폐기 → 탈취 시도 감지 가능
→ 이를 위해 서버는 Refresh Token 사용 이력 저장(DB or Redis) 필요
→ jti (JWT ID) 또는 블랙리스트 방식으로 관리 가능
JWT가 무엇인지 간단히 설명해주세요
JWT는 JSON Web Token의 약자로, 사용자 인증과 정보 전달을 위해 사용되는 토큰 기반 인증 방식이다. 클라이언트 측에 토큰을 저장하고 이를 서버에 전달하여 인증을 수행하며, 서버는 상태를 유지하지 않는 무상태(stateless) 인증이 가능하다.
JWT의 구조는 어떻게 구성되어 있고, 각각의 역할은 무엇인가요?
JWT는 세 부분으로 구성된다.
Header: 토큰의 타입(JWT)과 서명 알고리즘 정보가 담긴다.
Payload: 사용자 식별 정보나 권한 등 클레임 데이터가 담긴다. 민감한 정보는 포함하지 않는다.
Signature: Header와 Payload를 인코딩한 후 비밀키로 서명한 값으로, 위변조 여부를 검증하는 데 사용된다.
사용자가 JWT를 이용해 인증하는 과정을 클라이언트와 서버의 입장에서 각각 설명해주세요. 서버는 요청마다 토큰을 어떻게 검증하나요?
클라이언트는 로그인 후 서버로부터 Access Token을 발급받아 저장한다. 이후 요청 시 Authorization 헤더에 토큰을 담아 보낸다.
서버는 해당 토큰을 디코딩하고 서명을 검증해 위변조 여부를 확인한 후, Payload에 있는 정보를 바탕으로 사용자를 인증한다.
JWT의 저장 위치는 어떻게 되며, 저장 위치에 따른 차이점은 무엇일까요?
로컬스토리지나 세션스토리지에 저장할 수 있고, HttpOnly 쿠키에 저장할 수도 있다.
로컬스토리지는 XSS 공격에 취약하며, HttpOnly 쿠키는 XSS에 강하지만 CSRF에 취약하므로 별도의 방어책이 필요하다.
세션 방식과 JWT 방식의 가장 큰 차이점은 무엇일까요?
세션은 서버가 상태를 저장하는 방식이며, 서버에서 클라이언트의 인증 정보를 관리한다. 반면, JWT는 클라이언트가 인증 정보를 담은 토큰을 가지고 있으며, 서버는 상태를 저장하지 않는다.
JWT는 어떻게 수평 확장을 용이하게 하나요?
JWT는 서버가 인증 상태를 저장하지 않기 때문에, 어떤 서버가 요청을 받아도 동일하게 인증 처리가 가능하다. 별도의 세션 공유나 중앙 저장소가 필요 없어 서버 수평 확장에 유리하다.
JWT 기반 인증 시스템에서 로그아웃은 어떻게 처리하나요?
JWT는 무상태 방식이므로 서버가 로그아웃 상태를 기억하지 않는다. 로그아웃을 구현하려면 블랙리스트를 이용하거나, 토큰의 유효 시간을 짧게 설정하고 Refresh Token을 제거하는 방식으로 처리한다.
JWT의 무상태(stateless) 인증이 어떻게 수평 확장에 유리한가요?
서버가 사용자 상태를 저장하지 않으므로, 인증 정보를 서버 간 공유할 필요가 없다. 로드밸런서를 통해 어떤 서버에 요청이 들어가도 인증이 가능해져 수평 확장 구조에서 효율적이다.
Refresh Token Rotation이란 무엇이며, 어떤 보안 위협을 막을 수 있나요?
Refresh Token Rotation은 토큰이 사용될 때마다 새로운 Refresh Token을 발급하고 이전 토큰은 무효화하는 방식이다. 탈취된 Refresh Token이 재사용되는 것을 방지할 수 있다.
JWT 인증 방식의 단점은 무엇이고, 이를 보완하기 위한 방법은 무엇인가요?
토큰 무효화가 어렵고, 탈취 시 위험하며, 토큰 크기가 커 네트워크 부담이 있다. 이를 보완하려면 만료 시간을 짧게 설정하고 Refresh Token을 사용하며, 탈취 방지를 위한 보안 설정이 필요하다.
JWT를 사용할 때 캐싱 전략이 유리하다고 했는데, 왜 그런가요?
JWT는 자체적으로 사용자 정보를 포함하고 있어 디비나 세션 조회 없이 인증이 가능하다. 서버는 토큰을 검증하기만 하면 되므로 빠르게 인증할 수 있으며, 인증 캐싱 효과가 있다.
JWT와 Session 방식 중 어떤 방식이 어떤 상황에서 사용해야하나요?
소규모, 단일 서버 기반 서비스는 세션이 관리 측면에서 편리하다. 반면, 대규모 분산 시스템이나 마이크로서비스 구조에서는 JWT가 수평 확장성과 다양한 클라이언트 지원에 유리하다.
JWT의 서명(Signature)은 왜 중요하며, 어떤 공격을 방어할 수 있나요?
서명은 토큰의 위변조를 방지하기 위해 사용된다. 토큰이 조작되었는지 확인할 수 있으며, 공격자가 Payload를 수정해 권한을 상승시키는 등의 공격을 방어할 수 있다.
JWT와 OAuth2는 어떤 관계인가요?
OAuth2는 인증과 권한 위임을 위한 프레임워크이며, JWT는 인증 정보를 전달하는 형식 중 하나다. OAuth2는 인증 흐름 자체를 정의하고, JWT는 그 흐름에서 토큰 포맷으로 사용될 수 있다.
15. JWT를 사용할 때 토큰 무효화가 어려운 이유와 그에 대한 대응 전략은?
서버가 토큰 상태를 저장하지 않기 때문에 무효화 리스트를 관리하지 않는 한 토큰을 강제로 만료시킬 수 없다. 대응 전략으로는 토큰 만료 시간을 짧게 설정하고, 블랙리스트 또는 Refresh Token Rotation을 사용한다.
16. JWT의 payload 부분에는 민감한 정보를 넣지 말라고 흔히들 이야기합니다. 그 이유가 무엇이라고 생각하시나요? 그리고 payload에 넣는 정보의 종류와 적정선은 어디까지라고 보십니까?
JWT는 Base64로 인코딩되며 누구나 디코딩이 가능하다. 따라서 패스워드, 주민등록번호 등의 민감 정보는 넣으면 안 된다. userId, 권한 정보, 토큰 발급 시간, 만료 시간 등 최소한의 정보만 포함해야 한다.
JWT를 사용할 때 발생할 수 있는 보안 취약점에는 어떤 것들이 있을까요? 그리고 이러한 취약점을 방어하기 위한 방법은 무엇이 있을까요?
XSS, 토큰 탈취, 위조 등이 발생할 수 있다. HTTPS를 사용하고, 토큰을 HttpOnly 쿠키에 저장하며, 서명을 강력하게 검증하고, 짧은 만료 시간과 Refresh Token을 활용하여 보완한다.
Refresh 토큰으로 엑세스토큰을 재발급하는 과정을 설명해주세요
클라이언트가 만료된 Access Token과 함께 Refresh Token을 서버에 전송하면, 서버는 Refresh Token을 검증한 후 새로운 Access Token을 발급한다. 이때 Refresh Token Rotation을 적용해 이전 토큰을 무효화할 수 있다.
19. 만약 사용자 인증이 필요한 신규 서비스를 개발해야 한다면, 세션 방식과 JWT 방식 중 어떤 것을 선택하겠으며, 그 이유는 무엇인가요? 서비스의 특징(예: 소규모, 대규모, 단일 서버, MSA 등)에 따라 선택이 달라질 수 있다면 함께 설명해 주세요.
선택은 서비스의 구조와 규모에 따라 달라집니다.
단일 서버로 구성된 소규모 서비스라면 세션 방식을 선택하는 것이 더 간단하고 안전합니다. 서버에서 세션 상태를 관리할 수 있고, 탈취나 위조된 세션에 대한 대응이 용이하기 때문입니다. 또한 서버 내부에서 메모리 기반 또는 Redis 등을 활용해 세션을 관리하면 관리가 직관적입니다.
반면 MSA나 클라우드 기반의 대규모 서비스라면 JWT 방식을 선택하는 것이 유리합니다. JWT는 상태를 서버에 저장하지 않는 무상태 방식이므로 서버 간 세션 공유 없이도 인증 처리가 가능해 수평 확장에 적합합니다. 여러 마이크로서비스가 동일한 JWT를 검증하고 사용자 정보를 활용할 수 있어 인증 로직의 분산이 용이합니다.
따라서 소규모이거나 보안 통제가 중요한 시스템은 세션 기반, 대규모 분산 환경이나 외부 서비스와의 연동이 필요한 경우는 JWT 기반을 사용하는 것이 일반적인 선택입니다.
MSA 환경에서 세션(Session) 기반 인증 방식이 적합하지 않은 이유
- 세션을 여러 인스턴스에서 공유하려면 세션 클러스터링(예: sticky session, 공용 Redis 사용 등)이 필요합니다.
→ 이는 성능 저하와 운영 복잡성을 초래할 수 있으며, 특히 마이크로서비스 간 통신이 많은 경우 병목 지점이 됩니다.- MSA 구조에서는 여러 서비스가 사용자의 인증 정보를 공유해야 합니다.
→ 세션은 중앙 인증 서버가 아닌 이상, 각 서비스가 해당 세션 정보를 공유하거나 별도로 세션 정보를 조회해야 하기 때문에 서비스 간 독립성과 유연성을 해칩니다.
21. Spring Boot에서 JWT 인증을 구현할 때 필수적으로 구현해야 하는 필터 또는 컴포넌트는 무엇일까요?
JWT 토큰을 추출하고 검증하는 필터가 필요하며, 일반적으로 UsernamePasswordAuthenticationFilter 앞에 커스텀 필터를 두어 SecurityContext에 인증 정보를 등록한다.
대칭 키 방식(예: HS256)은 서명 생성과 검증에 동일한 키를 사용합니다. 구현이 간단하지만, 서명 키가 유출되면 누구나 유효한 JWT를 생성할 수 있기 때문에 키 관리가 매우 중요합니다.
비대칭 키 방식(예: RS256)은 공개키와 개인키 쌍을 사용합니다. 발급자는 개인키로 서명하고, 서버는 공개키로 이를 검증합니다. 공개키를 여러 서버에 안전하게 배포할 수 있기 때문에, 보안성과 확장성이 뛰어나며 인증 서버와 리소스 서버가 분리된 환경에서 적합합니다.
보안이 중요한 환경이나 여러 서비스 간 JWT를 공유해야 하는 구조에서는 비대칭 키 방식이 선호됩니다.