현대 서비스는 사용자의 인증과 권한 등의 관리가 필수이다.

이러한 정보를 안전하게 유지 및 관리하고 리소스 낭비 없이 인증 상태를 유지하려면 어떻게 해야 할까요?
이때 등장하는 것이 바로 JWT (JSON Web Token) 입니다.

세션 방식은 서버가 사용자마다 세션 데이터를 메모리나 DB에 저장해야 한다.

JWT는 인증 정보를 클라이언트가 체적으로 보유하고 전송하기에 서버는 상태를 유지할 필요 없음.

수평 확장성(Scale-out)에 유리하고, 로드밸런서 환경에서 세션 공유 없이도 인증 가능하다.

(하지만 블랙리스트 관리 or RefreshToken으로 인해 Redis같은 곳에 저장하기도 함, 하지만 기본적으로는

세션 상태를 저장하지 않아도 되는게 원칙)

 

하지만 가장 큰 차이점은 인가과정에 있다. 세션은 서버의 세션 저장소에 해당 인증 내용을 담지만, JWT 토큰은 

토큰 자체에 담고있다. 요청이 왔을때 토큰만 확인하면 되므로 간단히 인가 과정을 거칠 수 있다. 

 

세션과 JWT의 차이점

 

✔  세션은 서버 메모리/DB에 인증정보를 저장하지만 JWT는 클라이언트의 토큰에 저장한다.

  - 서버가 인증 상태를 기억할 필요가 없음 → 메모리/DB 부하 감소

  - 인증 상태 유지를 위한 별도 저장소(세션 저장소, DB 등)를 구성할 필요가 없음

 

✔ 세션은 Stateful하게 상태유지를 하지만 JWT는 Stateless하다.

  - 서버는 이전 상태를 기억할 필요가 없어서 토큰만 보고 처리가 가능하다.

 

✔ 세션기반은 서버확장시에 세션 공유 및 동기화가 필요하지만 JWT는 확장이 쉽다.

  - 무장단 서버확장이 가능하고, 세션 동기화가 필요없다.

 

✔ 세션기반은 세션을 통해 DB 조회가 들어가지만, JWT는 서명검증으로 즉시 처리가 된다.

  - JWT는 자체적으로 서명된 정보를 포함하고 있어서 서버는 DB를 보지 않아도 유효성 판단 가능

  - DB 부하 최소화 (세션 정보 조회 불필요) , 요청 처리 속도 향상 → 전체 시스템 성능 개선

 

세션에 비해 JWT가 가지는 단점

 

✔ 토큰 탈취 시 대응 어려움 및 상태를 세션처럼 기억하지 못함

  - JWT는 한 번 발급되면 서버가 강제로 무효화할 수 없음 --> Redis를 통한 블랙리스트 관리 및 refresh 토큰으로 보완

    

✔ 세션은 서버가 사용자의 인증상태를 완전히 통제 가능 (접속 제한, 강제 로그아웃, 중복 로그인 차단 등)

 

✔ 설계가 세션에 비해 복잡하다

  - 토큰 발급 및 만료 관리 refresh 토큰 발급 등 고려요소가 많음.

 

Access Token : 실제 유저정보가 담긴 토큰으로 이 토큰을 통하여 검증이 이루어진다. (클라이언트가 소지한다.)

 

RefreshToken : 짧은 유지 시간을 가지는 Access 토큰을 재발급하기 위해 사용되는 토큰으로 보통은 인메모리 

데이터베이스에 저장하고 관리한다.

 

 

* JWT가 세션보다 보안이 더 뛰어난건 아니다. 근데 내가 생각했을때 굳이 세션을 안쓰고 jwt를 쓰는 이유는

  일단 토큰자체로 검증을 편리하게 할 수 있는것이라고 생각한다.

  세션이나 jwt나 둘다 Redis를 실무에서는 거의 사용한다고 하면 jwt도 확장성은 어차피 떨어지는거 아닌가?

  세션은 모든 요청마다 Redis or DB 부하가 발생한다는 것이다. 저장소가 터져버리면 먹통이 된다.(의존적)

  하지만 JWT는 AccessToken자체로 인증이 가능하고 Refresh Token으로 재발급 하거나 블랙리스트를 관리

  할때만 부하가 생긴다. 세션에 비해서 항상 의존적이지 않다는게 가장 큰 차이점인 것 같다.

  즉 이러한 차이점으로 인해 인증 및 인가 속도면에서는 JWT가 더 빠르다고 생각한다. 

 

결론

* 보안 통제, 실시간 세션 제어 위주의 서비스다 -> 세션이 유리하다고 봄

* 확장성, 트래픽 감당, 모바일 중심  -> JWT가 유리하다고 본다.

 

🔴 JWT의 특징  (https://jwt.io/ 여기에 잘 나와있어서 첨부)

json 객체로 안전하게 전송하기 위한 토큰,  디지털 서명을 근간으로 작동한다.
핵심은 서명된 토큰에 중점이 된다.
서명된 토큰은 그 안에서 해당 서명에 대한 무결성을 보장해준다.

 

해당 페이지에 가보면 RFC 7519라는 문서에 정의되어있다고 한다.

RFC는 나도 잘 모르지만 찾아보니 JWT(JSON Web Token)의 공식 규격 문서
JWT 토큰의 구조, 사용 방법, 보안 고려사항 등을 국제 표준으로 정리한 문서라고 한다.

 

* RFC : 인터넷 기술 표준 문서

 

🔴 JWT의 구조

JSON 웹 토큰은 압축된 형태로 점( .)으로 구분된 세 부분으로 구성되며 각 부분은

아래와 같이 나뉜다.

  • Header (헤더)
  • payload (유효 탑재량)
  • signature (서명)

따라서 JWT는 일반적으로 다음과 같습니다.

xxxxx.yyyyy.zzzzz

 

✔ Header 

{
  "alg": "HS256",
  "typ": "JWT"
}

 

위와 같이 생겼으며 어떤알고리즘이 사용되고 어떤 타입인지 명시한다.

이 JSON은 Base64Url 로 인코딩되어 JWT의 첫 번째 부분을 형성한다.

 

✔ payLoad

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

 

위와 같이 생겼으며, 3가지의 클레임이 있는것같다 근데 개인 클레임이 중요한데 사용에 동의하고 사용자의 정보를 공유하기 위해 생성된 사용자 지정클레임이다.

 

공개 클레임 : JWT를 사용하는 사람들이 자유롭게 정의할 수 있습니다. 하지만 충돌을 피하기 위해 IANA JSON 웹 토큰 레지스트리 에서 정의하거나 충돌 방지 네임스페이스를 포함하는 URI로 정의해야 합니다.
        

등록된 클레임 : 이는 필수는 아니지만 권장되는 사전 정의된 클레임 세트로, 유용하고 상호 운용 가능한 클레임 세트를 제공합니다. 일부는 다음과 같습니다. iss (발급자), exp (만료 시간), sub (주체), aud (청중) 및 기타

 

개인 청구 : 이는 당사자 간에 정보를 공유하기 위해 작성된 맞춤형 청구로, 이를 사용하는 데 동의한 당사자 간에 정보를 공유하기 위해 작성되며 등록되지 않았 거나 공개된 청구가 아닙니다.

 

* https://jwt.io/introduction  해당 사이트에서 발췌

 

페이로드는 Base64Url 로 인코딩되어 JSON 웹 토큰의 두 번째 부분을 형성

 

✔ signature

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

 

위와 같이 생겼으며 결국 Base64UrlEncode(header) + . + Base64UrlEncode(payload) 로 구성된 문자열을
서버만 알고 있는 secret 키로 HS256(HMAC SHA-256) 알고리즘을 사용해 서명하고,
그 결과를 Base64Url 인코딩한 것이 바로 signature이다

 

* HS256(HMAC SHA-256) : 대칭키(HMAC) 방식으로, SHA-256 해시 함수를 이용해
메시지의 위조 여부를 확인할 수 있는 빠르고 안전한 서명 알고리즘이다.

여기서 대칭키가 나만의 시크릿키라고 볼 수 있다. (서버만 알아야 함)

 

https://develop-actas.tistory.com/77

 

[CIA와 대칭키, 비대칭키]

CIA보안 목표와 요구사항을 달성하기 위한 3요소, 즉 보안 시스템, 정책, 암호화, 인증 등의 기준 목표이자 기준  1. Confidentiality (기밀성) 허가되지 않은 사람이 데이터를 열람할 수 없도록 보호하

develop-actas.tistory.com

 

대칭키와 비대칭키 정리한 글이다. 나중에 까먹으면 다시보자

그래서 이어붙히면   최종적으로 아래와 같이 구성된다.

 

 

🔴 JWT 인증 과정

1. 사용자 로그인 시도

2. 서버에서 사용자 인증 완료후 JWT 토큰 발급 (HS256방식으로 사용자 정보를 담은 토큰을 생성하여 서명)

3. 이 토큰을 클라이언트에게 반환 ( JWT를 localStorage, sessionStorage, 또는 cookie 등에 저장 )

4. 인증이 필요한 요청시 서버에게 Authorization 헤더에 JWT를 실어서 전송

5. 서버는 헤더랑 페이로드를 똑같이 자신이 가지는 시크릿키로 암호화를 해본다 시그니처부분이랑 일치하면 검증을 완료

 

* RS265방식 : 

RS256은 Header+Payload를 개인키로 서명함
- 클라이언트는 이 JWT를 저장하고 요청에 포함시키고
- 서버는 공개키로 서명의 무결성만 검증하지, 내용을 복호화하진 않음

즉 서버는 자신의 개인키로 서명하고 나중에 검증시에 자신의 공개키로 서명 검증을한다.

 

 

세션 vs 쿠키 vs JWT 의 차이점에 관하여 아래 블로그에서 엄청 자세하게 다뤄준다.

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC

 

🌐 JWT 토큰 인증 이란? (쿠키 vs 세션 vs 토큰)

Cookie / Session / Token 인증 방식 종류 보통 서버가 클라이언트 인증을 확인하는 방식은 대표적으로 쿠키, 세션, 토큰 3가지 방식이 있다. JWT를 배우기 앞서 우선 쿠키와 세션의 통신 방식을 복습해

inpa.tistory.com

 

+ Recent posts