[CS] JWT 토큰 로그인 : 구조부터 검증 흐름

이지연·2026년 1월 23일

웹 CS (web CS)

목록 보기
16/16

토큰을 통한 로그인

세션이 “서버가 로그인 상태를 저장하는 방식”이라면, 토큰 로그인(JWT)은 “서버가 상태를 저장하기보다 토큰 자체를 검증해서 인증하는 방식”으로 이해하면 된다. 그래서 서버가 여러 대로 확장돼도(스케일 아웃) 세션 공유 같은 고민이 상대적으로 줄어든다. 다만 토큰이 탈취되면 대응이 까다롭다는 구조적 단점도 같이 따라온다.


JWT 토큰이란?

JWT(Json Web Token)는 로그인 인증값으로 자주 쓰이는 토큰 규격 중 하나다.
JWT는 .(점)으로 구분된 3개의 파트로 구성된다.

  • Header
  • Payload
  • Signature

형식은 아래처럼 생겼다.

  • 문법 형태: header.payload.signature
  • 실제 예시는 보통 길고, Base64URL 형태 문자열이 점으로 이어진 모양이다.

1) Header (헤더)

헤더에는 “이 토큰이 어떤 타입이고(JWT)”, “서명은 어떤 알고리즘으로 만들었는지” 같은 메타 정보가 들어간다.

  • 토큰 타입: 보통 JWT
  • 서명 알고리즘 예: HS256 / HS512 등

정리하면 헤더는 “이 토큰을 어떻게 검증해야 하는지”에 대한 안내문 느낌이다.


2) Payload (페이로드 / 클레임)

페이로드에는 사용자 식별 정보와 토큰의 성격(발급시간/만료시간 등)이 들어간다.
여기 들어가는 값들을 보통 “클레임(claim)”이라고 부른다.

자주 보는 예시는 이런 것들:

  • sub: 사용자 식별값(이메일, id 등)
  • role: 권한
  • iat: 발행 시간
  • exp: 만료 시간

페이로드는 서버가 “요청자가 누구인지 / 어떤 권한인지”를 확인하는 데 큰 도움이 된다.
하지만 중요한 원칙이 하나 있다.

  • 페이로드에 비밀번호 같은 민감정보는 절대 넣으면 안 된다.
    (어차피 토큰은 까보면 payload가 보인다고 생각하는 게 안전하다)

3) Signature (서명)

서명은 JWT에서 위변조 방지를 담당하는 핵심 파트다.
대충 “Header + Payload + 서버 secret key”를 기반으로 만들어진 결과물이라고 보면 된다.

여기서 포인트:

  • signature는 “디코딩해서 읽는 용도”가 아니다.
  • 서버는 토큰 검증할 때 signature를 해석하는 게 아니라,
    • 토큰의 header/payload를 가져와서
    • 서버가 가진 secret key로
    • 같은 알고리즘으로 signature를 다시 계산한 다음
    • 토큰에 들어있는 signature와 비교한다.

그래서 payload 내용을 누가 마음대로 바꿔치기하더라도, secret key 없이는 “정상 signature”를 다시 만들 수 없어서 검증에서 걸린다.


인코딩/디코딩 vs 암호화 (여기 많이 헷갈림)

JWT의 header/payload는 Base64URL 인코딩이라 “형태만 변환된 문자열”에 가깝다.
즉, 보안 포인트는 “내용을 숨긴다”가 아니라 “서명으로 위변조를 막는다”에 있다.

  • 인코딩(encoding): 전달 가능한 형태로 표현만 바꾸는 것
  • 디코딩(decoding): 표현을 되돌려 읽을 수 있게 하는 것
  • 암호화(encryption): 키 없이는 원본을 알기 어렵게 만드는 것(내용 숨김 목적)

만약 “내용 자체를 숨겨야” 하는 요구라면, 서명만으로는 부족하고 별도의 암호화 전략을 고려해야 한다(일반적인 JWT 서명 방식과 결이 다름).


토큰 발급 흐름(구성 기준으로 이해)

JWT 발급 과정을 “세 파트 생성 관점”으로 보면 아래처럼 정리된다.

  • Header 작성(서명 알고리즘 정보 포함)
  • Payload 작성(식별 정보 + 만료 등)
  • Header와 Payload를 인코딩
  • 서버 secret key로 signature 생성(서명)
  • 최종적으로 Header.Payload.Signature를 합쳐서 JWT 완성

여기서 중요한 결론은 이거다.

  • 서버는 사용자 세션을 저장하기보다, 검증에 필요한 secret key를 관리하는 구조로 가는 경우가 많다.

토큰 검증 흐름(서버가 신뢰하는 방식)

서버 검증 로직은 크게 두 단계로 이해하면 된다.

  • (1) header/payload는 디코딩해서 값 확인은 가능
  • (2) 서버 secret key로 signature를 “재계산”해서 토큰 signature와 비교

이 비교가 성공하면 “이 토큰은 서버가 발급했고, 중간에 변조되지 않았다”를 신뢰할 수 있다.


토큰을 신뢰할 수 있는 이유(위조 방지 논리)

정상 발급 토큰은:

  • signature = payload + secret key를 같은 알고리즘으로 서명한 값

공격자가 payload를 바꾼 토큰은:

  • payload가 달라진 순간, 서버가 재계산하는 signature도 달라짐
  • 그래서 기존 signature와 매칭이 안 되고 검증 실패

즉, JWT는 “payload를 못 본다”가 아니라 “payload를 바꿔도 통과 못 한다”가 핵심이다.


토큰 탈취 시: 대응 방법과 한계

JWT의 구조적 약점은 “탈취되면 만료 전까지 정상처럼 보일 수 있다”는 점이다.
세션처럼 서버에서 그 토큰 하나만 딱 지워서 즉시 차단하기가 어렵다.

가능한 대응은 있지만 대부분 비용이 크다.

  • secret key 교체
  • 토큰 규칙(구조) 변경
  • 서버 재배포/재시작

문제는 이런 강수는 대개 “기존 토큰이 전부 무효”가 되어 정상 사용자도 같이 로그아웃된다는 점이다.
그래서 운영에서는 보통 아래 전략을 같이 쓴다.

  • 만료(exp)를 짧게 가져가기
  • access / refresh token 분리로 피해 범위 줄이기
  • 필요하면 폐기/블랙리스트 같은 보완책(상태를 일부 저장하는 타협)을 섞기
profile
Eazy하게

0개의 댓글