본문 바로가기

Spring/Swagger

[KEUPANG] swagger 설정하기 (feat. MSA)

이전 페이지: docker로 msa 실행하기
다음 페이지: ncp 배포하기

1. 개요

swagger 사용하는 이유

사실 같이 개발하는 프론트 친구에게 보여줄 api 명세서를 이미 notion으로 다 만든 상황이기 때문에 주요 api들은 공유가 된 상황이다.

하지만 개발을 하다보니 수시로 응답할 때 들어가는 값들이 바뀌게 되고, 개발 상황에 맞춰서 보여줄 수 있는 정확한 api 명세서를 필요로 하게됨.

MSA 구조에서 swagger-ui 적용할 때 주의할 점

사실 일반적으로 swagger를 설정할 때는 그냥 의존성 추가하고 swagger 설정만 조금 해주면 바로 사용할 수 있다.

하지만 지금 프로젝트는 MSA 구조이기 때문에 컨트롤러로 바로 접근하지 못하고 api-gateway를 통해서 접근한다는 특징이 있어서 swagger를 적용할 때 주의해야 한다.

프로젝트 구조

현재 프로젝트는 위와 같은 구조로 이루어져 있다. 간단하게 설명하면 gateway에서 product, user 쪽으로 들어오는 요청을 넘겨주고 있는 상황이다.

지금은 일단 gateway와 user 서비스에만 swagger를 적용하는 방법을 포스팅할 예정

  • gateway 포트 번호 : 8080
  • gateway 에서 user로 라우팅 되는 환경
  • docker image 생성후 docker compose로 실행하는 환경
  • 로컬에서 실행한다고 가정(이지만 ncp ubuntu 환경에 배포되어있습니다 -> 다음 글에서 설명)

2. Swagger 기본 개념

swagger

  • RESTful API를 설계하고 문서화하는 데 사용된다.
  • swagger-ui는 API 명세서를 시각적으로 보여주고, 직접 API 요청을 테스트할 수 있는 인터페이스를 제공한다.

3. Gateway에서 Swagger 설정

Spring Cloud Gateway에 Swagger 의존성 추가

이때 라이브러리의 버전 선택이 중요하다.

다른 블로그를 참고했을 때, tomcat이랑 netty 둘 중에 뭘 쓰는지에 따라 사용하는 라이브러리가 다르다면서 정리한 내용이 있다.

그리고 버전은 스프링 3.0 이상이면 2.4.0 이 버전을 사용한다는 글도 봤었다.

#tomcat
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0'

#netty
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.4.0'

 

이에 따라 정리해봤을 때, 위와 같이 선택할 수 있다.

이때 spring-cloud-gateway를 사용하면 자동으로 netty를 사용하도록 설정이 된다고 한다. 그래서 나는 webflux-ui 의존성을 추가해서 사용했다.

gateway application.yml 설정(API 통합 설정 - user만 함)

springdoc:
    swagger-ui:
        path: /swagger-ui.html #swagger-ui.html로 접속
        urls: #여러 서비스의 API 명세서를 보여주기위한 설정
            - url: /user/v3/api-docs #특정 API명세서의 경로를 지정해줌
              name: user
        enabled: true
    api-docs:
        enabled: true

 

4. User 서비스에서 Swagger 설정

Spring Boot 서비스에서 Swagger 의존성 추가

이것도 tomcat이냐 netty냐에 따라 의존성 맞춰주면 됨.

보통 web 서비스 만들겠다고 web 의존성 추가 했을 때는 tomcat을 사용하게 됨.

#tomcat 사용하게 됨
implementation 'org.springframework.boot:spring-boot-starter-web'

#netty 사용하게 됨
implementation 'org.springframework.boot:spring-boot-starter-webflux'

#이거 말고도 그냥 실행해서 log 확인하거나 다양한 방법으로 어떤 서버 사용하는지 확인 가능

 

이렇게 서버 확인하고 거기에 맞게 의존성 추가

#tomcat
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0'

#netty
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.4.0'

SwaggerConfig 클래스 추가

package com.example.keupanguser.config;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@OpenAPIDefinition
public class SwaggerConfig {
    @Bean
    public OpenAPI customOpenAPI(@Value("${openapi.service.url}") String url){
        return new OpenAPI()
            .servers(List.of(new Server().url(url)))
            .info(new Info().title("User Service API")
                .version("v0.0.1"));
    }
}

 여기서 openapi.service.url 를 쓴거는 application.yml 에서 가져오는 거임.

이렇게 나눈 이유는 테스트할때 application-test.yml을 쓰기 때문에 거기서는 다른 경로로 수행해 보고 싶어서임. 굳이 이렇게 안하고  http://localhost:8080 넣어도 됨.

application.yml 설정

openapi:
    service:
        # API Gateway 포트
        url: http://localhost:8080

현재는 로컬에서 돌린다는 것을 가정하고 있으므로 apigateway의 포트번호인 8080을 가리켜 줌.

이렇게 설정해주면 apigateway에서 각각의 api에 접근하는 것처럼 swagger에서 테스트 하는 것이 가능함.

user service의 SequrityConfig 클래스 수정

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf(AbstractHttpConfigurer::disable)
        .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
            .requestMatchers("/api/user/**", "/api/auth/**", "/user/**")
            .permitAll()  // 로그인, 회원가입 엔드포인트 허용
            .anyRequest().authenticated())
        .formLogin(AbstractHttpConfigurer::disable)
        .addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
    ;
    return http.build();
}

gateway에서 user의 api에 접근할 url을 지정해줬을 때, /user 로 시작했기 때문에 해당 경로에 대한 접근을 허용해줘야함.