Swagger

goose_bumps·2025년 4월 10일

SpringBoot

목록 보기
4/9

API를 개발하려면 명세가 필요하다. 이 API가 무슨 기능을 하고 어떤 로직을 수행하며 그 로직을 수행하기 위해 어떤값을 입력받아야 하는지 그리고 출력값은 어떻게 되는지 등을 정리한 자료를 명세라고 한다.

옛날에는 API를 개발하면 명세 문서도 작성하고 그 API의 내용이 변경될 때마다 명세 문서도 업데이트를 했어야 했다.
이러한 과정은 번거롭고 오히려 개발의 생산성을 떨어뜨릴 수 있다.

하지만, Swagger를 사용하면 명세 문서 작성 필요없이 API를 개발할 수 있다.
Swagger는 API의 명세 문서를 자동으로 생성하며 Swagger UI를 사용하여 API에 대한 이해와 테스트가 가능하다.

스프링부트 2.x 시절에는 Springfox 패키지를 통해 생성하였는데 스프링부트 3.x로 넘어오면서 springdoc-openapi 패키지를 통해 생성하는 것으로 변경되었다.

build.gradle 파일에

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

다음과 같이 의존성을 추가하면 된다.

Swagger 설정을 위해 클래스를 만들어주어야 하는데

@Configuration
public class SwaggerConfiguration {
    //설정 로직
    }
}

설정 코드를 작성할 클래스에 @Configuration 에너테이션을 추가하면 된다.

이제 @Bean을 추가하여 설정을 하면 되는데 Springfox 시절과 변경된 점이 있다.

1. 명세화 범위 설정

@Configuration
public class SwaggerConfiguration {

    @Bean
    public GroupedOpenApi api(){
        return GroupedOpenApi.builder()
                .group("com.example.demo")
                .packagesToScan("com.example.demo")
                .build();
    }
}

GroupedOpenApi는 어떤 API에 대한 명세를 만들지, 즉 어느 범위까지 명세를 만들면 되는지 설정하는 것이다.
우선 groupdemo 패키지로 설정하여 전체를 그룹으로 설정하였다.
그 다음 packagesToScan은 문서화할 컨트롤러의 범위를 설정하는 메서드로 모든 API를 문서화할거라면 그룹과 동일하게 지정하면 된다.
demo 패키지의 하위 패키지인 PackageA만 문서화하고 싶으면 인자로 "com.example.demo.PackageA"로 입력하면 된다.

2. API에 명세 추가

API에 대한 설명을 작성하기 위해서는 @Operation 에너테이션을 사용하고 매개변수를 통해 설정이 가능하다.

예를 들어, GET API에 대한 설명 제목을 "상품의 정보를 조회하는 메서드"으로 지정하고 세부설명으로 "@RequestParam으로 상품 고유번호를 인자로 받아 해당 상품을 조회할 수 있음"으로 해보자.

그러기 위해서는 에너테이션을 다음과 같이 설정하면 된다.

@Operation(summary = "상품의 정보를 조회하는 메서드", description = "@RequestParam으로 상품 고유번호를 인자로 받아 해당 상품을 조회할 수 있음")

매개변수에 대한 설명을 추가하고자 할 경우 @Parameter를 사용하면 된다.
소괄호를 열어 속성을 입력할 수 있는데 다음과 같이 사용할 수 있다.

  • description : 설명을 작성
  • example : 예시 값 제공
  • required : 필수 여부 (true/false)

자 그렇다면 매개변수의 명세를 다음과 같이 만들어보겠다.

  • 설명 : 상품의 고유번호를 입력해야 number를 통해 상품을 조회
  • 예시 : "http://localhost:8080/product/1"
  • 필수 여부 : true(이 파라미터가 필수적으로 입력해야 하는 것인지 아닌지를 설정)
    @Operation(summary = "상품의 정보를 조회하는 메서드", 
    			description = "@RequestParam으로 상품 고유번호를 인자로 받아 해당 상품을 조회할 수 있음")
    @GetMapping("/{productID}")
    public ResponseEntity<ProductResponseDTO> getProduct(
            @Parameter(description = "상품의 고유번호를 입력해야 `number`를 통해 상품을 조회",
                        example = "http://localhost:8080/product/1",
                        required = true)
            @PathVariable("productID") Long number){
        ProductResponseDTO productResponseDTO = productService.getProduct(number);
        return ResponseEntity.status(HttpStatus.OK).body(productResponseDTO);
    }

3. 문서 전체에 대한 명세

스캔할 컨트롤러의 범위를 지정하면 그 컨트롤러들에 대해서만 명세를 만드는데 전체에 대한 설명을 추가할 수 있다.

예를 들어, 제목은 "상품을 조회,저장,수정,삭제하는 메서드"로 정하고 이에 대한 설명으로 "MariaDB와 연동하여 상품에 대한 정보를 데이터베이스에서 조작하고 상품의 고유번호를 통해 상품을 조회하거나 삭제할 수 있으며 상품의 이름을 수정할 수 있습니다."로 추가해보겠다.

@OpenAPIDefinition 에너테이션을 사용하면 되는데 다음과 같이 Application 클래스에 추가하면 된다.

@OpenAPIDefinition(
		info = @Info(
				title = "상품을 조회,저장,수정,삭제하는 메서드",
				version = "1.0.0",
				description = "MariaDB와 연동하여 상품에 대한 정보를 데이터베이스에서 조작하고 상품의 고유번호를 통해 상품을 조회하거나 삭제할 수 있으며 상품의 이름을 수정할 수 있습니다."
		)
)
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

자 이제 직접 실행하여 결과를 확인해보자.

이렇게 명세를 작성하면 다른 개발자가 테스트를 할 경우 이 API들이 무슨 용도이고 왜 만들었는지 바로 알 수 있어 개발의 생산성이 더 높아질 것이다.

https://springdoc.org/index.html#Introduction

springdoc를 참고하였으며 Springfox와 비교해 달라진 점들은 Migrating from Springfox를 참고하면 된다.

추가로 컨트롤러로 사용하는 클래스에 @Controller만 있을 경우 Restful API 앤드포인트로 스캔하지 못하기 때문에 @Controller + @ResponseBody의 조합인 @RestController를 사용해야 한다.

0개의 댓글