Backend/프로젝트

JWT(JSON Web Token)와 세션 방식을 쉽게 비교해보자

동구름이 2023. 5. 30. 15:10

 프로젝트 진행 중 회원 기능을 구현하기 위해 JWT 인증 방식을 도입하기로 했습니다.

 

 그런데 세션 방식에 비해 어떤 이점이 있기에 JWT를 많이 쓰는 것인지, 개발하는 입장에서는 사용자의 정보를 가져올 때, 세션이든 JWT든 어디서든 가져오기만 하면 되는 것 아닌가? JWT 토큰 보안이 잘 이루어지는게 맞는지? 같은 여러 의문이 생겼습니다.

 

 이번 포스팅에서 그 의문점에 대해 정리해보겠습니다.

 

 

1. 세션 방식과 JWT 방식 비교

 우선 서버에서 사용자를 어떻게 인증하는지에 대해 살펴보겠습니다.

 

 만약 한 웹 사이트를 만들었다고 가정하겠습니다. 이 웹사이트에서 로그인한 사람만 웹 사이트를 구경할 수 있게 하고 싶다면 어떻게 해야할까요?

(출처 : https://oopsys.tistory.com/277)

 

 보통 세션 방식(좌)과 JWT 방식(우) 두 가지를 제시합니다.

 

 두 가지 방식의 동작 과정은 매우 유사합니다. 사용자가 로그인을 하는 순간 서버가 유저에게 입장할 수 있는 권한을 부여합니다. 세션 방식은 세션을 생성하고 유지하는 것으로 권한을 부여하고, JWT 방식은 토큰을 생성해 권한을 부여합니다.

 

 그리고 사이트에서 어떤 동작을 할 때, 두 가지 방식 모두 사용자가 입장할 수 있는 권한을 제시하면 서버에서 권한을 검증하고 웹 사이트에서 다음 동작이 가능하도록 응답을 해줍니다.

 

 이처럼 세션과 JWT 방식은 회원 인증 기능의 기본적인 동작 과정이 비슷합니다. 그런데 세션 방식과 JWT 방식은 입장 권한에 대한 내용이 조금 다릅니다.

 

 

(1) 세션을 통한 사용자 인증

 세션에 대한 정보는 Key/Value형태로 서버의 세션 저장소에 저장이 됩니다. 그리고 브라우저에서는 Key값(세션 식별자)만 가지고 있도록 합니다. 이 식별자는 보통 쿠키를 통해 저장됩니다.
(쿠키에 대한 포스팅은 HTTP에서 다루었습니다.  바로가기 페이지 하단 참조)

 

 세션을 통해 입장 시, 사용자는 세션 식별자(Key)를 서버에 제시하게 됩니다. 그러면 서버의 세션 저장소를 조회하여 세션 식별자(Key)값을 조회해 인증이 되어있는 사용자인지를 조회합니다. 조회하고 문제가 없다면 유저 인증을 해주는 방식입니다. 

 

(2) JWT 를 통한 사용자 인증

 반면 JWT 에는 세션과 달리, 사용자에 대한 여러 정보들이 포함됩니다. (이메일, 이름, 유효기간 등등)

 

JWT는 사용자의 많은 정보를 JSON 형식으로 인코딩하여 토큰으로 생성합니다. 그리고 서버에 접근할 때, JWT 자체만 확인하고 유효기간, 서명 등이 이상이 없으면 유저인증을 해주는 방식입니다.

 

 

 

정리

 그래서 세션과 JWT 방식의 가장 큰 차이점은 세션 방식이 서버 측에 사용자의 정보를 저장하고 관리하는 반면, JWT 방식은 클라이언트 측에서 사용자의 정보를 저장하고 관리한다는 점입니다.

 

쉽게 말해, 두 가지의 차이는 세션 방식은 세선 저장소에서 조회를 통해 검증을 해야하지만, JWT는 토큰 그 자체로 검증이 가능한 것입니다.

 

 

 그래서, JWT 방식의 장점은 회원이 매우 많더라도 서버에 부담을 줄일 수 있습니다.

 

 왜냐하면 기존의 세션 방식은 사용자가 세션 식별자를 제시할 때마다, 서버의 세션 저장소를 조회해야하는 문제가 생깁니다. 예를 들어 회원이 천 만명이라면 그에 해당하는 정보를 모두 서버에 저장해야합니다.

 

 반면 JWT는 토큰 자체에 사용자 정보를 포함하고 있어서 추가적인 데이터베이스 조회 없이도 사용자를 인증할 수 있습니다. 즉, JWT는 사용자의 토큰 자체만 확인하면 됩니다.

 

 

 

위 장점과 반대로, 세션은 서버 측에서 관리되므로 일반적으로 보안에 더 강력하다는 장점이 있습니다. 하지만 JWT 방식은 여러 가지 보안 이슈를 고려해야만 합니다.

 

 

2. JWT 보안에 있어 신경써야할 점

 우선 JWT 는 아래와 같은 구조로 생겼습니다. header, payload, signature가 들어갑니다.

JWT에서 중요한 것은 가운데의 payload를 모두가 볼 수 있다는 점입니다. 그래서 password와 같은 민감한 정보를 넣어서는 안됩니다. 

 

https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

 

위 사이트에서 JWT 를 만들어 볼 수 있습니다.

 

JWT를 만들 때 주의해야할 점은 alg 를 none으로 적는 경우가 많습니다. 반드시 알고리즘의 방식을 지정해주어야합니다.

 

그리고 JWT 강의들을 보면 Signature 부분에 예시로 secret을 적는 경우가 많은데, 그걸 따라서 secret이라고 적거나 짧은 문자열로 적게되면, 브루트포스 어택에 쉽게 뚫릴 수 있습니다. 만약 secret key를 강탈 당하면 JWT를 마음대로 발행할 수 있어서 매우 위험합니다. 

 

 

 

JWT의 취약점은 다음과 같습니다. 

 

(1) Payload 디코딩

JWT는 디코딩이 매우 쉽습니다. Payload 자체는 암호화된 것이 아니라, encoding이 된 것이기 때문에, JWT가 탈취되어 decoding으로 개인 정보를 열어볼 수 있습니다. 그래서 Payload에는 민감한 유저 정보를 넣어서는 안됩니다.

(2) Stateless

JWT을 임의로 삭제할 수 없다는 것입니다. 

 

 만약 어떤 사람이 다른 유저의 JWT를 탈취한다고 생각해보겠습니다. 서비스 개발자 입장에서는 이를 대비해서 JWT 토큰을 사용 정지한다던지, 그런 조치를 취해줄 수 있어야하는데 JWT는 stateless, 상태를 저장하지 않기 때문에 그런 조치를 취하기가 불가능합니다.

 

 그래서 이를 대비한 방법이 몇 가지가 있습니다.

 

우선 첫째로, TTL을 정해주는 것입니다. 유효기간을 정해 JWT를 탈취당하더라도 일정 시간이 지나면 사용 불가능하게 만들어야합니다. 이런 방식에서는 refresh token을 통해 입장권 재발급의 기능을 추가해주어야합니다. 

 

 두 번째는, 강탈 당한 토큰의 블랙리스트를 저장하는 것입니다. 특정 입장권들은 입장 권한을 제외시키는 것입니다. 하지만 이런 방식은 세션 방식과 동일해진다는 단점이 있습니다.

 

 

 

 결론적으로, 대부분의 서비스에서는 간단히 세션 방식으로 회원을 인증을 구현하는 것을 추천하지만, 회원이 매우 많아 DB에서 입장 권한을 체크하는 것이 어려운 경우 등에는 JWT를 사용하는 것이 좋습니다.

 

 하지만 위의 취약점들로 인해 보안이 중요한 서비스에서는 세션 방식을 섞는다던지, 다른 업체의 인증 서비스를 이용하는 방식 등을 사용하는 것으로 알고 있습니다.

 

 

 

 

 

참고자료

토큰 저장 위치
https://velog.io/@fe_jungseok/%ED%86%A0%ED%81%B0-%EC%A0%80%EC%9E%A5%EC%9C%84%EC%B9%98

알고 쓰자, JWT(Json Web Token)
https://velog.io/@chuu1019/%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-JWTJson-Web-Token

서버 기반 인증 & 토큰 기반 인증 이해하기
https://oopsys.tistory.com/277

JWT token이란?
https://blog.naver.com/ds4ouj/222691400394