멀티모듈 환경의 Swagger 설정

 

 

단일 모듈에서의 Swagger 설정은 여기

 

멀티 모듈(Spring Boot 기반)에서 Swagger를 설정하고 API 문서를 통합하는 방법을 정리해 봤다.

 

나는 모든 모듈에서 공통적으로 implement 하는 core 모듈을 사용해서 SwaggerConfig를 추상화하여 각 모듈에 Swagger 설정을 추가했다.

그리고 각 모듈의 Swagger-ui 들을 각자의 IP로 들어가서 보면 불편하니까 Gateway 모듈에서 모아볼 수 있도록 설정해 주었다.

 

설정 과정


 

1. 의존성 추가

Swagger를 추가할 각 모듈에는 아래 의존성을 추가하고

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.5'

 

 

Swagger를 모아서 볼 Gateway모듈에는 아래 의존성을 추가해 준다.

implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.8.3'

 

 

2. Swagger interface 생성

모든 모듈에서 사용하는 core 모듈에 Swagger config interface를 생성한다.

 

package com.example.core.config;


import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springdoc.core.models.GroupedOpenApi;

public interface SwaggerConfigInterface {


    default GroupedOpenApi createGroupedOpenApi(String group, String path, String title, String description) {
        return GroupedOpenApi.builder()
                .group(group)
                .pathsToMatch(path)
                .addOpenApiCustomizer(openApi ->
                        openApi.setInfo(new Info()
                                .title(title)
                                .description(description)
                                .version("1.0.0")
                        )
                )
                .build();
    }

    default OpenAPI createOpenAPI(String title, String description) {
        return new OpenAPI()
                .info(new Info()
                        .title(title)
                        .description(description)
                        .version("1.0.0"));
    }
}

 

3. 각 모듈에서 SwaggerConfig 구현

 

Core를 implemention 하고 Interface를 가져와서 실제 객체를 각 모듈에서 구현한다.

 

각 모듈에 core 모듈 의존성 추가

implementation project(':core')

 

❗ 각 모듈에 core 모듈을 추가하고 @SpringBootApplication 어노테이션이 달려있는 메인 application에 @ComponentScan으로 core의 패키지도 명시적으로 지정을 해줘야 interface를 잘 가져옴

 

예시

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.core.config","com.example.apiorders"})
public class ApiOrdersApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiOrdersApplication.class, args);
    }

}

 

 

각 모듈에서 실제 SwaggerConfig 객체 구현

import com.example.core.config.SwaggerConfigInterface;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig implements SwaggerConfigInterface {

    @Bean
    public GroupedOpenApi userGroupedOpenApi() {
        return createGroupedOpenApi("user", "/user/**", "User API", "유저 업무 처리를 위한 API");
    }
}

 

createGroupOpenApi 안의 값은 잘 설정해 주면 될 것 같다.

 

4. application.yml 파일 수정

 

일단 각 모듈의 application.yml 파일에 아래와 같은 설정을 추가해 준다.

springdoc:
  api-docs:
    path: /모듈이름/v3/api-docs
  swagger-ui:
    path: /모듈이름/swagger-ui.html

 

api-docs는 user 모듈의 Swagger API 문서가 제공되는 API 문서 경로고 swagger-ui는 이를 랜더링 해서 ui로 보여주는 경로다.

Gateway에서 저 api-docs의 경로를 이용해 API 문서를 한 군데서 모아보는 것이다.

 

이제 Gateway의 yml파일을 아래와 같이 수정하면 된다.

springdoc:
  swagger-ui:
    path: /swagger-ui.html
    urls:
      - name: user
        url: /user/v3/api-docs
      - name: other-service
        url: /other-service/v3/api-docs

 

❗ 여기서 url을 각 모듈의 api-docs와 꼭 일치시켜줘야 한다!

그리고 url의 경로가 해당 모듈로 로드밸런싱 잘 되게 설정도 맞춰야 한다.

 

ex

spring:
  cloud:
    gateway:
      routes:
        - id: api-user
          uri: lb://api-user
          predicates:
            - Path=/user/**

 

 

모든 설정을 잘해줬다면 Gateway의 IP에서 Swagger를 접속하면 UI가 잘 뜰 것이다.

ex) localhost:8080/swagger-ui.html

오른쪽 상단에서 모듈을 선택해서 Swagger를 사용하면 된다!

 

 

만약 에러가 뜬다면?

 

1. 각 모듈의 Swagger에서 제공하는 API 문서의 경로(해당모듈의 IP/api-docs의 경로)로 접속해 JSON 문서가 잘 나오는지 확인

 

2. 잘 나온다면 Gateway의 yml파일의 url과 경로가 같은지 확인

 

3. 경로도 같다면 Gateway에서 경로를 해당 모듈로 잘 라우팅 하는지 확인