본문 바로가기

플밍 is 뭔들/그 외..

[JWT] JSON Web Token - 서버기반/토큰기반 인증의 차이와 JWT의 장단점

※ 서버 기반 인증
기존의 인증 시스템에서는 서버측에서 유저들의 정보를 세션에 기억하고 있어야 합니다. 이 세션을 유지하기 위해서는 여러가지 방법이 사용되는데 메모리/디스크/데이터베이스 시스템에 이를 담곤 합니다. 서버 기반 인증 시스템의 흐름은 다음과 같습니다.
 
 
  • 서버 기반 인증의 문제점
- 세션 : 유저가 인증을 할 때 이 기록을 서버에 저장해야 하는데 이를 세션이라 합니다.  보통은 메모리에 이를 저장하는데, 로그인 중인 유저의 수가 늘어난다면 서버의 램에 과부화가 될 수 있습니다. 데이터베이스에 저장하는 방식도 있지만 이 또한 유저의 수가 많으면 데이터베이스의 성능에 무리를 줄 수 있습니다.
            
- 확장성 : 세션을 사용하면 서버 확장이 어렵습니다. (단순 서버 사양 업그레이드 뿐 아니라 더 많은 트래픽 감당을 위해 프로세스를 여러개 돌리거나 여러대의 서버 컴퓨터를 추가하는것) 세션을 사용하면서 분산된 시스템 설계가 불가능한건 아니지만 과정이 매우 복잡합니다. 
 
- CORS (Cross-Origin Resource Sharing) : 웹 어플리케이션에서 세션을 관리 할 때 자주 사용되는 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어있습니다. 따라서 쿠키를 여러 도메인에서 관리하는것은 좀 번거롭습니다.
 
※ 토큰 기반 인증
토큰 기반 시스템은 stateless합니다. 유저의 인정 정보를 서버나 세션에 담아두지 않기 때문에 인정정보를 서버에 담아둠으로써 발생하는 많은 문제점들이 해소됩니다. 토큰 기반 인증 시스템의 흐름은 대력적으로 다음과 같습니다.
 
 
  1. 유저가 아이디/비밀번호로 로그인
  2. 서버측에서 해당 계정정보 검증
  3. 계정정보가 정확하다면 서버측에서 유저에게 signed토큰을 발급 (signed토큰 : 해당 토큰이 서버에서 정상적으로 발급된 토큰임을 증명하는 signature를 지니고 있음)
  4. 클라이언트 측에서는 전달받은 토큰을 저장해두고 서버에 요청할 때 마다 해당 토큰을 함께 서버에 전달
  5. 서버는 토큰을 검증하고 요청에 응답
 
※ JWT의 장점
 
무상태(stateless)이며 확장성이 있다.
기존 서버에 세션을 저장하는 방식에서 서버 여러대를 사용하여 요청을 분산하였다면 어떤 유저가 로그인했을 때 그 유저는 처음 로그인한 서버에만 요청을 내보내도록 설정해야합니다. 하지만 토큰을 사용하면 토큰 값만 알고 있다면 어떤 서버로 요청이 들어가던 상관이 없습니다.
 
보안성
쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라집니다. 
 
여러 플랫폼 및 도메인
어플리케이션 규모가 커지면 여러 디바이스를 호환 시키고 더 많은 종류의 서비스를 제공합니다. 토큰을 사용한다면 그 어떤 디바이스에서도 그 어떤 도메인에서도 토큰만 유효하다면 요청이 정상적으로 처리 됩니다. 
 
 
※ JWT의 단점
 
길이
claim에 넣는 데이터가 많아질 수록 JWT토큰이 길어집니다. API호출 시 매 호출마다 토큰 데이터를 서버에 전달해야 하는데 길이가 길다는 것은 그만큼 네트워크 대역폭 낭비가 심할 수 있습니다.
 
한번 발급된 토큰은 값 수정 및 폐기가 불가
JWT는 토큰 내에 모든 정보를 다 가지고 있기 때문에 한번 발급된 토큰에 대한 변경은 서버에서는 더 이상 불가능합니다. 토큰을 잘못 발행하여 삭제하고 싶더라도 Signature만 맞으면 맞는 토큰으로 인식하기 때문에 서버에서는 한번 발급된 토큰의 정보를 바꾸는 일 등이 불가능 합니다.
그래서 JWT를 쓴다면 Expire time을 꼭 명시적으로 두도록 하고 Refresh Token을 이용하여 중간중간 토큰을 재발행 하도록 해야합니다.
 
보안
JWT는 기본적으로 Payload에 대한 정보를 암호화 하지 않습니다.  단순히 BASE64로 인코딩만 하기 때문에 중간에 패킷을 가로채거나 기타 방법으로 토큰을 취득했으면 디코딩을 통해 데이터를 볼 수 있습니다.
그래서 JWE(JSON Web Encryption)를 통해 암호화 하거나 중요데이터를 Payload에 넣지 말아야 합니다.