본문 바로가기
💻Information Security

JSON과 JWT! (JSON Web Token)

by Prof. Panda 2024. 1. 14.

Ferenc Almasi on Unsplash

JSON

JSON은 JavaScript Object Notation의 약자로 자바스크립트에서 일종의 객체(object) 형식으로 데이터를 표현하기 위한 형식을 의미합니다. 즉, 자바스크립트라는 언어로 구성된 것이고, 데이터를 표현하는 방식입니다. 이름은 제이슨이라고 부르고 속성-값의 형태이고 배열식으로 되어있습니다. 속성-값(Attribute-value)의 형태라는 것은 영어를 직역했기에 이해가 쉽지 않을 수 있습니다. 예를 하나 들자면 '키'라는 속성과 '몸무게'라는 속성이 있을 수 있습니다. 누군가의 '키(height)'가 170이라면 '키(height)'라는 속성의 '값'은 170이 되는 거겠죠? 이걸 JSON 형식으로 표현하면 { "height" : "170" } 이렇게 됩니다. 이런 식으로 된 데이터의 '구조'를 JSON이라고 하면 되겠습니다.

 

ZSun Fu on Splash

Token

이제 토큰이라는 개념에 대해서 먼저 살펴보겠습니다. 토큰은 말 그대로 Token, 동전입니다. 동전을 우리는 돈으로 사용하기 때문에 의미를 헷갈리기 쉽지만, 돈 = 동전이란 원래 다른 무언가로 교환을 받을 수 있는 일종의 '징표', '증명'이 되는 것입니다. 웹 토큰(Web Token)이라고 한다면 웹에서 사용되는 토큰입니다. 주로 인증을 수행할 때 사용됩니다. 웹에서 인증을 수행하는 3가지 방법이 있습니다.

  • 쿠키 - 클라이언트(브라우저)에 인증 값을 저장
  • 세션 - 서버가 인증 값을 저장 (클라이언트에도 세션 ID값을 저장)
  • 토큰 - 클라이언트에 인증값을 저장하되 JSON 형식이며 서명(암호화) 과정을 거침

이렇게 쿠키, 세션, 토큰 세가지 방법이 있습니다. 각각이 장단점이 있지만, 쿠키의 방식보다는 보안성이 중요해진 지금은 보통 토큰의 방식을 사용합니다. 서버에 자원이 충분하거나 사용자가 적다면 세션으로 서버에서 관리를 하는 것이 가장 좋겠지만, 자원이 부족하거나 사용자가 너무 많거나 하다면 토큰 방식으로 인증을 수행하도록 하는 것이 좋습니다. 정리하자면, 웹 토큰은 '입장권' 같은 것으로 생각해보면 되겠습니다. 이걸 보여주면 입장을 해도 괜찮은 사람이라는 것을 증명하는 것이지요.

 

토큰(Token) 인증 방식의 장단점

이제는 세션과 토큰 방식을 주로 사용한다고 할 수 있습니다. 그렇다면 어떤 상황에서 쓰게 될까요? 토큰 방식과 세션 방식을 표로 비교해서 보겠습니다.

  세션 토큰
자원 관리 서버에서 관리 클라이언트에서 관리
만료 기간 알기 어려움 만료기간이 따로 명시됨

위처럼 세션은 서버에서 관리되기 때문에 로그인 한 대상을 관리하기 용이하며 원칙적으로 브라우저를 종료할 시에 바로 세션을 저장한 세션값이 만료가 되어서 보안 위험이 적습니다. 뿐만 아니라 세션 하이재킹의 경우도 새로운 세션값을 생성해서 저장하는 방식을 채택하면 방어하기에 유리할 수 있습니다. 그렇지만, 서버의 자원을 소비하게 되고 토큰만큼의 편리함은 적다는 점이 있습니다. 여기서 토큰은 바로 편리함과 보안을 적절히 보완한 개념이라고 볼 수 있습니다. JWT 토큰의 경우 토큰의 내용을 암호화(서명)하고 위변조 여부를 해시검증을 통해 수행합니다. 다만, 만료기간이 정해져 있어서 악의적인 공격자가 토큰을 탈취한다면 만료기간 동안 공격자가 대신 로그인 하는 상황이 생길 수도 있습니다. 물론 이것에 대해서 방어하기 위해 Access Token과 Refresh Token을 분리해서 쓰는 방식으로 보완하기도 합니다. 하지만, 근본적인 위협은 존재한다는 것이 토큰의 한계라고 할 수 있습니다. 

 

JWT

위에서 Token에 대한 개념과 JSON에 대한 개념을 정리했으니 JWT(JSON Web Token)는 'JSON의 데이터 형식으로 된 웹 토큰'이라는 것을 쉽게 이해할 수 있습니다. JWT는 3개의 구조로 되어있습니다. 바로 헤더(Header), 페이로드(Payload), 서명(Signature)입니다.

  • 헤더(Header) - 이 구조체가 어떤 알고리듬, 구조(토큰타입)로 되어있는지 명시합니다.
  • 페이로드(Payload) - 실제 정보가 위치해 있습니다.
  • 서명(Signature) - 헤더와 페이로드와 '암호'를 합쳐서 알고리듬으로 암호화하여 변조여부를 확인할 수 있습니다.

JWT.io에서 확인 가능한 JWT의 예시

그림의 오른쪽을 보면 헤더/페이로드/서명이 나누어져있습니다. 오른쪽의 내용이 암호화(인코딩) 과정을 거쳐서 왼쪽의 인코딩된 형태로 나오게 됩니다. 인코딩된 토큰을 전달하면 변조되기 매우 어려울 뿐 아니라 값이 노출되지 않아 보안에도 유리합니다.