Swagger + RestDocs
Web Testing환경을 쉽게 제공하지만, 테스트 안정적이지 못한 Swagger와 테스트 안정적이지만 Web Testing을 할 수 없고,asciidoctor 의 편집이 까다로운 restdocs의 장점을 합쳐 swagger의 Web 환경에서 Restdocs로 생성된 API 가이드를 확인하고 실행까지 시켜볼 수 있도록 하는 프로젝트
Git Repository Address
1.기존 Swagger, RestDocs 사용 방식과의 구별 점
•
Swagger dependency 가 필요하지 않습니다.
◦
Swagger의 경우 standalone으로 사용할 것이기에 별도의 의존성 필요가 없습니다.
•
asciidoctor 를 따로 편집하지 않습니다.
◦
기존 restdocs로 생성되는 문서들을 종합하여 보여주는 asciidoctor 문서를 따로 편집하지 않습니다.추출된 OAS 파일을 Swagger 디렉토리로 복사하여 Swagger환경에서 노출되도록 합니다.
•
spring REST Docs 의존성 변경
◦
2. 구현 방법
구현 방법은 Maven 기준으로 진행하며, 다음과 같습니다.
1. Swagger-UI standalone 세팅
1.
다음 링크[ link ]에서 source를 다운받아 /dist의 내용을 프로젝트의 /resources/static/swagger-ui/ 경로에 집어넣도록 하며 이 때 폴더 구조는 다음과 같습니다.
2.
복사한 파일 중 이름 변경이 필요한 파일 수정과, 불필요한 파일을 제거한다.
a.
index.html → swagger-ui.html 이름 변경
b.
index.html 내부의 js, css경로를 static routing경로로 변경
c.
SwaggerUIBundle 메서드의 경로는 생성되어 복사 될 파일의 경로로 입력(ex: openapi-3.0.json or openapi-3.0.yaml)
d.
불필요한 파일 삭제
i.
oauth2-redirect.html
ii.
swagger-ui.js
iii.
swagger-ui-es-bundle-core.js
iv.
swagger-ui-es-bundle.js
3.
Static Routing 설정하기
@Configuration
public class StaticRoutingConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/static/swagger-ui");
}
}
Java
복사
2. dependency 설정
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<asciidoctor.version>2.2.2</asciidoctor.version>
<restdocs-api-spec.version>0.16.0</restdocs-api-spec.version>
<restdocs-spec.version>0.21</restdocs-spec.version>
</properties>
XML
복사
<dependency>
<groupId>com.epages</groupId>
<artifactId>restdocs-api-spec</artifactId>
<version>${restdocs-api-spec.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.epages</groupId>
<artifactId>restdocs-api-spec-mockmvc</artifactId>
<version>${restdocs-api-spec.version}</version>
<scope>test</scope>
</dependency>
XML
복사
<plugin>
<groupId>io.github.berkleytechnologyservices</groupId>
<artifactId>restdocs-spec-maven-plugin</artifactId>
<version>${restdocs-spec.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!--suppress MavenModelInspection -->
<skip>${skipTests}</skip>
<specification>OPENAPI_V3</specification>
<name>[OAS + Swagger] Prototype</name>
<description>restDocs로 생성되는 API 문서를 OAS(OpenApi Specification)을 이용해 Swagger로 표출하기</description>
<format>JSON</format>
<host>localhost:8080</host>
<outputDirectory>${project.build.directory}/classes/static/swagger-ui/.</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
XML
복사
3. 테스트 코드 작성
이제 문서화를 할 테스트를 작성해 줍니다.테스트 케이스 샘플 코드
참고: 기존 REST Docs로 작성한 코드도 적용하고싶다면?
이 경우 기존 사용하고 있던 Spring의 MockMvcRestDocumentation를 MockMvcRestDocumentationWrapper로 바꿔주면 된다.
4. 실행하기
4.1 수동으로 Maven command 실행
mvn clean package
5. 실행 후 생성된 OAS 확인
기본적으로 target/classes/static/swagger-ui/ 경로에 json혹은 yaml으로 생성된다.
{
"openapi" : "3.0.1",
"info" : {
"title" : "[OAS + Swagger] Prototype",
"description" : "restDocs로 생성되는 API 문서를 OAS(OpenApi Specification)을 이용해 Swagger로 표출하기",
"version" : "0.0.1-SNAPSHOT"
},
"servers" : [ {
"url" : "<http://localhost:8080">
} ],
"tags" : [ ],
"paths" : {
"/api/products" : {
"get" : {
"tags" : [ "상품 관리 API" ],
"summary" : "상품 전체 조회 API",
"description" : "상품 전체 조회 API",
"operationId" : "상품 목록 조회",
"responses" : {
"200" : {
"description" : "200",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/상품 응답 객체 형식"
},
"examples" : {
"상품 목록 조회" : {
"value" : "[{\"id\":1,\"price\":1000,\"name\":\"사과\"},{\"id\":2,\"price\":2000,\"name\":\"포도\"}]"
}
}
}
}
}
}
},
"post" : {
"tags" : [ "상품 관리 API" ],
"summary" : "상품 저장",
"description" : "상품 저장",
"operationId" : "상품 저장 성공유효하지 않은 상품 저장 정보- 상품 가격유효하지 않은 상품 저장 정보- 상품명",
"requestBody" : {
"content" : {
"application/json;charset=UTF-8" : {
"schema" : {
"$ref" : "#/components/schemas/api-products-971553285"
},
"examples" : {
"상품 저장 성공" : {
"value" : "{\"price\":2500,\"name\":\"딸기\"}"
},
"유효하지 않은 상품 저장 정보- 상품 가격" : {
"value" : "{\"price\":-1000,\"name\":\"수박\"}"
},
"유효하지 않은 상품 저장 정보- 상품명" : {
"value" : "{\"price\":1500,\"name\":\"\"}"
}
}
}
}
},
"responses" : {
"201" : {
"description" : "201",
"headers" : {
"location" : {
"description" : "생성된 상품 조회 상세정보 URL",
"schema" : {
"type" : "string"
}
}
},
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/저장된 상품 정보"
},
"examples" : {
"상품 저장 성공" : {
"value" : "{\"id\":3,\"price\":2500,\"name\":\"딸기\"}"
}
}
}
}
},
"400" : {
"description" : "400",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/에러 형식"
},
"examples" : {
"유효하지 않은 상품 저장 정보- 상품 가격" : {
"value" : "{\"status\":\"400 BAD_REQUEST\",\"message\":\"상품 가격은 0원 이상이어야 합니다.\"}"
},
"유효하지 않은 상품 저장 정보- 상품명" : {
"value" : "{\"status\":\"400 BAD_REQUEST\",\"message\":\"이름을 입력해주세요.\"}"
}
}
}
}
}
}
}
}
},
"components" : {
"schemas" : {
"상품 응답 객체 형식" : {
"title" : "상품 응답 객체 형식",
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"price" : {
"type" : "number",
"description" : "상품 가격"
},
"name" : {
"type" : "string",
"description" : "상품명"
},
"id" : {
"type" : "number",
"description" : "상품 식별자"
}
}
}
},
"에러 형식" : {
"title" : "에러 형식",
"type" : "object",
"properties" : {
"message" : {
"type" : "string",
"description" : "예외 메세지"
},
"status" : {
"type" : "string",
"description" : "상태 코드"
}
}
}
}
}
}
JSON
복사
6. 결과
3. 차후 고려사항
•
문서화를 보여주기 위해 별도의 리팩토링이나 주석 생략한걸 리팩토링 할 지 차후 고려
•
docker based Swagger-ui 서버 구축하여 document server 분리
•
신규 프로젝트를 위한 Gradle 버전 build.gradle 문서 작성
•
MSA 환경에서 각각의 아키텍처의 테스트 문서(OAS)를 종합할 수 있는 기능이 가능한지 기술 검토 필요
•
Select Group 이 아닌 URI Explore 사용방식이 번거로울 수 있기에 간편화 가능할지 검토
◦
Swagger를 Docker로 구현할 경우 URL 을 Name으로 그룹을 지정할 수 있어 가능함.