0Pricing
Java Academy · 강의

JWT: 구조, 생성 및 검증

JWT 구조를 직접 디코딩하고 비밀 키로 서명된 토큰을 만든 뒤 프레임워크 없이 클레임을 검증합니다.

JWT: 구조, 생성 및 검증은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

JWT란 무엇입니까

JSON 웹 토큰(JWT)은 당사자 간에 클레임을 전송하기 위한 간결하고 URL에 안전한 토큰 형식입니다. JWT에는 서명이 포함되며 선택적으로 암호화할 수도 있습니다. 자체 완결형이므로 클레임을 확인할 때 데이터베이스 조회가 필요하지 않습니다.

JWT 구조: Header.Payload.Signature

JWT는 점으로 구분된 세 부분을 Base64URL로 인코딩한 형식입니다: header.payload.signature. 헤더는 알고리즘을 지정하고, 페이로드는 클레임을 포함하며, 서명은 무결성을 확인합니다.

// Example JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9      <- header
// .eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0  <- payload
// .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c     <- signature

디코딩된 헤더와 페이로드

각 부분을 Base64URL로 디코딩하면 JSON을 볼 수 있습니다. 페이로드에는 클레임이 포함됩니다. 표준 클레임은 sub(주체), iss(발급자), exp(만료), iat(발급 시각)입니다.

// Header:
{ "alg": "HS256", "typ": "JWT" }
// Payload:
{ "sub": "user-42", "name": "Alice", "role": "ADMIN",
  "iat": 1716000000, "exp": 1716003600 }

JWT 수동 생성하기(HS256)

헤더와 페이로드 JSON을 구성하고 각각 Base64URL로 인코딩한 다음 점으로 연결하십시오. 그런 후 header.payload에 대해 HMAC-SHA256을 계산하고 그 결과를 서명으로 덧붙이십시오.

String header  = Base64.getUrlEncoder().withoutPadding()
    .encodeToString("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes());
String payload = Base64.getUrlEncoder().withoutPadding()
    .encodeToString("{\"sub\":\"user-42\",\"exp\":9999999999}".getBytes());
String sigInput = header + "." + payload;
byte[] sig = computeHmac(secretKey, sigInput);
String jwt = sigInput + "." + Base64.getUrlEncoder().withoutPadding().encodeToString(sig);

JWT 수동 검증하기

점으로 분할하고 헤더와 페이로드를 디코딩한 다음 header.payload에 대해 HMAC을 다시 계산하십시오. 서명과 비교하고 exp가 미래 시점인지 확인하십시오.

String[] parts = jwt.split("\\.");
String sigInput = parts[0] + "." + parts[1];
byte[] expectedSig = computeHmac(secretKey, sigInput);
byte[] actualSig   = Base64.getUrlDecoder().decode(parts[2]);
if (!MessageDigest.isEqual(expectedSig, actualSig)) throw new SecurityException("Invalid signature");
// Decode payload and check exp:
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]));
// parse JSON and check exp > now

java-jwt 라이브러리 사용(Auth0)

com.auth0:java-jwt 라이브러리는 유창한 API를 통해 JWT 생성과 검증을 간소화합니다.

// Create:
Algorithm alg = Algorithm.HMAC256(secretKey);
String token = JWT.create()
    .withSubject("user-42")
    .withClaim("role", "ADMIN")
    .withExpiresAt(Instant.now().plusSeconds(3600))
    .sign(alg);
// Verify:
JWTVerifier verifier = JWT.require(alg).withIssuer("my-service").build();
DecodedJWT decoded = verifier.verify(token);
System.out.println(decoded.getSubject());

HS256과 RS256 비교

HS256은 공유 대칭 키를 사용하므로 간단하지만 발급자와 검증자가 모두 키를 서로 신뢰해야 합니다. RS256은 RSA를 사용하여 개인 키로 서명하고 공개 키로 검증하므로, 서명 키를 알지 못하는 서비스도 검증할 수 있는 다중 서비스 아키텍처에 적합합니다.

JWT 저장: HttpOnly 쿠키와 localStorage 비교

JWT는 HttpOnly 쿠키에 저장하십시오. 쿠키는 JS에서 접근할 수 없어 XSS 탈취를 방지하며, Secure 및 SameSite=Strict 플래그를 함께 사용해야 합니다. XSS 공격이 읽을 수 있으므로 localStorage는 피하십시오.

// Set JWT as HttpOnly cookie in Spring:
ResponseCookie cookie = ResponseCookie.from("jwt", token)
    .httpOnly(true).secure(true).sameSite("Strict")
    .path("/").maxAge(3600).build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());

갱신 토큰

JWT의 만료 시간은 짧게 설정합니다(15분). 불투명하고 서버 측에 저장되는 갱신 토큰은 더 긴 만료 시간을 가집니다. 클라이언트는 다시 인증하지 않고 갱신 토큰을 새 JWT로 교환합니다.

JWT 폐기 문제

JWT는 상태가 없으므로 기본 제공되는 폐기 기능이 없습니다. 만료 전에 로그아웃할 수 있도록 짧은 만료 시간과 Redis에 폐기된 JWT ID(jti 클레임) 차단 목록을 사용하십시오.

// On logout, add the jti to a Redis blocklist with TTL = token expiry:
redis.set("revoked:" + jti, "1", ex, 3600);
// On verify, check blocklist:
if (redis.exists("revoked:" + decoded.getId())) throw new SecurityException("Token revoked");

Spring Security JWT 통합

Spring Security에서는 JwtAuthenticationFilter extends OncePerRequestFilter를 구현하여 각 요청에서 JWT를 추출하고 검증한 다음 SecurityContext를 설정하십시오.

String token = request.getHeader("Authorization").replace("Bearer ","");
DecodedJWT decoded = verifier.verify(token);
String userId = decoded.getSubject();
UsernamePasswordAuthenticationToken auth =
    new UsernamePasswordAuthenticationToken(userId, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);

빠른 확인

HS256과 RS256 JWT 서명의 핵심적인 구조적 차이는 무엇입니까

복습

JWT = header.payload.signature(Base64URL). HMAC(HS256) 또는 RSA(RS256)로 서명하십시오. 서명과 exp 클레임을 검증하십시오. HttpOnly 쿠키에 저장하십시오. 짧은 만료 시간과 갱신 토큰을 사용하십시오. Redis의 jti 차단 목록을 통해 폐기하십시오.

자주 묻는 질문

“JWT: 구조, 생성 및 검증” 강의는 무료인가요?

네 — “JWT: 구조, 생성 및 검증” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“JWT: 구조, 생성 및 검증”에서 뭘 배우나요?

JWT 구조를 직접 디코딩하고 비밀 키로 서명된 토큰을 만든 뒤 프레임워크 없이 클레임을 검증합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“JWT: 구조, 생성 및 검증” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. MessageDigest를 사용한 암호화 해시
  2. AES 대칭 암호화
  3. 메시지 무결성을 위한 HMAC-SHA256
  4. JWT: 구조, 생성 및 검증
← Java Academy(으)로 돌아가기