회원가입, 로그인 등의 API에서 인증(Authorization)이 필요하지 않은 경우, Swagger 자물쇠 표시 제거 설정과 Interceptor 각각에서 처리해야하는 불편함이 있습니다. 이 문제를 해결하기 위해, 예외 처리할 경로를 리스트로 관리하여 직관적이고 편리하게 수정할 수 있는 방법을 소개합니다.
// constant/ExcludedPaths.java
public class ExcludedPaths {
    public static final String[] PATHS = {
            "/auth/sign-up", "/auth/sign-in", // 회원 가입 및 로그인
            "/nice/**", // 회원가입에서 사용될 nice 본인인증
            "/swagger-ui/**", "/v3/api-docs/**" // Swagger 문서
    };
}
// config/WebConfig.java
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
    private final AuthInterceptor authInterceptor;
	...
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/**")
                // 인증이 필요하지 않은 경우 Interceptor에 추가해 예외처리 해야한다.
                .excludePathPatterns(ExcludedPaths.PATHS);
    }
    
    ...
}
// config/SpringConfig.java
@Configuration
public class SpringConfig {
    @Bean
    public OpenAPI openAPI() {
        String jwt = "JWT";
        SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
        Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
                .name("Authorization")
                .type(SecurityScheme.Type.HTTP)
                .scheme("bearer")
                .in(SecurityScheme.In.HEADER)
                .bearerFormat(jwt)
        );
        return new OpenAPI()
                .components(components)
                .info(new Info().title("Swagger").description("Backend API Swagger UI").version("0.0.1"))
                .addSecurityItem(securityRequirement);
    }
    @Bean
    public OpenApiCustomizer openApiCustomizer() {
        return openApi -> {
            AntPathMatcher antPathMatcher = new AntPathMatcher();
            // ExcludedPaths 경로들은 자물쇠를 해제
            for (String pattern : ExcludedPaths.PATHS) {
                // 모든 경로를 확인하여 패턴 매칭
                for (Map.Entry<String, PathItem> entry : openApi.getPaths().entrySet()) {
                    String path = entry.getKey();
                    PathItem pathItem = entry.getValue();
                    // 경로 패턴이 일치하면 자물쇠 해제
                    if (antPathMatcher.match(pattern, path)) {
                        pathItem.readOperations().forEach(operation -> {
                            // 보안 항목을 없애는 방식으로 자물쇠 해제
                            operation.setSecurity(new ArrayList<>());
                        });
                    }
                }
            }
        };
    }
}