세션 vs JWT 비교
Application에서 인증 정보를 유지할 때 사용하는 대표적인 방법은 세션(Session) 또는 JWT(Json Web Token)이다. 최근에는 이상하게도 세션이 없어져야할 방식이고, JWT로만 사용해야한다는 여론이 있어서 간략하게 정리해보고자 한다.
각 기술 이해해보기
세션의 경우, Client 쿠키에 세션의 ID를 저장해두면, Server에서 해당 쿠키를 읽고, 내부 메모리를 찾아서 세션 ID = 로그인된 User를 매칭시켜주는 방식이다.
JWT의 경우, Client에 access token을 저장하면, Server에서 디코딩하여 로그인된 User를 확인하고, 정보를 제공하는 방식이다. 이 access token은 인코딩이 되어 있지만, 인증된 user의 정보가 들어있는 것이다.
즉, 이 기술들은 사용자 인증에 사용되는 username/password, 패스키, 이메일 인증 등을 진행하여 성공하였다면, 이후에 어떻게 사용자를 기억할지에 대한 기술을 이야기한다.
쉽게 이해해보자면 찜질방에 간식 외상을 달아두는 상황이라고 하자.
매점 점원이 고객의 얼굴(세션 ID)을 통해서 기억하는 방식이 세션이다. 즉, 점원이 쉬러가고 다른 점원이 오면 미리 적어두지 않은 이상 고객을 기억하지 못할 수 있다.
최근에는 다르지 않는가!? 열쇠에 내가 누군지 저장(JWT)되고, 태깅해 사용하면, 열쇠의 데이터를 토대로 외상 처리한다. 즉, 점원이 바뀌어도 열쇠를 통해 본인을 증명한다. 열쇠를 도난 당하면 타인이 본인 행세를 할 수 있단 단점이 있다.
특징
위의 비유는 세션과 JWT의 차이를 설명해준다. 비유를 넘어 기술적으로 보자.
세션
세션은 ID를 Client 쿠키에 저장하고 특정 요청을 보낼 때 Sever에 전송된다. Client에서는 ID 값만 가지곤 누군지 알 수 없고, Server 메모리 내 Session ID : User Context 매칭을 통해서 알 수 있다.
이 ID가 악용될 소지가 있다면 서버의 매칭 테이블에서 삭제하면 된다. ID는 의미 없는 String이 된다. 즉, 인증 데이터가 서버 안에서 돌기 때문에 변조 가능성, 해킹 가능성에서 상대적으로 안전하다 할 수 있다.
다만, 수평 확장(Scale Out)에는 취약하다. 이는 동일 WAS 다수를 배포하고 앞단 LB(Load Balancer)를 통해 요청 분배한다. 그러므로 사용자가 A WAS에서 로그인을 진행했는데, 다음 요청이 B WAS로 간다며, B는 사용자를 모르기에 인증을 통과시켜 주지 않는다. 그리고, 많은 유저들이 사용한다면, 정보를 저장하기 위해 메모리의 사용이 커진다.
이런 단점을 극복하기 위해서 WAS들이 세션 정보를 공유하는 별도의 Session Storage를 갖거나 LB의 설정을 최근에 연결한 WAS로 전달되도록 한다.
JWT
JWT는 인증 성공 후 Access Token으로서 발급된다. 여기에는 토큰 종류, 서명 알고리즘 정보(헤더)와 사용자 관련 정보(페이로드)를 담고 있다. 다만, Base64Url로 인코딩 되어 있어 쉽게 디코딩할 수 있다. 중요한 부분은 서버가 비밀 키 또는 개인 키로 생성한 서명으로, 서버는 서명을 검증하여 위변조 여부와 유효성을 확인한다.
이 방법은 Client에 인증 정보를 저장하기에 서버의 메모리 부담이 적어진다. 하지만, Token을 탈취당한다면 해커가 사용자인냥 행세할 수 있다. (찜질방에서 열쇠를 잃어버렸는데 누가 주워서 외상하고 다닌 것과 마찬가지)
이런 특징을 보완하기 위해 JWT를 Access Token과 Refresh Token으로 나누어 2개로 발급한다.
왜 나뉠까? Access Token은 대부분 localStorage나 내부 Context에 저장된다. 그러므로 자연스럽게 JS에서 접근을 할 수 있다. Access Token이 탈취될 수도 있다는 것이다. 그러므로, 유효기간을 짧게하여 Access Token이 탈취가 되도 영향을 적게하는 것이다. Refresh Token은 흔히들 HTTP Only Cookie에 저장한다. HTTP Only Cookie는 JS에서 접근이 불가능한 데이터이기 때문에 상대적으로 XSS에 안전하다고 할 수 있다.
추가적으로 Token을 Revoke 한다는 개념을 도입하기도 한다. 서버 쪽에서 로그아웃 등으로 기 발급된 Token을 사용하지 않겠다는 선언을 하면, 기존 Token 정보를 저장하고, 매칭해서 거부를 하는 방식으로도 사용한다.
누가 우월한가?
위 특징을 이해하였다면, 이 단락의 질문이 옳지 않음을 알 수 있다.
세션과 JWT는 본인이 만들 Application의 상황에 맞추어서 의사결정을 해야하는 것으로 "JWT가 최근에 나온 기술이므로 JWT를 사용하는 것이 옳다!"라는 주장은 옳지 않다.
어떨 때 쓰면 좋은가?
세션
- 단일 Application(Monolithic Architecture)으로 제작할 때
- 수직 확장으로 확장하는 경우
- 사용자 수를 예측할 수 있는 경우
- 즉각적인 세션의 제어를 요구하는 경우
JWT
- MSA(Micro Service Architecture)를 사용하는 경우
- 수평 확장을 사용하는 경우
- 사용자 수를 예측할 수 없는 경우
마무리
이 글을 통해서 세션과 JWT에 대해서 이해하고 기술의 본질을 이해했으면 좋겠다.