[Spring] JWT 01. Json Web Token 개념정리

[Spring] JWT(Json Web Token) 정리

JWT(Json Web Token)는 로그인 이후 세션을 대신해서 사용자 인증을 처리하는 토큰 방식입니다.
비밀번호를 대신하는 것이 아니라, 로그인 성공 후 발급되는 인증 증표입니다.


1. 비밀번호와 JWT의 차이

  • 비밀번호 → 로그인할 때만 사용 (DB에는 해시 저장)
  • JWT → 로그인 성공 후 발급, 이후 요청마다 전송

로그인 흐름은 아래와 같습니다.

  1. 아이디 + 비밀번호 전송
  2. 서버가 비밀번호 검증
  3. 성공하면 JWT 발급
  4. 이후 요청은 JWT로 인증

2. JWT 구조

JWT는 3개의 영역으로 구성됩니다.

Header.Payload.Signature
  • Header : 알고리즘 정보 (예: HS256)
  • Payload : 사용자 정보(Claim)
  • Signature : 위변조 방지 서명

중요: Payload는 암호화가 아닌 Base64 인코딩입니다.
비밀번호 같은 민감정보는 절대 넣으면 안 됩니다.


3. JWT 서명 키 생성 (256bit 이상)

HS256 알고리즘 기준 최소 256bit(32바이트) 이상 키를 권장합니다.

import java.security.SecureRandom;
import java.util.Base64;

public class JwtKeyGenerator {
    public static void main(String[] args) {
        byte[] key = new byte[32];
        new SecureRandom().nextBytes(key);
        String encoded = Base64.getEncoder().encodeToString(key);
        System.out.println(encoded);
    }
}

출력된 문자열을 application.yml 또는 환경변수에 설정합니다.


4. JWT 생성 코드 예제

import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Date;
import javax.crypto.SecretKey;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

public class JwtCreateExample {

    public static void main(String[] args) {

        String keyStr = "여기에_32자이상_랜덤키";
        SecretKey key = Keys.hmacShaKeyFor(keyStr.getBytes(StandardCharsets.UTF_8));

        Calendar c = Calendar.getInstance();
        Date now = c.getTime();

        c.add(Calendar.MINUTE, 30);
        Date expire = c.getTime();

        String token = Jwts.builder()
                .signWith(key)
                .issuer("my-service")
                .issuedAt(now)
                .expiration(expire)
                .claim("loginId", "testuser1")
                .claim("loginLevel", "USER")
                .compact();

        System.out.println(token);
    }
}

5. 실행 결과 (Output)

실행하면 아래와 같은 토큰이 생성됩니다.

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJteS1zZXJ2aWNlIiwiaWF0IjoxNzA4MzAwMDAwLCJleHAiOjE3MDgzMDE4MDAsImxvZ2luSWQiOiJ0ZXN0dXNlcjEiLCJsb2dpbkxldmVsIjoiVVNFUiJ9.qZx8W3K1mLp9Xy2VbT4aJk6PnQwErTyUiOpLmNoPqRs

Payload 디코딩 결과

{
  "iss": "my-service",
  "iat": 1708300000,
  "exp": 1708301800,
  "loginId": "testuser1",
  "loginLevel": "USER"
}

6. JWT 검증 코드 예제

import java.nio.charset.StandardCharsets;
import javax.crypto.SecretKey;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

public class JwtParseExample {

    public static void main(String[] args) {

        String authorization = "Bearer 토큰값";
        String token = authorization.replace("Bearer ", "");

        String keyStr = "여기에_32자이상_랜덤키";
        SecretKey key = Keys.hmacShaKeyFor(keyStr.getBytes(StandardCharsets.UTF_8));

        Claims claims = (Claims) Jwts.parser()
                .verifyWith(key)
                .build()
                .parse(token)
                .getPayload();

        System.out.println("loginId = " + claims.get("loginId"));
        System.out.println("loginLevel = " + claims.get("loginLevel"));
    }
}

7. Spring에서 토큰 보내는 방법

axios.get("/api/mypage", {
  headers: {
    Authorization: `Bearer ${accessToken}`
  }
});

8. 자주 하는 실수

  • JWT에 비밀번호 넣기 ❌
  • key-str를 너무 짧게 설정 ❌
  • 비밀키를 Git에 업로드 ❌
  • AccessToken을 영구토큰으로 사용 ❌

마무리

JWT는 로그인 상태를 증명하는 토큰이며,
비밀번호를 대신하는 것이 아니라 로그인 이후 인증을 유지하는 방식입니다.

다음 글에서는 AccessToken / RefreshToken 구조와
Spring Boot에서 실제 적용 흐름까지 정리해보겠습니다.