프로젝트 지식(3) - 세션 vs 토큰

1 minute read

인증(Authentication) vs 인가(Authorizaion)

인증은 내가 이 사이트에 가입된 회원임을 아이디와 패스워드를 통해서 인증을 받는 것이다. 반면 인가는 인증을 받은 사용자가 본인의 계정으로만 할 수 있는 서비스를 이용할 때 서버가 로그인 되어있는 상태를 보고 서비스 이용을 허가해주는 것이다. 즉 로그인이 유지되는 상태에서 일어날 수 있는 일을 말한다.

세션(Session) vs 토큰(Token)

JWT는 인증보다는 인가에 관련된 개념이다.

우선 전통적인 방식인 세션은 사용자가 로그인에 성공하면 서버가 세션을 출력한다. 그래서 이 중 반쪽은 사용자의 브라우저에, 나머지 반 쪽은 자신의 메모리에 올린다. 그렇다면 브라우저가 이를 세션 ID란 이름의 쿠키로 저장하고 브라우저는 앞으로 다음 사이트에 요청을 보낼 때마다 이 세션 ID를 실어보낸다. 서버는 이 요청을 통해 나머지 반 쪽과 비교하여 허가를 한다. 하지만 이는 메모리가 날아가면 다시 로그인을 해야하거나 서버가 여러 대 있으면 세션 유지가 제대로 안되는 치명적인 문제가 있다.

이러한 문제를 해결하고 부담없이 인가를 하기위해 고안된 것이 바로 토큰 방식인 JWT(JSON Web Token)이다. 이 역시 사용자가 로그인을 하면 토큰을 발행한다. 하지만 이번에는 서버가 반 쪽을 보관하지 않는다.

토큰을 살펴보면 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c처럼 인코딩된 데이터 3가지가 .을 기준으로 이어붙어 있다. 각각 header(헤더), payload(페이로드), verify signature(서명)로 구분된다.

먼저 페이로드부터 디코딩해서 살펴보면 JSON 형식으로 누가 누구에게 발급했는지, 언제까지 유효한지, 서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용 등의 Claim이 들어있다.

하지만 이렇게 되면 사용자가 임의로 토큰의 값을 디코딩하여 조작할 수 있게 되는데 이를 방지하기 위해 헤더와 서명 부분이 존재한다. 헤더에는 타입이 JWT임을 확인하는 타입과 서명 값을 만드는데 사용되는 alg(알고리즘)이 지정된다.

그러면 서버는 요청에 토큰 값이 실려오면 헤더와 페이로드의 값을 서버의 비밀 키와 함께 돌려봐서 계산된 결과값이 서명 값과 일치하는 결과가 나오는지 확인한다.

하지만 안타깝게도 세션을 대체하기에는 JWT는 큰 결점이 있다. 세션은 구현하기 부담되고 고려사항도 많지만 사용자의 상태를 기억하고 있기 때문에 사용자를 제어할 수 있다. 예를 들어 한 사용자가 한 기기에서만 로그인되게 하려면 세션을 이용해 이를 해결할 수 있다. 반면 JWT는 서버가 사용자를 제어할 수 있는 방법이 없다.

이러한 문제를 해결하기 위해 짧은 유효기간을 가지고 있는 access 토큰과 새로운 access 토큰을 발급할 수 있게 해주는 긴 유효기간을 가진 refresh 토큰 2개를 활용하기도 한다. 하지만 세션 방식을 완전히 보완할 수는 없기 때문에 JWT만으로 인가를 구현하는 곳은 거의 없다. 따라서 자신이 구현하려는 서비스의 성격을 잘 파악하여 인가방식을 적절히 사용해야 하겠다.

Reference

세션 VS. 토큰! JWT가 뭔가요?

Leave a comment