본문 바로가기
카테고리 없음

그래서 JWT가 뭔데? (Stateless의 장단점과 보완방법)

by 샘오리 2025. 4. 8.
728x90
반응형

JWT(JSON Web Token)의 이해와 활용


JWT는 JSON Web Token로 말 그대로 JSON 객체로 토큰을 주고 받는 토큰 인증 방식이다.
이 토큰은 디지털 서명되어 있어 정보의 신뢰성과 무결성을 보장하고 HMAC 알고리즘을 사용한 비밀키나 RSA를 사용한 공개/개인 키 쌍으로 서명될 수 있다고 한다.

JWT는 세 부분으로 구성되어 있다.

  • 헤더(Header): 토큰 유형(JWT)과 서명 알고리즘
  • 페이로드(Payload): 토큰에 포함할 사용자에 대한 정보나 메타데이터, 통칭 클레임
  • 서명(Signature): 헤더와 페이로드를 Base64Url로 인코딩한 비밀키

이 세 부분은 점(.)으로 구분되어 xxxxx.yyyyy.zzzzz 형태로 표현된다.

JWT의 Flow

토큰 생성: 클라이언트가 웹에 로그인하면 서버는 사용자 정보와 권한을 포함한 JWT를 생성하고 서명

토큰 저장: 클라이언트는 이 토큰을 로컬 스토리지나 쿠키에 저장

요청 시 토큰 포함: 이후 요청에서 클라이언트는 Authorization 헤더에 JWT를 포함시켜 서버에 전송

토큰 검증: 서버는 토큰의 서명을 검증하고, 페이로드의 클레임을 확인하여 사용자를 인증

응답 처리: 토큰이 유효하면 서버는 요청을 처리하고 적절한 응답을 반환

 

 

서버에서는 토큰을 어떻게 검증하는 걸까?

 

토큰 형식 확인
서버는 Authorization 헤더가 존재하는지 확인하고, 토큰이 "Bearer "로 시작하는 올바른 형식인지 검사.

클레임(Claims) 유효성 확인
exp (만료 시간): 현재 시간이 만료 시간(exp)보다 이전인지 확인.
nbf (Not Before): 현재 시간이 이 값 이후인지 확인.
iss (발급자): 토큰 발급자가 신뢰할 수 있는 발급자인지 확인.
aud (대상자): 토큰이 의도된 리소스 서버를 대상으로 하고 있는지 확인.

 

위 방식으로도 검증하지만 제일 중요한 게 아래이다.

 

서명(Signature) 검증
JWT의 Header와 Payload를 Base64 디코딩 후 결합.
서버가 보유한 비밀키(secret key) 또는 공개키(public key)를 사용해 서명을 재생성.
서버쪽에서 재생성된 서명과 받은 토큰의 서명을 비교하여 일치 여부를 확인.


Stateless 특성에 따른 장단점


장점
성능(Performance): 서버 오버헤드가 감소하여 응답 시간이 빠르다.

 

-> Stateless한 토큰을 도입한 가장 큰 이유인데 빠르다는 것이다. 사용자가 적으면 상관없는데 수많은 유저들의 정보를 세션 스토리지 따위에 저장해놓고 관리하는 것도 비용이고 로그인 하고 나서 뭔가를 request 할 때 마다 인증이 필요하다면 DB에서 조회를 해야하기 때문에 DB 트랜잭션이 발생할 것이고 이는 비용적인 측면에서 낭비가 될 것이다. JWT와 같은 Stateless한 토큰 인증 방식은 서버가 사용자에 대한 상태 정보를 가지고 있지도 않고 매 Request마다 백엔드 선에서 검증하고 끝내서 DB를 거치지 않아도 되기 때문에 인증 절차를 줄여서 응답 시간이 빠르다고 할 수 있다.

단점
제어의 어려움: 발급된 토큰은 만료 전에 무효화하기도 어렵고 만료 시간 연장 등의 수정도 불가능하다. 보안적인 측면에서 구멍이 있는 것과 다름이 없다. 누군가 이미 발급된 토큰을 탈취해서 악용을 하고 있다 하더라도 이미 발급이 됐다면 제어를 못하니까 말이다.

 

-> Stateless의 고질적인 단점인데 토큰을 발급해놓고 나면 서버는 각 사용자에 대한 상태를 알지 못하기 때문에 만료 시간전에 무효화하기 어렵고 사용자가 토큰이 만료되어 재발급하지 않는 이상 제어가 불가능하다. 만료시간이 길 경우에는 다른 사람이 발급된 토큰을 가지고 악용할 수도 있다.

 

Stateless의 단점 보완

만료 시간이 지나기 전까지는 제어가 안되니 만료 시간을 매우 짧게 두고 만료 시 재인증을 하게 하는 방법

 

-> Stateless의 장점을 죽이는 방법이고 짧은 만료 시간 이후에 사용자가 매번 재 인증을 해야하기 때문에 번거롭다. 그래서 나온게 Refresh Token이다.

 

Refresh Token을 통한 한계 극복

Refresh Token은 액세스 토큰(JWT)이 만료되었을 때 새로운 액세스 토큰을 발급받기 위한 장기 토큰으로 아래와 같이 작동한다.

사용자가 로그인하면 서버는 Access Token과 함께 Refresh Token을 발급. 이 Refresh Token은 서버에도 저장됨.

Access Token 이 만료되면 클라이언트는 가지고 있는 Refresh Token을 사용하여 재발급을 요청.

서버는 Refresh Token의 유효성을 검증하고, 새로운 액세스 토큰과 Refresh Token을 발급.

장점:

액세스 토큰의 수명을 짧게 유지하여 보안을 강화할 수 있다.

Refresh Token은 서버에 저장되므로 필요시 무효화가 가능.

사용자가 자주 로그인할 필요 없이 장기간 인증 상태를 유지할 수 있다.

단점:

만료시간이 짧아졌다 하더라도 그 사이에 악용하려고 들면 무효화 할 수 있는 방법이 거의 없다.

그래서 Application의 특성에 맞춰 적절히 Session 을 섞어서 쓸지 말지도 고민해봐야한다.

 

강력한 보안보다는 속도가 중요시 된다면 충분히 선택해볼만한 대표적인 Stateless 인증방법이라서 소개해보았다.

728x90
반응형