[Spring] JWT(Json Web Token) 정리
JWT(Json Web Token)는 로그인 이후 세션을 대신해서 사용자 인증을 처리하는 토큰 방식입니다.
비밀번호를 대신하는 것이 아니라, 로그인 성공 후 발급되는 인증 증표입니다.
1. 비밀번호와 JWT의 차이
- 비밀번호 → 로그인할 때만 사용 (DB에는 해시 저장)
- JWT → 로그인 성공 후 발급, 이후 요청마다 전송
로그인 흐름은 아래와 같습니다.
- 아이디 + 비밀번호 전송
- 서버가 비밀번호 검증
- 성공하면 JWT 발급
- 이후 요청은 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에서 실제 적용 흐름까지 정리해보겠습니다.
'Tech Stack > Spring Boot' 카테고리의 다른 글
| [Spring MVC] DispatcherServlet(디스패처 서블릿)이란 무엇인가? (0) | 2026.03.28 |
|---|---|
| [Spring] JWT 05. RefreshToken DB 저장 + 1회성 폐기(로테이션) + 재발급 흐름 완성 (0) | 2026.02.19 |
| [Spring] JWT 04. 만료 임박 자동 갱신(TokenRenewalInterceptor) 적용 (0) | 2026.02.19 |
| [Spring] JWT 03. Interceptor로 인증 적용하기 (로그인 필요 API 보호) (0) | 2026.02.19 |
| [Spring] JWT 02. AccessToken / RefreshToken 구조 + 재발급 흐름 (0) | 2026.02.18 |