Springboot

스프링부트 JWT란 무엇인가? 왜 사용할까?

수아파파's 2025. 2. 11. 20:03
반응형

🔹 JWT(JSON Web Token)란?

  • JSON 기반의 토큰 인증 방식
  • 세션(session) 기반 인증과 달리, 서버에 상태(state)를 저장할 필요가 없음 (Stateless)
  • 사용자가 로그인하면 토큰을 발급받고, 이후 요청마다 이 토큰을 포함하여 인증을 수행

🔹 JWT를 사용하는 이유

세션 기반 인증과 비교한 장점

  1. 서버 확장성(Scalability) 증가: 상태 저장이 필요 없어서 분산 서버에서도 인증 유지 가능
  2. 인증 속도 향상: 매 요청마다 DB에서 사용자 정보를 조회할 필요 없음
  3. 보안 강화: 토큰에 **서명(Signed Token)**이 포함되어 있어 변조 방지

JWT가 필요한 대표적인 사례

  • RESTful API 인증 (ex. 로그인 후 API 호출)
  • OAuth2 기반 인증 시스템
  • 마이크로서비스 아키텍처(MSA) 환경

스프링부트에서 JWT 생성 방법

1. JWT 구현을 위한 의존성 추가

📌 Spring Boot 프로젝트에서 JWT를 사용하려면, Maven 또는 Gradle에 의존성을 추가해야 합니다.

 

Maven (pom.xml)

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.11.5</version>
</dependency>

 

Gradle (build.gradle)

implementation 'io.jsonwebtoken:jjwt:0.11.5'

2. JWT 토큰 생성 로직 구현

📌 토큰을 생성하기 위해 비밀 키(Secret Key)를 설정하고, Claims(정보)를 추가해야 합니다..
아래는 JWT를 생성하는 JwtTokenProvider 클래스를 구현한 코드입니다.

 

JwtTokenProvider.java

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtTokenProvider {

    private final Key secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 랜덤 시크릿 키 생성
    private final long EXPIRATION_TIME = 1000 * 60 * 60; // 1시간 (밀리초)

    // 🔹 JWT 생성 메서드
    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)  // 사용자 정보 설정
                .setIssuedAt(new Date())  // 토큰 발급 시간
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))  // 만료 시간
                .signWith(secretKey)  // 서명(Signature)
                .compact();
    }

    // 🔹 JWT 검증 & 파싱 메서드
    public String validateToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            return claims.getSubject();  // 토큰에서 사용자 정보 추출
        } catch (Exception e) {
            return null;  // 유효하지 않은 토큰
        }
    }
}

3. JWT를 활용한 로그인 API 구현

📌 JWT 토큰을 발급하는 로그인 API를 Controller에 추가해봅시다.

AuthController.java

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

    private final JwtTokenProvider jwtTokenProvider = new JwtTokenProvider();  // JWT 토큰 프로바이더

    // 로그인 API (토큰 생성)
    @PostMapping("/login")
    public String login(@RequestParam String username) {
        return jwtTokenProvider.generateToken(username);  // JWT 토큰 생성 후 반환
    }

    // 토큰 검증 API
    @GetMapping("/validate")
    public String validate(@RequestParam String token) {
        return jwtTokenProvider.validateToken(token);  // 토큰 검증 후 사용자 정보 반환
    }
}

4. JWT를 활용한 Spring Security 적용 (Optional)

📌 JWT를 Spring Security와 연동하면 보안이 더 강화됩니다.

  1. Spring Security 필터를 생성하여 JWT 인증 필터를 적용
  2. SecurityConfig에서 JwtAuthenticationFilter를 등록
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.security.Keys;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private final String SECRET_KEY = "MySecretKeyForJWTAuthentication";  // 실제 배포 시 환경변수로 관리

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String token = request.getHeader("Authorization");  // 요청 헤더에서 JWT 토큰 추출

        if (token != null && validateToken(token)) {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()))
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            request.setAttribute("username", claims.getSubject());  // 요청 속성에 사용자 정보 저장
        }

        filterChain.doFilter(request, response);
    }

    private boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()))
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

 


JWT를 활용한 인증 시스템 구축하기

JWT는 세션 기반 인증보다 확장성이 높고 RESTful API에 적합한 인증 방식
스프링부트에서 JWT 토큰을 생성하고, 로그인 API에서 이를 활용하는 방법 구현
Spring Security와 함께 사용하면 추가적인 보안 강화 가능
배포 환경에서는 시크릿 키를 환경 변수로 관리하여 보안 강화 필요


💡 다음 시간

이제 JWT 기반의 인증을 더 발전시켜봅시다.
✔️ 리프레시 토큰(Refresh Token) 적용
✔️ 사용자 권한(Role-Based Access Control, RBAC) 추가
✔️ OAuth 2.0 & JWT 통합

반응형