본문 바로가기
Backend 개발자/StackOverflow

Swagger UI Java 면접과제 Springboot SpringDoc 적용 API문서 자동화 Mock 데이터 샘플 만들기

by by 앵과장 2022. 8. 29.
반응형

API 문서 자동화 사용하는 이유?

Swagger UI API를 설정하고 문서 자동화 하는 이유는 내가 만든 API 인터페이스 문서를 잘 정리해서

다른 개발자들과 사용하는 모든 사람들에게 편의성을 제공하고

어떤 동작을 하는지에 대한 부분을 잘 표현하기 위함이라고 생각하면 됩니다.

 

최근에 사용했던 목적을 정리해보면 

면접 과제용 API 개발하고 표현하기 위해서 많은 시간을 사용한것 같고 

프로젝트 진행하면서 프론트앤드와 개발 진행하고 있는데 일정이 빠듯하다보니 Mock 데이터를 구성해서 API를 제공하는 목적으로 

사용하면서 필요한부분 Swagger UI API를 표현하는 몇가지 유형 그리고 간단하게 API호출하는 테스트 코드까지 만들어 보려고 합니다.

 

Rest Doc을 많이 사용하나요? Swagger UI API를 많이 사용하나요?

이부분은 상황에 따라서 Rest Doc를 사용하기도 하고 Swagger UI를 사용하기도하는데 보통은 

회사에서 자주빈도수 높게 사용하는것 위주로 진행됩니다. 

코드에 스타일과 방법이 일관적인 방향이면 될것 같습니다. 현업에서도 둘다 사용하기 때문에 결국에는 두개다 사용하는 방법을 찾아보시고 알아두면 좋을것 같습니다.

 

Swagger UI 공식 사이트

공식 링크는 아래를 클릭하세요!!

문서 Documentation 그리고 샘플로 작성된 Swagger Site입니다. 

다양한 유형들을 포함하고있어서 참고해서 구성하시면 좋을것 같습니다.

 

REST API Documentation Tool | Swagger UI

 

swagger.io

https://petstore.swagger.io/?_ga=2.21688507.1655130715.1661735233-383348530.1661735233 

 

Swagger UI

 

petstore.swagger.io

pet, store, user 는 Swagger UI로 만들어진 rest API 에대한 설명

아래 models 는 API만들면서 DTO에 해당하는 Request, Response 정의한 파라메타 필드들을 확인할수 있습니다.

Swagger UI 설정말고 Springdoc.org 로 시작해 보겠습니다.

swagger ui 사이트에서 제공하는 설정으로 진행할수있지만 springboot 이기때문에 Springdoc 를 이용해서 진행해보도록 하겠습니다.

내부적으로 swagger ui를 사용하는데 좀더 spring 레이어가 있고 webmvc, webflux 2가지 모두 지원하는 기능이라고 생각하면됩니다.

 

모로가던 Swagger UI API 인터페이스가 잘 나오기만 하면되는거라 한번 시작해보겠습니다.

 

https://springdoc.org/#Introduction

 

OpenAPI 3 Library for spring-boot

Library for OpenAPI 3 with spring boot projects. Is based on swagger-ui, to display the OpenAPI description.Generates automatically the OpenAPI file.

springdoc.org

자세한 정보들은 사이트를 참고하시면됩니다.

 

OpenAPI3 Annotation 설명

AnnotationFieldDescription

@Tag name API 그룹(주로 컨트롤러 단위) 태그 이름
description API 그룹(주로 컨트롤러 단위)에 대한 설명
@Operation summary 메서드 동작에 대한 요약
description 메서드 동작 설명
tags API 그룹 태그 이름 (생략가능)
responses 메서드 Response 목록
parameters 메서드 Parameter 목록
requestBody 메서드 RequestBody
@ApiResponse responseCode HTTP 상태 코드
description Response에 대한 설명
content Response 컨텐츠 유형 설정
- mediaType
- schema : hedden(Schema 숨김 여부), implementation(Schema 대상 클래스)
- examples : Response 예시 (@ExampleObject(value = "") 사용하여 작성)
@Parameter name 파라미터 이름
description 파라미터 설명
required 필수 여부 (true / false)
example 예시 값
@RequestBody description RequestBody에 대한 설명
@Schema name 모델 이름
description 모델 / 필드에 대한 설명
defaultValue 기본 값
required 필수 여부 (true / false)
example 예시 값
@ParameterObject - Parameter Object의 필드를 Query Parameter로 추출

 

SpringDoc 로 시작하는 5분만에 만들어보는 Swagger UI API

 

Spring initializr 프로젝트만들기

https://start.spring.io/

 

Project : Gradle Project

Language : Java

Springboot : 2.7.3

Packaging : jar

java : 11

해당 정보로 프로젝트 생성하도록 하겠습니다. GENERATE 클릭!!

 

build.gradle
plugins {
	id 'org.springframework.boot' version '2.7.3'
	id 'io.spring.dependency-management' version '1.0.13.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	//implementation 'org.springframework.boot:spring-boot-starter-web'

	// spring boot
	implementation 'org.springframework.boot:spring-boot-starter-actuator'
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	implementation 'org.springframework.boot:spring-boot-starter-tomcat'
	implementation 'org.springframework.boot:spring-boot-starter-validation'

	implementation 'com.fasterxml.jackson.core:jackson-databind'
	implementation 'javax.validation:validation-api'

	implementation ('org.springdoc:springdoc-openapi-ui:1.6.9') {
		exclude group: 'org.springdoc', module: 'springdoc-openapi-webmvc-core'
	}
	implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.6.9'

	developmentOnly 'org.springframework.boot:spring-boot-devtools'

	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

javadoc {
	source = sourceSets.main.allJava
	options.encoding = 'UTF-8'
}

tasks.named('test') {
	useJUnitPlatform()
}

webflux 방식으로 처리하였습니다. web servlet 방식으로 하려면 메뉴랑 위에 주석처리한 web을 푸시고 webfulx를 변경하셔야합니다.

 

 

application.yml
server:
  port: 8888
  error:
    include-message: always
    include-binding-errors: always
    include-stacktrace: never
    include-exception: false

spring:
  application:
    name: demo-api-application

logging:
  level:
    org.springframework.boot.autoconfigure: info

springdoc:
  swagger-ui:
    path: /sample/swagger-ui.html
    displayRequestDuration: true
    operationsSorter: method
    apisSorter: alpha
  default-produces-media-type: application/json

기본 port 그리고 swagger ui 설정 정보입니다

 

OpenApiConfig 설정
@OpenAPIDefinition(info = @Info(
        title = "샘플 OpenAPI Doc",
        description = "샘플 대해 설명하는 문서입니다.",
        version = "1.0"),
        servers = @Server(url = "/", description = "Default server url"))
@Configuration
public class OpenApiConfig {
    @Bean
    public OpenApiCustomiser openApiCustomiser() {
        return openApi -> openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {
            ApiResponses apiResponses = operation.getResponses();
            if (!apiResponses.containsKey("404")) {
                apiResponses.addApiResponse("404", new ApiResponse().description("Not Found"));
            }
            if (!apiResponses.containsKey("500")) {
                apiResponses.addApiResponse("500", new ApiResponse().description("Server Error"));
            }
        }));
    }
}

OpenAPiConfig 설정 Class입니다.

 

Controller 만들기 타입A
@RestController
@RequiredArgsConstructor
public class SampleTypeAController {

    private final SampleService sampleService;

    @Operation(
            summary = "기능 단건 검색 TYPEA",
            parameters = {
                    @Parameter(name = "index", description = "일련번호", example = "89821"),
            },
            description = "메뉴에 대한 설명을 기록해 주세요"
    )
    @GetMapping("/sample/typea/{index}")
    public ResponseEntity<GenericCollectionResponse<SampleResponse>> getSample(@PathVariable long index){
        return ResponseEntity.ok(sampleService.getSamples(
                SampleRequest.builder()
                        .index(index)
                        .build()
        ));
    }
}

 

Controller 만들기 타입B
소스코드와 Swagger UI용 Annotation 분리하기
@RestController
@RequiredArgsConstructor
public class SampleTypeBController implements SampleTypeBControllerApi {
    private final SampleService sampleService;

    public ResponseEntity<GenericCollectionResponse<SampleResponse>> getSample(@PathVariable long index){
        return ResponseEntity.ok(sampleService.getSamples(
                SampleRequest.builder()
                        .index(index)
                        .build()
        ));
    }
}

꿀팁

Intellij 를 사용하신다면 controller 에서 interface 추출 팁

controller 선택 Refactor -> Extract interface 선택

Extract Interface 팝업에서 인터페이스 이름을 수정하고 "Member To Form interface" 에서 Member 선택후 Refactor 선택

하시면 작성했던 Controller에서도 Interface를 분리 할수 있습니다. 

 

Controller > Refactor > Extract Interface 선택

 

Interface nam 변경, Members To Form Interface 에서 인터페이스 추출할 method선택

생성된 interface 를 볼수 있고 Implements 에 Swagger Annotation이 생성되었으니 기존에 Controller에 코드는 삭제하시면 됩니다.

@Tag(name = "대메뉴 > 하위메뉴B", description = "메뉴 기능을 제공합니다.")
public interface SampleTypeBControllerApi {
    @Operation(
            summary = "기능 단건 검색 TYPEB",
            parameters = {
                    @Parameter(name = "index", description = "일련번호", example = "89821"),
            },
            description = "메뉴에 대한 설명을 기록해 주세요"
    )
    @GetMapping("/sample/typeb/{index}")
    public ResponseEntity<GenericCollectionResponse<SampleResponse>> getSample(@PathVariable long index);
}
Swagger UI API 잘나오는지 클릭

application.yml 에 설정한 정보를 기반으로 아래 URI로 접근하시면됩니다.

http://localhost:8888/sample/swagger-ui.html

Swagger UI 표현하는방법으로 Controller 을 2가지 방법으로 표현하였습니다.

타입A 는 Controller.java에 swagger ui + code 포함한 내용입니다.

타입B 는 Controller.java Interface.java 2가지를 만들어서 Swagger UI와 Code를 분리하였습니다.

 

2가지모두 사용가능하기때문에 선호 하시는 방법으로 선택하시면 좋을것 같습니다.

 

GitHub 코드는 아래 공유 드립니다.

 

https://github.com/lswteen/swaggerdemo

 

GitHub - lswteen/swaggerdemo: swagger demo Springdoc api

swagger demo Springdoc api. Contribute to lswteen/swaggerdemo development by creating an account on GitHub.

github.com

 

즐거운 코딩 되세요!!