[Spring Security] JWT(JSON Web Token)

이민호·2025년 5월 26일

이번에 새로운 fortuneMon 프로젝트를 진행하면서, Spring security를 사용해 로그인, 인증 등의 기능을 구현하게 되면서 JWT에 대한 개념을 공부하고 나만의 방식으로 간단히 정리해 보았다.

jwt 토큰의 구조

위의 header + payload + signature 각각의 값들은 이미 base64 encoding 되어있으므로 복호화가 가능하다.

  1. B(header) → header (알고리즘 종류, jwt) 정보들어 있는데 이걸 base64 encoding해서 만든값 decoding 하면 정보를 그대로 알 수 있음
  2. B(payload) → payload(유저의 정보들 username이나 id등,,) 역시 base64 encoding 해서 만든값
  3. B(signiture) → signiture (header + payload + 서버에서 알고있는 secret key값을 HMACSHA256 알고리즘을 이용해 암호화한 값) 을 한번 더 base64 encoding해서 만든값.

🎈전체적인 인증 흐름

  1. 클라이언트가 서버에 로그인 시도.
  2. 토큰이 없으면, 유저의 header값 ,payload값 그리고 서버의 key값을 이용해 jwt토큰 생성
  3. client 쪽으로 전달 (쿠키나, 세션스토리지에 저장)
  4. 다음에 로그인할때 서버에 jwt토큰을 같이 전송
  5. jwt token header부분과 payload부분을 서버만 알고있는 secret key를 이용해 hashing하고 그것을 base64 encoding해서 jwt token부분의 signature부분과 비교해 검증.

처음엔 JWT가 로그인 할때 사용하는 것인 줄 알았다.
그래서 이런 멍청한 질문을 했었는데...

Q. 최초 로그인에는 당연히 jwt토큰을 못보낼탠데, 그걸 token을 안보낸 사람인지, 최초로 로그인을 하는 사람인지 어케알지?

→ 구별하지않음. login api에서 login을 하면 계속 만들어 보내주고, 다른 api요청에서 jwt가 없으면 로그인이 안된 사용자라고 간주하고 401 Unauthorized 오류를 보냄.

한마디로,

JWT는 "로그인 자체"에 쓰이는 게 아니라

로그인에 성공한 후,

서버가 "이 사용자가 인증된 사람"임을 증명하는 신분증 같은 역할을 합니다.

그리고, 구별하지 않는다는 것은 실제 DB에 토큰을 저장조차 하지 않는다는 것을 의미하는데...! 즉, 서버가 사용자 상태 정보를 별도로 저장하지 않는다는 뜻이고 이를 JWT가 Stateless 하다고 말한다!

하지만 세션에 저장하는 인증방식도 있는데 그것을 세션방식(stateful)이라고 한다.

🚫 세션 방식(=stateful)과 비교

항목JWT (Stateless)세션 (Stateful)
인증 정보 저장 위치클라이언트의 토큰에 포함서버 세션 DB에 저장
서버 메모리 사용거의 없음사용자 수만큼 상태 보관 필요
확장성 (스케일 아웃)뛰어남 (서버 간 공유 필요 없음)세션 공유 필요 (Sticky Session, Redis 등)
로그아웃 처리까다로움 (블랙리스트 관리 등 필요)간단 (세션 삭제)


서버가 클라이언트에게 jwt를 전달한다음엔, 클라이언트가 서버에 매번 jwt를 전달해야하는데, 전달 방식을 알아보자! (프론트앤드와 관련된 내용이라 간단하게 정리해보았다!!! )

🎈클라이언트가 서버에 토큰을 전달하는 방식.

  1. 서버가 client에게 response로 토큰을 주면 쿠키(요청보낼때마다 자동으로 전송)나 세션스토리지(요청 보낼때마다 Request header에 전달)에 저장해서 사용.

    • 장점 : 꺼내서 원할 때 쓸 수 있기 때문에 용이함.

    • 단점 : 세션 스토리지에 저장한다면, javascript코드로 접근이 가능해서 토큰 탈취위험이 있음.

  2. 서버에서 보내는 Response header에 Set-Cookie 옵션 설정. 응답을 받으면 client는 토큰을 보관하는 쿠키를 만듦.
    (but, origin 값이 다르면 CORS 정책때문에 토큰이 다른 url에 저장될 수있음. ⇒ 프록시를 사용해서 요청한곳과 같은 곳으로 응답이 온것처럼 만들어 쿠키를 저장.)

    • 장점: 요청 보낼때, 헤더를 조작하지 않고 자동적으로 보낼 수 있고, httpOnly 옵션을 설정해 javascript코드로 접근 불가능하게 만들 수 있음

    • 단점 : React에서 상태 관리가 힘들 수 있다. 새로고침하면 렌더링이 초기화 됨 & 자바스크립트에서 접근 불가능 → 서버에 요청을 다시보내서 응답을 다시받아 로그인 된지 확인하여 렌더링 하는 방법이 가능.
profile
효율적으로 살게요.

0개의 댓글