기록

[Swagger] Swagger에서 JWT 인증 처리하기 본문

Web/Spring

[Swagger] Swagger에서 JWT 인증 처리하기

zyin 2025. 10. 26. 10:20

1. 들어가며

Swagger(OpenAPI)는 단순한 API 목록 도구가 아니라, API 보안 구조까지 함께 명세화할 수 있는 문서 시스템이다.
JWT(JSON Web Token) 기반 인증을 사용하는 서비스라면 Swagger UI의 Authorize 버튼을 통해 실제 토큰을 입력하고 인증된 요청을 테스트할 수 있다.
이번 글에서는 Spring Boot 3.x와 Spring Security 환경에서 JWT 인증을 Swagger(OpenAPI) 문서에 통합하는 방법을 설명한다.

 

2. Swagger에서의 보안 구조 이해

OpenAPI 명세는 components.securitySchemes와 security 섹션을 이용해 인증 방식을 정의한다.
JWT 인증은 HTTP Bearer 스킴으로 정의되며, Swagger UI에서 “Authorize” 버튼을 활성화한다.

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []
필드 설명
type: http HTTP 기반 인증 방식을 사용한다.
scheme: bearer Bearer Token 인증 방식을 지정한다.
bearerFormat: JWT JWT 포맷의 토큰을 사용함을 명시한다.
security 문서 전체에 인증 스키마를 적용한다.

 

이 설정이 반영되면 Swagger UI 상단에 Authorize 버튼이 표시되고,
사용자가 입력한 토큰은 자동으로 Authorization: Bearer <token> 헤더로 포함되어 전송된다.

참고 문서

 

3. OpenAPI 보안 설정

Spring Boot에서는 OpenAPI Bean을 구성하여 JWT 인증 스키마를 문서에 반영할 수 있다.

@Configuration
public class OpenApiConfig {

    private static final String SECURITY_SCHEME_NAME = "bearerAuth";

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("JWT 인증 예시 API")
                        .version("1.0.0")
                        .description("Swagger에서 JWT 토큰 인증을 테스트하는 예시"))
                .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
                .components(new Components()
                        .addSecuritySchemes(SECURITY_SCHEME_NAME,
                                new SecurityScheme()
                                        .name(SECURITY_SCHEME_NAME)
                                        .type(SecurityScheme.Type.HTTP)
                                        .scheme("bearer")
                                        .bearerFormat("JWT")));
    }
}

 

addSecurityItem은 문서 전역에 기본 보안 스키마를 적용하며, bearerFormat("JWT")는 Swagger UI에서 JWT 토큰 입력 필드로 표시된다. Swagger UI는 입력된 토큰을 자동으로 HTTP Authorization 헤더에 추가한다. 이 설정은 Swagger 문서의 명세를 정의할 뿐, 실제 JWT 검증 로직은 Spring Security에서 처리한다.

 

4. 인증이 필요한 API 정의

Swagger 문서에 정의한 보안 스키마를 개별 API에 적용하려면 @SecurityRequirement를 사용한다.

@RestController
public class SecureController {

    @Operation(
        summary = "보호된 리소스 조회",
        description = "JWT 토큰이 있어야 접근 가능한 API",
        security = { @SecurityRequirement(name = "bearerAuth") }
    )
    @GetMapping("/secure/data")
    public String secureEndpoint() {
        return "인증 성공. 보호된 데이터 접근이 허용됨.";
    }
}

@SecurityRequirement(name = "bearerAuth")는 OpenApiConfig에서 정의한 인증 스키마를 이 엔드포인트에 연결한다.
Swagger UI에서는 /secure/data 엔드포인트 옆에 자물쇠 아이콘이 표시된다. API별로 인증이 필요한 경우에만 @SecurityRequirement를 지정하면 된다. 문서 전체에 인증을 강제하지 않으려면 addSecurityItem을 생략하고 API별로만 선언한다.

 

5. Spring Security 설정

Swagger UI에서 JWT를 테스트하기 위해 간단한 보안 필터를 구성한다.
실무에서는 JWT 검증 필터(OncePerRequestFilter)를 별도로 두지만, Swagger 테스트를 위해서는 다음과 같은 최소 설정으로 충분하다.

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                .requestMatchers("/secure/**").authenticated()
                .anyRequest().permitAll()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt());
        return http.build();
    }
}

이 설정은 Swagger UI와 API 문서를 누구나 접근할 수 있도록 허용하되, /secure/** 경로는 인증된 요청만 접근할 수 있도록 제한한다.
Swagger UI의 “Authorize” 입력값은 자동으로 Authorization 헤더에 포함되어 요청되므로, JWT 필터를 추가하지 않아도 정상적인 인증 테스트가 가능하다.

 

6. Swagger UI에서 JWT 인증 테스트

  1. 서버를 실행하고 http://localhost:8080/swagger-ui.html에 접속한다.
  2. 화면 상단의 Authorize 버튼을 클릭한다.
  3. 팝업창의 입력란에 JWT 토큰을 붙여넣는다.
  4. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
  5. Authorize를 클릭하면 Swagger UI가 토큰을 저장하고, 이후 모든 요청에 자동으로 헤더를 추가한다.
  6. /secure/data API를 선택하고 “Try it out”을 클릭한 뒤 실행하면 인증된 요청이 전송된다.

Swagger가 전송하는 실제 요청 예시는 다음과 같다.

GET /secure/data
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

응답 예시:

{
  "message": "인증 성공. 보호된 데이터 접근이 허용됨."
}

 

 

7. 인증이 필요한 API와 공개 API 구분

모든 API에 인증을 강제하지 않고, 일부만 보호 대상으로 설정할 수도 있다.
예를 들어 /public/** API는 인증이 필요 없도록 설정할 수 있다.

@Operation(summary = "공개 API", security = {})
@GetMapping("/public/info")
public String publicInfo() {
    return "누구나 접근 가능";
}

security = {}를 지정하면 Swagger UI에서 자물쇠 표시가 사라지고, 토큰 입력 여부와 관계없이 호출할 수 있다.

Comments