이번 포스팅에서는 Session과 JWT의 차이점, 장단점에 대해서 포스팅하고, 다음 포스팅에서 내가 이해한 React + Express로 JWT를 구현하는 방법에 작성하려고 한다
Session VS JWT
Session-based Authentication
-
세션은 브라우저와 웹 서버가 연결되어 브라우저가 종료될 때까지의 시점이다. 브라우저를 통해 서버에 접속할 때 서버는 세션 id를 쿠키에 담아 되돌려주고, 사용자는 세션 id를 담은 쿠키인 세션 쿠키를 이 후 요청부터 계속해서 함께 전달함으로 서버가 클라이언트를 식별할 수 있게 하는 기술이 세션 기반 인증 방식인데 보통 세션이라고 한다.
-
클라이언트가 HTTP요청을 보낼 때 쿠키에 세션 id가 없다면 서버는 세션 id를 생성 해 쿠키에 담아서 돌려준다. 다시 HTTP 재요청을 할 때 쿠키를 보내기 때문에 서버에서는 세션 id를 통해 클라이언트를 식별할 수 있는 것이다.
전체적인 Flow는 다음과 같다.
- 로그인시 제출한 아이디, 비밀번호가 DB에 저장된 회원정보와 맞다면 세션스토어에 Session을 하나 만들어서 저장한다. (여기서 세션스토어는 DB가 될 수도 있고 서버 메모리가 될 수도 있음) Session은 쉽게 말해서 Client가 언제 어디서 로그인 했는지에 대한 정보를 담은 자료이다.
- 로그인 한 유저마다 각각 유니크한 세션아이디를 발급한다.
- 발급한 세션아이디는 쿠키에 담아서 고객 브라우저에 전송해준다. 세션아이디는 고객과 서버 둘다 보관한다. (쿠키란 브라우저에 마련되어 있는 작은 문자데이터 저장공간이다. 여기에 세션아이디가 abc123 이렇게 기록이 된다.)
- 이제 Client가 myPage와 같은 로그인이 필요한 페이지를 접속하고자 한다면 페이지를 보여주기 전에 로그인을 하였는지를 확인하는 미들웨어를 실행합니다.
- 고객이 페이지를 요청할 때 마다 자동으로 쿠키가 서버로 전송되게 되는데, 서버는 쿠키에 기록된 세션아이디를 세션스토어(서버메모리 or DB)에 저장되어 있던 세션아이디와 비교해서 있으면 마이페이지를 보여준다.

장점
- 서버에서 클라이언트의 상태를 유지하고 있으므로, 사용자의 로그인 여부 확인이 용이하고, 경우에 따라서 강제 로그아웃 등의 제재를 가할 수 있다.
- 클라이언트가 임의로 정보를 변경시키더라도 서버에서 클라이언트의 상태 정보를 가지고 있으므로 상대적으로 안전하다.
단점
- 서버에서 클라이언트의 상태를 모두 유지하고 있어야 하므로, 클라이언트 수에 따른 메모리나 DB 부하가 심하다.
- 사용자가 많아지는 경우 로드 밸런싱을 통한 서버확장을 이용해야 하는데 이때 세션관리가 여려워진다.
- 웹 브라우저에서 세션 관리에 사용하는 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어 CORS 방식(여러 도메인에 request를 보내는 브라우저)을 사용할 때 쿠키 및 세션 관리가 어렵다.
- 멀티 디바이스 환경(모바일, 브라우저 공동 사용 등)에서 로그인 시 중복 로그인 처리가 되지 않는 등의 신경 써줘야 할 부분들이 생긴다.
JSON Web Token (JWT)
- 토큰 방식은 세션데이터를 서버에 저장하지 않고, 마이페이지를 열람할 수 있는 열쇠(토큰)을 사용자에게 쥐어주는 것이다.
- 따라서 토큰에는 session 방식보다 더 많은 정보가 들어간다. (이름, 아이디, 유효기간 등)

- JWT 토큰에는 Header, Payload, Signature 구조로 이루어져 있다. JWT는 암호화되지 않아서 쉽게 Decoding이 가능하기 때문에 Payload(Data)에는 최소한의 정보만 담아야 한다.
전체적인 Flow는 다음과 같다.
- 로그인시 제출한 아이디와 비밀번호가 DB에 저장된 회원정보와 맞다면 서버는 Token을 하나 만들어서 고객 브라우저로 보낸다.
- 클라이언트가 마이페이지를 요청하면 서버는 마이페이지를 보여주기위해서 토큰 검사를 수행한다. 고객이 마이페이지 요청시 함께 보낸 Token이 적법한지 등을 검사한다. 유통기한이 지나지는 않았는지, Signature는 올바르게 되어 있는지 등의 검사를 거친 후 이상이 없으면 마이페이지를 보여준다.

장점
- stateless하다. 서버측 부하를 낮출 수 있고 독립적이기 때문에 능률적으로 접근 권한관리를 할 수 있고 분산/클라우드 기반 인프라 스트럭처에 잘 대응할 수 있다.
- 별도의 인증 저장소가 필요하지 않다. 인증서버와 db에 의존하지 않아도 된다.
단점
- JWT는 Decoding이 매우 쉽다. 민감한 유저의 정보는 집어넣지 않는다. 최소한의 정보만 넣어야함.
- Signature의 SecretKey를 때려 맞추기 매우 쉽다. 이를 brute force attack이라 한다. 따라서 SecretKey를 매우 길고 보안성이 뛰어나게 설정해야한다. 보안성을 더욱 더 신경쓰고 싶으면 생성용키와 검증용키를 사용하여 운영한다. (JWT 라이브러리 이용)
- JWT가 수명이 길어서 제 3자에게 탈취당할 경우가 발생할 수 있다. 그런데 JWT는 서버가 발급하고 나면 JWT를 관리하지 않기 때문에 유효기간이 끝날때 까지 해커는 계속 사용이 가능하다. 이를 보완한 방법 중 하나로 access token & refresh token 방식이 있는데 두개의 토큰 모두 JWT이다.
RefreshToken & AccessToken
access token & refresh token 방식은 토큰들에 유효기간을 주어서 보안을 강화시킨 것이다. access token은 유효기간이 짧은 토큰이고, refresh token은 access token보다 유효기간이 긴 토큰이다.
- 사용자가 로그인을 하면 서버로부터 access token, refresh token 2개의 토큰을 받는다. 이때 서버는 refresh token을 안전한 저장소에 저장한다.
- 서버로부터 받은 access token의 유효 기간이 지나지 않은 경우 사용자가 어떤 요청을 보낼 때 access token을 함께 보내고 서버는 유효한 지 확인 후 응답을 보낸다.
- 서버로부터 받은 access token의 유효 기간이 지난 경우 사용자는 refresh token과 함께 요청을 보내고, 저장소에 저장되어 있던 refresh token과 비교한 후에 유효하다면 새로운 access token과 응답을 함께 보낸다.
참고
https://millo-l.github.io/Session-%EA%B8%B0%EB%B0%98-%EC%9D%B8%EC%A6%9D%EB%B0%A9%EC%8B%9D/
https://80000coding.oopy.io/1f213f10-185c-4b4e-8372-119402fecdd0
https://velog.io/@gotaek/%EC%84%B8%EC%85%98Session%EA%B3%BC-JWT