세션이 “서버가 로그인 상태를 저장하는 방식”이라면, 토큰 로그인(JWT)은 “서버가 상태를 저장하기보다 토큰 자체를 검증해서 인증하는 방식”으로 이해하면 된다. 그래서 서버가 여러 대로 확장돼도(스케일 아웃) 세션 공유 같은 고민이 상대적으로 줄어든다. 다만 토큰이 탈취되면 대응이 까다롭다는 구조적 단점도 같이 따라온다.
JWT(Json Web Token)는 로그인 인증값으로 자주 쓰이는 토큰 규격 중 하나다.
JWT는 .(점)으로 구분된 3개의 파트로 구성된다.
형식은 아래처럼 생겼다.
header.payload.signature헤더에는 “이 토큰이 어떤 타입이고(JWT)”, “서명은 어떤 알고리즘으로 만들었는지” 같은 메타 정보가 들어간다.
JWT정리하면 헤더는 “이 토큰을 어떻게 검증해야 하는지”에 대한 안내문 느낌이다.
페이로드에는 사용자 식별 정보와 토큰의 성격(발급시간/만료시간 등)이 들어간다.
여기 들어가는 값들을 보통 “클레임(claim)”이라고 부른다.
자주 보는 예시는 이런 것들:
sub: 사용자 식별값(이메일, id 등)role: 권한iat: 발행 시간exp: 만료 시간페이로드는 서버가 “요청자가 누구인지 / 어떤 권한인지”를 확인하는 데 큰 도움이 된다.
하지만 중요한 원칙이 하나 있다.
서명은 JWT에서 위변조 방지를 담당하는 핵심 파트다.
대충 “Header + Payload + 서버 secret key”를 기반으로 만들어진 결과물이라고 보면 된다.
여기서 포인트:
그래서 payload 내용을 누가 마음대로 바꿔치기하더라도, secret key 없이는 “정상 signature”를 다시 만들 수 없어서 검증에서 걸린다.
JWT의 header/payload는 Base64URL 인코딩이라 “형태만 변환된 문자열”에 가깝다.
즉, 보안 포인트는 “내용을 숨긴다”가 아니라 “서명으로 위변조를 막는다”에 있다.
만약 “내용 자체를 숨겨야” 하는 요구라면, 서명만으로는 부족하고 별도의 암호화 전략을 고려해야 한다(일반적인 JWT 서명 방식과 결이 다름).
JWT 발급 과정을 “세 파트 생성 관점”으로 보면 아래처럼 정리된다.
Header.Payload.Signature를 합쳐서 JWT 완성여기서 중요한 결론은 이거다.
서버 검증 로직은 크게 두 단계로 이해하면 된다.
이 비교가 성공하면 “이 토큰은 서버가 발급했고, 중간에 변조되지 않았다”를 신뢰할 수 있다.
정상 발급 토큰은:
payload + secret key를 같은 알고리즘으로 서명한 값공격자가 payload를 바꾼 토큰은:
즉, JWT는 “payload를 못 본다”가 아니라 “payload를 바꿔도 통과 못 한다”가 핵심이다.

JWT의 구조적 약점은 “탈취되면 만료 전까지 정상처럼 보일 수 있다”는 점이다.
세션처럼 서버에서 그 토큰 하나만 딱 지워서 즉시 차단하기가 어렵다.
가능한 대응은 있지만 대부분 비용이 크다.
문제는 이런 강수는 대개 “기존 토큰이 전부 무효”가 되어 정상 사용자도 같이 로그아웃된다는 점이다.
그래서 운영에서는 보통 아래 전략을 같이 쓴다.