파일

src/main/java/kr/co/onmediagroup/onoffapi/
│
├── config/
│   ├── JWTConfig.java            // JWT 설정
│   └── SecurityConfig.java       // 스프링 시큐리티 설정
│
├── filter/
│   └── JWTAuthenticationFilter.java  // JWT 인증 필터
│
├── controllerAdvice/
│   └── ApiControllerAdvice.java              // JWT 생성, 검증 유틸리티
│
├── exception/
│   └── CustomAuthenticationEntryPoint.java              // JWT 생성, 검증 유틸리티
│
├── model/
│   └── dto/User.java              // JWT 사용자 정보 DTO
│
├── util/
│   └── JWTUtil.java              // JWT 생성, 검증 유틸리티
│
└── controller/
    └── AuthController.java       // 로그인, 회원가입 컨트롤러

src/test/java/kr/co/onmediagroup/onoffapi/
│
└── util/
    └── JWTUtilTest.java              // JWT 생성, 검증 유틸리티 Test
클래스명 설명
JWTConfig JWT 관련 설정을 구성하는 클래스
SecurityConfig 스프링 시큐리티 설정
JWTAuthenticationFilter JWT 인증 커스텀 필터
ApiControllerAdvice REST API 전용 예외 처리 클래스
CustomAuthenticationEntryPoint 인증 실패 시 호출되는 커스텀 AuthenticationEntryPoint 구현체
User JWT 사용자 정보 DTO
JWTUtil JWT 생성, 검증 유틸리티
AuthController 로그인, 회원가입 컨트롤러

의존성

## build.gradle ##

// security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

//JWT
// <https://mvnrepository.com/artifact/com.auth0/java-jwt>
implementation 'com.auth0:java-jwt:4.4.0'

로직

[로그인 요청]
↓
[아이디/비밀번호 인증 성공]
↓
[JWT 발급 - createToken()]
↓
[응답에 JWT 포함 + VO 응답]
↓
[클라이언트 저장]
↓
[Authorization: Bearer <토큰> 으로 요청]
↓
[JWTAuthenticationFilter: 토큰 검증]
↓
[SecurityContext 에 인증 정보 저장]
↓
[컨트롤러에서 사용자 정보 사용]


JWTConfig

JWT 서명 키, 만료 시간 설정

## JWTConfig.java ##

@Configuration
@Getter
public class JWTConfig {
  private final int expiredSeconds;
  private final Algorithm algorithm;

  public JWTConfig(@Value("${auth.jwt.signKey}") String signKey,
                   @Value("${auth.jwt.expiredSeconds}") int expiredSeconds) {

    this.expiredSeconds = expiredSeconds;
    this.algorithm = Algorithm.HMAC256(signKey.getBytes());
  }
}