JWT란 무엇인가?
JWT는 정보를 JSON 객체 형태로 안전하게 전송하기 위한 개방형 표준(RFC 7519)이다.
"전 세계 개발자들이 '이렇게 만들자'고 약속한(RFC 7519)
가볍고(JSON) 조작이 불가능한 디지털 서명
Header: 토큰의 타입과 사용된 암호화 알고리즘 정보
Payload: 실제 전달할 데이터(사용자 정보 등)
Signature: Header와 Payload를 조합해 만든 보안 코드 (위변조 방지 핵심)
JWT의 3단 구조: 왜 점(.)으로 나뉠까?
JWT는 세 부분으로 구성되며, 각 부분은 '마침표(.)'로 구분된다.
Header.Payload.Signature 형식을 가진다.
1. Header (헤더): "이 물건의 정체는 무엇인가?"
헤더는 토큰의 '메타 데이터'를 담고 있다.
두 가지 핵심 정보를 포함한다.
typ: 토큰의 타입을 지정한다. (보통 JWT)
alg: 시그니처(서명)를 생성할 때 사용할 해싱 알고리즘을 지정한다.
(예: HS256, RS256)
비유: 택배 상자 겉면에 붙은 '배송 라벨'과 같다.
이 상자가 어떤 종류의 물건인지,
어떤 방식으로 취급(검증)해야 하는지 알려주는 역할이다.
2. Payload (페이로드): "실제 전달할 내용물"
토큰에 담을 실제 정보(클레임)들이 들어있다.
클레임은 크게 세 종류로 나뉜다.
등록된 클레임: 서비스에서 이미 정의된 정보들
(예: iss(발행자), sub(제목), exp(만료시간))
공개 클레임(Public): 충돌 방지를 위해 URI 형식으로 정의한 정보
비공개 클레임(Private): 서버와 클라이언트 간에 협의하여
사용하는 사용자 정의 정보 (예: userId, role)
주의: 페이로드는 암호화된 것이 아니라 Base64Url로 인코딩된 것뿐이다.
누구나 디코딩하면 내용을 볼 수 있기 때문에,
비밀번호 같은 민감한 정보는 절대로 페이로드에 넣어서는 안 된다.
3. Signature (시그니처): "이 내용물이 진짜인가?"
JWT의 핵심이다.
헤더의 인코딩 값과 페이로드의 인코딩 값을 합친 뒤,
"서버만 알고 있는 비밀키(Secret Key)"로 암호화하여 생성한다.
목적: 토큰의 무결성 검증,
만약 중간에 누군가 페이로드의 내용을 1바이트라도 수정한다면,
서버의 비밀 키로 계산한 시그니처와 일치하지 않게 된다.
서류 봉투에 찍힌 "인감도장" or "봉인 씰"
봉투 안의 내용(Payload)이 바뀌었는지, 이 도장이 진짜
우리 회사의 도장(Secret Key)이 맞는지 확인하는 장치이다.
왜 인코딩(Base64Url)을 하는 것인가?
JSON 데이터에는 공백이나 특수문자({, }, ", :, , \n 등)가 포함되어 있어
전송 시 URL이나 HTTP 헤더의 규칙과 충돌하여 데이터가 깨질 위험이 있는데
이를 방지하기 위해
전 세계 모든 시스템이 공통적으로
해석할 수 있는 64개의 안전한 문자(알파벳, 숫자, -, _)로만
데이터를 변환(Base64Url)하여 전송의 안정성과 무결성을 보장하기 위함이다.
왜 세션 대신 JWT를 쓰는 것인가?
Stateless(무상태)
세션: 사용자가 로그인하면 서버(메모리나 DB)에
"이 사람은 로그인됨"이라는 기록을 남겨야 한다.
JWT: 서버는 기록을 남기지 않는다.
대신 로그인 시 유효기간이 적힌 위조 불가능한 티켓(JWT)을
만들어서 사용자에게 준다.
이후 사용자가 티켓(JWT)을 제시하면 서버는 자기 장부를 확인하는 게 아니라,
티켓의 인장(Signature)이 진짜인지만 확인하고 즉시 통과시킨다.
Scale-out (서버 확장)
세션: 서버가 1번부터 10번까지 있을 때,
1번 서버에서 로그인한 사용자가 2번 서버로 요청을 보내면
2번 서버는 그 사용자를 모른다(세션 공유 문제 발생).
이를 해결하려면 별도의 공유 DB(Redis 등)를 구축해야 한다.
JWT: 모든 서버가 동일한 비밀 키(Secret Key)만 공유하고 있다면,
어느 서버로 요청이 가든 그 자리에서 즉시 티켓 검증이 가능하다.
서버를 수백 대 늘려도 인증 체계가 복잡해지지 않는다.
Decoupled (분리): 역할의 독립
세션: 인증과 서비스 로직이 같은 세션 저장소를
바라봐야 하므로 강하게 결합된다.
JWT: "인증만 해주는 서버"를 따로 만들 수 있다.
인증 서버가 토큰을 발행해주면, 메일 서비스 서버나 결제 서비스 서버는
각자 자기 키로 토큰이 맞는지 확인만 하면 된다.
서로 남의 장부를 뒤져볼 필요가 없어 서비스 간 독립성이 극대화된다.