들어가기
온라인 쇼핑몰을 생각해보자. 마음에 드는 물건을 카트에 담았다. 계속해서 둘러보고 다른 물건도 카트에 담아서 확인을 해봤는데 앞에 물건이 없다? 우리가 원하는 것은 내가 카트에 물건을 담아도 사라지지 않는 것이다. 그 상태를 유지하고 싶다.
HTTP 프로토콜은 기본적으로 stateless(무상태)이다. stateless라는 의미는 서버-클라이언트 간의 통신 시에 이전 통신 정보를 저장하지 않는다는 의미이다. 즉, 물건을 담는 요청을 하면 물건을 담지만 그 상태를 유지하지 않는다.
서버와 클라이언트는 독립적이며 그렇기 때문에 서버에 어떠한 정보도 저장하지 않는다. 앞서 예시를 든 것은 stateless가 아니라 stateful, 사용자의 상태를 유지하기 위한 방법이 필요하다. 쿠키와 세션은 이런 HTTP 의 stateless 특징을 stateful 하게 만들어준다.
우리는 쇼핑중에도 물건을 카트에 넣은 유지하는 상태인 stateful 상태를 만들고 싶어한다. stateful 상태를 만들기 위해서 우리는 세션/쿠키 기반 혹은 JWT 같은 토큰을 사용할 수 있다. 이 둘의 차이점은 무엇일까?
JWT 를 이야기하기전에 쿠키와 세션에 대해 먼저 알아보자.
쿠키와 세션
쿠키는 클라이언트(브라우저)에 있는 키밸류 형태의 최대 4KB의 작은 데이터 파일이다. 쿠키는 이전 상태를 알 수 있다. 쿠키 없이 서버에 요청을 하면 서버는 상태가 담긴 쿠키를 담아 응답한다. 응답을 받은 클라이언트는 쿠키를 저장해뒀다가 서버에 다시 요청할 때마다 쿠키를 보낸다.
세션은 쿠키를 사용해 서버와 통신한다. 이런 쿠키를 세션 쿠키라고 하는데 이 글에서는 그냥 세션이라고 하겠다. 일반적인 쿠키와 다른점은 사용자 정보를 서버에서 관리한다는 것이다. 클라이언트에서는 sessionId 라는 id값만 쿠키에서 가지고 있고, 서버에 요청할때마다 서버는 해당 쿠키의 sessionId로 유효한 세션인지 확인을 하고 응답을 한다.
서버에서 사용자정보를 관리하기 때문에 쿠키보다 보안에 유리하지만, 각각의 사용자들에 대한 정보를 모두 가지고 있기 때문에 사용자가 많아질수록 서버 메모리에 부담이 증가된다. 이 때문에 무조건적인 세션사용보다는 적절히 보안에 크게 신경쓰지 않아도 되는 액션들에는 쿠키를 사용하는 것이 좋다.
세션의 단점으로부터 나오는 문제는 서버가 분산되어 있을 때이다. 예를 들어 쇼핑몰앱에서 주문을 담당하는 서버와 회원관리를 담당하는 서버가 따로 있다고 생각해보자. 처음에 회원관리 서버를 통해 로그인을 해서 세션이 생성되었다. 그리고 원하는 물건을 주문하려는 순간, 주문 서버로 요청이 가기 때문에 세션을 찾을 수 없게 되는 문제가 있다.
이 문제를 해결하기 위해서는 두 서버 모두가 접근할 수 있는 별도의 세션 관리 서버를 두고 세션은 모두 거기에서 관리하도록 해야한다. 하지만 세션 관리 서버 하나가 장애가 나면 모든 시스템이 마비가 된다. 그렇다면 앞에서 나뉘어져있던 회원관리서버와 주문서버를 나눈 의미가 있을까?
이것을 해결해야하려면 어떻게 해야할까? 지금부터 이야기할 토큰 기반 인증은 이런 문제점을 완화시킬 수 있다.
토큰
먼저, API에서 Token이라는 용어는 일종의 비밀번호 같은 것을 말한다. 쇼핑몰에 로그인 같은 특정 행동을 취하기 위해서 서버가 사용자에게 인증을 요구한다. 여기서 토큰은 사용되는 어감에서 그대로 나오듯이 인증을 위한 교환권이라고 상상하면 이해하기 편하다.
토큰 기반 인증은 일반 토큰 기반인증과 클레임 기반 인증으로 나뉘어진다. 일반 토큰 기반인증은 토큰의 의미가 없는 랜덤 문자열로 되어 단순히 비밀번호 역할만 한다. 그 외의 사용자 정보나 만료시간 등은 따로 보내기 때문에 한계가 있다.
클레임 토큰 기반은 사용자 정보나 데이터의 메타데이터를 토큰에 모두 담고 있어 상태관리를 쉽게할수있다.
JWT
JWT(JSON Web Token)는 그런 클레임 토큰들 중에서 JSON 형식의 클레임 토큰을 말하고, RESTful APIs나 OAuth에서 거의 표준처럼 많이 사용되고 있다.
세션이나 JWT나 결국엔 요청때마다 유효한 인코딩된 정보를 서버에 보낸다. 세션 같은 경우에는 쿠키에 sessionId를 담아서 요청하고 JWT는 HTTP Authorization 리퀘스트 헤더에 담아 보내는 차이가 있는 것이다.
중요한 건 세션 같은 경우엔 서버에서 sessionId를 가지고 세션 디비에서 사용자 정보를 찾는다. 때문에 수 많은 사용들이 한번에 어플리케이션에 요청을 하면 서버 메모리에 무리가 갈 것이다. 하지만 JWT는 디비를 뒤적이는 게 아니라 secret key를 이용해 복호화하는 알고리즘 방식이다. 그렇기 때문에 세션 기반은 아무래도 디비를 한번 거치기 때문에 비교적 JWT가 복호화하는 것보다 느리다.
앞서 이야기 했던 토큰이 세션의 단점을 완화시킬 수 있다는 것은 토큰은 확장성이 크기 때문이다. JWT는 사용자 정보를 얻기위해 디비를 거치지 않아도 되고, JWT가 ACCESS_TOKEN_SECRET를 통해서 복호화되면서 바로 사용자 정보를 얻게 된다. 이때 JWT는 ACCESS_TOKEN_SECRET만 여러 서버에 공유하면서 스케일아웃이 가능해진다.
이것을 두고 확장성이 크다고 하는데, 세션 기반이라면 디비에 있는 sessionId를 모두 카피해야하거나 모든 서버가 공통의 세션디비를 공유해야기 때문에 확장성이 낮다고 한다.
스케일아웃에 쉬운 ACCESS_TOKEN_SECRET 관리
여기까지 쿠키, 세션, JWT 에 대해 기본적인 비교를 해보았다.
결국 JWT를 쿠키와 세션과 비교하는 것은, 세션-쿠키 기반 인증과 토큰기반 인증을 비교하는 것이 의미 있다는 것을 알았을 것이다.
세션-쿠키 기반 인증
JWT가 나오기전에는 주로 이 인증 방식을 사용했다. 세션 기반은 서버에서 인증 과정이 모두 이루어지기 때문에 클라이언트는 요청을 보낸 뒤 서버 사이드에서 어떤 일이 일어나는지 알수 없다.
로그인을 예로 들어보자. 유저가 로그인을 하면 서버는 그 유저에 대해 sessionId를 만들어 세션DB 안에 저장한다. 그리고 그 sessionId를 헤더 Set-Cookie
에 담아 클라이언트로 보낸다.
유저가 브라우저에서 이런저런 활동을 하는동안에도 브라우저 내 쿠키에는 이 세션아이디가 cookie storage 라는 곳에 저장되어 있다. 그리고 요청할때마다 세션아이디가 담긴 쿠키를 같이 보낸다. 유저가 로그인 할 때는 서버는 세션DB에 저장되어있는 sessionId를 가지고 쿠키에 있는것과 비교하여 인증할 수 있다. 끝으로 유저가 로그아웃하면 세션 데이터가 서버에서 삭제되어진다.
JWT 토큰 기반 인증
JWT 토큰 기반인증은 앞서 말했듯, OAuth나 RESTful API에서 주로 사용되어지는 인증 방법이다.
로그인 인증 후에 서버는 ACCESS_TOKEN_SECRET을가지고 userId와 expiresIn을 암호화하여 accessToken을 생성한다. 그리고 accessToken을 클라이언트로 보내고, JWT는 브라우저(클라이언트)의 localStorage나 cookie에 저장된다. 서버가 요청을 수신하면 모든 요청에 대해 JWT가 해당 특정 사용자에게만 해당하는지 확인한 다음 필요한 응답을 클라이언트에 다시 보낸다.
중요한 점은 accessToken은 세션DB에 저장되어지지 않는다.
JWT는 .
을 기준으로 아래와 같이 Header, Payload, Signature 세 파트로 나뉘어지는데, 자세한 특징은 공식 레퍼런스를 참고하자.
xxxxx.yyyyy.zzzzz
어떤 것을 사용해야 하나?
현대 웹 애플리케이션에서 JWT는 세션 쿠키보다 확장성이 뛰어나서 널리 사용된다. 토큰은 클라이언트 측에 저장되는 반면 세션은 서버 메모리를 사용하여 데이터를 저장하기 때문이다.
나또한 스스로 판단할만큼의 인사이트를 얻은 것은 아니지만, 주변의 정보에 의하면 무조건적으로 JWT만을 실무에서 쓰는 것은 아니며 둘다 사용하거나 세션을 사용한다면 스토리지를 구성하고, 보통 레디스를 많이 쓴다고 한다.
참고
- https://hackernoon.com/using-session-cookies-vs-jwt-for-authentication-sd2v3vci
- https://medium.com/@prashantramnyc/difference-between-session-cookies-vs-jwt-json-web-tokens-for-session-management-4be67d2f066e
- https://interconnection.tistory.com/74
- https://yonghyunlee.gitlab.io/node/jwt/
- https://guides.dataverse.org/en/latest/api/auth.html
- https://elfinlas.github.io/2018/08/12/whatisjwt-01/
- https://stackoverflow.com/questions/37582444/jwt-vs-cookies-for-token-based-authentication
- https://velog.io/@0307kwon/JWT%EB%8A%94-%EC%96%B4%EB%94%94%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C-localStorage-vs-cookie
- https://github.com/java-squid/2022-jubilant/pull/11
'기술과 생각 > HTTP 일반' 카테고리의 다른 글
하이브리드앱에서 자동로그인 기능으로 보는 세션이 아닌 JWT의 필요성 (2) | 2022.06.09 |
---|