Back End/Spring && Spring Boot

JWT 개념과 구조, 작동 방식

Im_Hayden 2024. 6. 22. 17:49

Spring Security를 사용하여 웹 상에서의 인증/인가 작업을 구현할 때는 세션-쿠키 기반의 인증 방식을 사용한다.
하지만 이러한 인증 방식에는 몇가지 단점이 존재한다.
이러한 단점을 보완하는 인증 방식으로 JWT 인증 방식이 존재한다.
이때 JWT가 어떻게 사용되고 왜 필요한지 한번 살펴보자

✨ JWT의 개념과 필요성

세션-쿠키 기반 인증 방식의 한계

  • 세션-쿠키 기반 인증 방식에서는 클라이언트의 세션 정보를 서버의 DB에 저장한다.
    • 이 경우 클라이언트의 매 요청마다 DB를 참조해야 하므로 인증 과정이 길어진다.
    • 서비스가 확장되어 클라이언트의 수가 많아질 경우, 그만큼 서버에 저장되는 세션 정보도 많아짐으로 서버의 부담도 증가한다.
  • 세션-쿠키 인증 방식의 경우, 클라이언트는 발급받은 토큰 아이디를 쿠키에 저장한다.
    • 일반적으로 이런 쿠키 시스템은 웹브라우저에서만 지원한다.
    • 때문에 모바일 네이티브 앱 등을 사용해 인증을 받을 경우, 세션 아이디를 저장하고 전송하는 과정을 직접 구현해야하기 때문에 번거롭다.

JWT를 사용한다면 위와 같은 문제를 해결 할 수 있다.

JWT란?

JWT(Json Web Token)는 클라이언트-서버간의 인증/인가를 처리할 때 토큰을 이용하여 인증/인가를 처리하는 방식이다.
이때 사용되는 토큰을 Json Web Token이라고 한다.

JWT의 장점은 아래와 같다.

  1. 서버는 요청에 대한 권한 인증을 토큰을 통하여 처리하므로, DB를 참조할 필요가 없다.
  2. 마찬가지로 토큰을 사용하기 때문에, DB에 세션 정보를 따로 저장하지 않아도 된다.
  3. 인증에 사용되는 토큰은 다양한 방식으로 전송 가능하기 때문에, 다양한 플랫폼에서도 유연하게 동작한다.

✨ JWT의 구조

jwt는 헤더(Header), 정보(Payload), 서명(Signature) 으로 이루어져있다.
이때 각 부분은 Base64 방식으로 인코딩되며, 각 부분은 . 으로 구분된다.

  • 헤더(Header): jwt가 암호화되는 방법을 저장한다.
    • 서버는 jwt의 유효성을 검사할 때, 암호화된 서명(Signature)비밀키헤더에 저장된 방법(Alg)으로 해독 하여 유효성을 검사한다.
  • 정보(Payload): 실제로 서버에 전달될 정보를 담는다.
    • 각 정보는 키(Key) : 값(Value) 형태로 저장된다.
      • 이때 저장되는 정보 하나 하나를 클레임(Claims)이라고 한다.
      • 클레임의 종류는 아래와 같다.
        • 등록된(Registered) 클래임
        • 공개(Public) 클래임
        • 비공개(Private) 클래임
    • 페이로드는 서버가 각 클라이언트를 식별할 수 있는 정보(id, email 등)를 포함해야한다.
    • 페이로드에는 민감한 정보(password 등)을 포함시키지 않는 것이 좋다.
  • 서명(Signature): 전달받은 JWT가 유효한지 검증하기 위해 사용한다.
    • 이때 서명은 위의 헤더와 페이로드를 Base64로 인코딩한 값과, 비밀키를 가지고, 헤더에 정의된 암호화 알고리즘으로 암호화 시킨 값이다.
      • 이렇게 암호화된 값은 이후 서버에서 비밀키를 가지고 다시 해석할 수 있다.

JWT는 위와 같은 부분들로 이루어져있으며, 각 부분은 .으로 구분된다.

jwt.io에서 간편하게 jwt를 생성해볼수 있으며, 생성된 JWT의 예시는 아래와 같다.

✨ JWT의 동작 방식

JWT를 사용한 인증 과정은 다음과 같다.

이미지 출처

  1. 클라이언트가 처음 로그인, 인증을 위해 idpw를 서버에 전송한다.
  2. 서버는 db를 조회하여 해당 정보가 유효한지 검증한다.
  3. 만약 해당 정보가 유효하면, 해당 유저의 정보서버만 알고있는 비밀키를 가지고 JWT 를 생성한다.
  4. 서버는 생성된 토큰을 클라이언트에게 전달하고, 클라이언트는 해당 토큰을 저장한다.
  5. 클라이언트는 이후 서버에 요청을 보낼 때 마다 해당 토큰을 함께 전송한다.
  6. 서버는 전달받은 토큰이 유효한지 검증한다.
    • 이때 검증할때는 서명 값을 사용하여 검증한다. 검증 과정은 아래와 같다.
      1. 토큰의 헤더에 저장된 암호화 알고리즘을 참조함
      2. 토큰의 서명값을, 위의 암호화 알고리즘비밀키를 사용하여 해석
      3. 해석된 서명값이 유효한지 검증
  7. 만약 해당 토큰이 유효한 토큰이면, 서버는 요청에 알맞은 응답을 한다.

✨ JWT의 단점

JWT가 다양한 장점을 가진것은 맞지만, 그렇다고 만능인 것도 아니다.
JWT의 한계는 아래와 같다.

  • 이전에 발급한 토큰에 대한 제어를 할 수 없다.
    • 기존 세션 인증 방식에서는, 서버 DB에 저장된 세션 정보를 처리하면 되었지만, JWT에서는 불가능하다.
    • 이러한 문제를 위해 토큰의 유효기간을 짧게 설정하는 등의 방법을 사용한다.
  • 토큰이 탈취될 경우 사용자의 정보가 그대로 유출된다.
    • JWT에는 사용자의 정보가 암호화되지 않고 그대로 들어있다.
    • 이 때문에 JWT를 생성할 때 비밀번호와 같은 민감한 정보는 포함시키지 않는 것이 좋다.

이처럼 JWT와 세션 방식은 서로 각각의 장점을 가지고 있기 때문에, 각 상황에 맞게 알맞은 인증 방식을 사용하는 것이 좋다.