Notice
Recent Posts
Recent Comments
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

Spring & Java

JWT 이해 본문

심화 Spring/JWT & Filter

JWT 이해

dev.hyuck 2026. 1. 21. 12:40

 

JWT 이해 

 

JWT가 무엇인지, JWT 장점이 무엇인지를 학습 하면서 로그인 기능을 구현해볼까 합니다.

시작전에 학습 자료를 먼저 살펴보고 내용을 기록에 남기는 것으로 JWT에 대한 내용을 시작해보겠습니다.

 

JWT란 무엇인가요 ?

JWT는 출입증이랑 동일하다고 보면 됩니다.  예시로, 회사 출입증 같은거라고 보면 이해하기 쉬울 것 같네요. 

회사에 매일 출입 하는데 절차가 복잡하고 인증 하기가 쉽지 않다면 회사를 다니기 쉽지 않겠죠 ?

그래서 그 간편한 절차로 인증을 하도록 만든 방식입니다. ( JWT : 토큰을 생성해서 로그인 하도록 유지 ) 

말그대로 가지고 다닐수 있는 출입증으로 통과 하는 방식이라고 보면 되겠네요.

위 이미지는 JWT 방식 출입증이라고 보면 매우 쉽습니다.

 

https://token.dev/

 

JWT는 크게 3개로 구성되어 있습니다.

1. HEADER 

 ○ 암호화에서 사용된 알고리즘 

: 위 이미지 처럼 알수 없는 문자열을 암호화한 정보가 들어있는 곳이 헤더라고 생각 하면 됩니다.

 

2. PAYLOAD

 

3. SIGNATURE

○ 암호화 할 때 사용한 KEY 값

 

JWT 사용할 때 꼭 필요한 것

● 어떤 암호화 알고리즘을 사용할 것인가

: HS 256

● 어떤 정보를 넣을건가요? 

이름, 주소, 이메일, 휴대폰 번호 등등 넣을수 있겠죠 ?

● 어떤 암호키로 사용 될 것인가

: Secret Key

● 만료 시간

- JWT는 만료시간이 필수 입니다. 누군가 토큰을 악의적으로 탈취하게 된다면 아무런 조치를 취할 수 없습니다. 그래서 JWT는 편리 하지만 보안이 취약합니다 그래서 우리는 토큰의 "만료 시간" 을 지정하고 만료 시간 이후에는 새로운 토큰을 발급 받는 형식으로 관리를 하는것이 필수 입니다.

 

JWT 흐름 따라가기

토큰을 발행해주는 경우

 

Client 입장

1. 인증/인가를 위해서 로그인 한다.

 

Server 입장

1. Client가 보낸 정보를 기반으로 로그인 시도한다.

2. 로그인에 성공하면 JWT 토큰을 발급한다.

 

JWT 생성 과정을 실습 해보자

우선 common에 패키지를 하나 생성 합니다

 

생성된 패키지 구성을 하고 그  안에 내부 구조를 만들기 전에 우리는 

jwt.secret.key를 맞춰야 합니다.

 

Base64 인코딩 값이 너무 짧으면 실행이 되지 않는 오류가 있었습니다. 그래서 이 문제를 해결하기 위해 

https://www.base64decode.org/ko/

사이트에 접속해서 인코딩 값을 변경 했더니  문제 없이 실행 되는 것을 확인할 수 있었습니다. 

이제부터 본격적으로 성능 테스트를 포스트맨까지 거쳐 JWT 작동 방식을 확인하고

어떻게 사용하는것이 효율적인지 알아보겠습니다.

 

< 실습코딩 >

우선 Controller에 로그인 Request에서 id와 비밀번호를 받아 오면 username 기반으로 username key 안에 받아서 사용하겠다고 생각 하기로 했습니다. 

 

 

    // 토큰 생성
    // username이란 값을 넣어 준다. 다른 값 추가도 가능 예시로 추가
    // '발행 시간' issuedAt(now)
    // '만료 시간' .expiration(new Date(now.getTime() + TOKEN_TIME))
    public String generateToken(String username) {
        Date now = new Date();
        return BEARER_PREFIX + Jwts.builder()
                .claim("username", username)
                .issuedAt(now) // 발행 시간
                .expiration(new Date(now.getTime() + TOKEN_TIME)) // 만료 시간
                .signWith(key, Jwts.SIG.HS256)
                .compact();
    }

    // 토큰 검증
    public boolean validateToken(String token) {
        if (token == null || token.isBlank()) return false;
        try {
            parser.parseSignedClaims(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            // 개별 예외 분리 없음: 서명/형식/만료 등 모든 실패를 한 번에 처리
            log.debug("Invalid JWT: {}", e.toString());
            return false;
        }
    }

    // 토큰 복호화
    private Claims extractAllClaims(String token) {
        return parser.parseSignedClaims(token).getPayload();
    }

    public String extractUsername(String token) {
        return extractAllClaims(token).get("username", String.class);
    }

치지 말고 한번에 때려 넣자!

 

이젠 코드를 가지고 postman 동작 원리를 파악하고 그 실행 결과를 토대로 어떻게 작용 하는지 단번에 알아볼 수 있습니다.

 

이제 토큰이 정상적으로 생성 됐는지 더블 체크가 필요한 시점이에요 .

 

확인 해보니까 전혀 문제 없이 Veryfiled! 라고 출력 되는것을 알수 있습니다.

 

확인 방법은 토큰 값을 복사 하고 application.propeties에서 지정한 key 값을 그대로 넣으면 됩니다.

 

토큰의 유무를 확인하고  Postman Authorization을 확인 할 예정 입니다. 

 

기존에 로그인 하면서 받은 토큰 값을 Authorization에 추가하도록 하고 헤더를 확인해 봅시다.

아마 헤더에 잘 올려져 있을거라고 생각해요!! 

알면서 가면 더욱 재미있는것을 발견 할 수 있습니다.

 

Authorization 값을 Header 안에 담고 있다고 나옵니다. 근데 위 코드를 분석해 보면 

String jwt = authorizationHeader.substring(7);

앞 7자리를 제거 하겠다는 코드를 사용하고  최종적으로 나온 jwt가 아래 이미지 처럼 나오게 되는 것을 알 수 있습니다. 

 

만약 유효한 값이 결과가 나올 경우 포스트맨에서는 아래 이미지 처럼 도출 됩니다.

 

JWT 복호화 하는 방법 (* 초간단! )

 

복호화 방법은 그냥 claim 안에 값을 추가 하기만 하면 된다.

 

끝으로 JWT 토큰을 생성하고 그 토큰을 유효한지 검사도 해보고 내가 원하는 정보들을 꺼내서 활용하는것 까지 배워 봣습니다. 

 

한번만 더 헷갈리지 말라고 보여드리면 

 

새로운 token 값을 받아 토큰을 복사 합니다.

 

새로운 값을 토큰에 넣고 send를 누르게 된다면 어떻게 될까요 ? 

결과가 잘 나오는것을 확인할 수 있었습니다 긴 글 읽어주셔서 진심으로 감사합니다.

 

 

오늘의 TIL 

📌 날짜 : 2026 01 21

📌 주제 : JWT(Json Web Token) 인증 학습

 

오늘은 JWT(Json Web Token) 인증 방식에 대해 학습했습니다.

JWT는 서버가 인증 상태를 저장하지 않는 Stateless 인증 방식으로,
클라이언트가 로그인 성공 시 발급받은 토큰을 요청마다 전달하여 인증을 수행합니다.

세션(Session) 방식과 달리 서버에 로그인 정보를 저장하지 않고,
토큰 자체에 인증 정보가 포함된 구조라는 점이 가장 큰 특징이였습니다.

로그인 요청
→ 사용자 정보 검증
→ JWT 토큰 발급
→ Authorization Header 저장

이후 요청마다

Authorization: Bearer {JWT 토큰}
→ Filter에서 토큰 검증
→ Controller 접근
클라이언트 로그인 요청
        ↓
아이디 / 비밀번호 검증
        ↓
JWT Access Token 발급
        ↓
Authorization: Bearer {token}
        ↓
Filter에서 토큰 검증
        ↓
Claims 정보 추출
        ↓
컨트롤러 접근
🧩 JWT 구성 요소
JWT는 다음 세 가지 요소로 구성된다.

✔ Header
토큰 타입 (JWT)
서명 알고리즘 (HS256 등)
✔ Payload
사용자 정보(Claims)
예: username, role, userId 등
✔ Signature
Secret Key로 생성된 서명
토큰 위변조 방지 역할

Signature를 통해 토큰이 서버에서 발급된 정상 토큰인지 검증할 수 있게 되었습니다.

 

 

구현하며 이해한 핵심 내용

● JWT는 서버가 인증 정보를 저장하지 않습니다.

● 인증 상태는 토큰이 대신 유지합니다.

● 서버는 토큰을 복호화 하지 않고 서명 검증을 통해 신뢰성만 확인합니다.

● 토큰이 유효하면 내부 Claims 정보를 꺼내 인증에 활용합니다.

● 만료 시간이 지나면 토큰은 자동으로 무효 처리 됩니다. 

(.expiration(new Date(now.getTime() + TOKEN_TIME)) // 만료 시간)

 

주의할 점

  • Secret Key는 외부에 노출되면 안 된다.
  • 토큰 자체에 민감한 정보는 저장하지 않는다.
  • HTTPS 환경에서 사용해야 안전하다.
  • 만료 시간(expiration) 설정이 중요하다.

오늘 느낀 점

JWT는 단순히 토큰을 발급하는 기술이 아니라, HTTP의 Stateless 특성을 보안하기 위한 인증 구조라는 점을 이해하게 되었습니다. 특히 Filter와 함께 사용하면 모든 요청에 대해 공통 인증 처리가 가능하다는 것을 알게 되었습니다.

 

'심화 Spring > JWT & Filter' 카테고리의 다른 글

Filter와 같이 사용하는 JWT  (0) 2026.01.22
Filtet 개념과 동작 원리  (0) 2026.01.20