파란하늘의 지식창고
article thumbnail
반응형

이 글의 내용은 Spring Rest Docs를 이미 사용하고 있는 상황에서 OpenAPI 문서를 만들기 위한 내용을 담고 있습니다.


OpenAPI Specification 소개

OpenAPI Specification은 예전엔 Swagger Specification으로 알려졌었다.

OpenAPI Specification은 Rest API에 대해 문서화를 하기 위한 사양을 정의한 것으로 특정한 소프트웨어나 라이브러리가 아니다.

SmartBear Software 회사가 자사 swagger framework에서 REST Api를 문서화하기 위해 사용하던 Swagger Specification을 공개하면서 Linux Foundation의 OpenAPI Initiative project로 관리가 이전되었다.

https://www.openapis.org/

 

Home - OpenAPI Initiative

Something great got better, get excited!

www.openapis.org

그전까지는 Swagger 1.x, 2.x로 불려졌는데 이후엔 OpenAPI 3.x로 불리게 된다.

https://spec.openapis.org/oas/v3.1.0

현재 최신 버전은 3.1.0이다.

Version Date Notes
3.1.0 2021-02-15 Release of the OpenAPI Specification 3.1.0
3.0.3 2020-02-20 Patch release of the OpenAPI Specification 3.0.3
3.0.2 2018-10-08 Patch release of the OpenAPI Specification 3.0.2
3.0.1 2017-12-06 Patch release of the OpenAPI Specification 3.0.1
3.0.0 2017-07-26 Release of the OpenAPI Specification 3.0.0
2.0 2014-09-08 Release of Swagger 2.0
1.2 2014-03-14 Initial release of the formal document
1.1 2012-08-22 Release of Swagger 1.1
1.0 2011-08-10 First release of the Swagger Specification

Swagger UI 소개

swagger ui는 위에서 설명한 OpenAPI specification에 맞춰 생성된 api 문서를 웹 화면으로 보기 위한 toole이다.

https://swagger.io/tools/swagger-ui/

 

REST API Documentation Tool | Swagger UI

 

swagger.io

어떤 식으로 보여주는지는 아래 live demo를 보면 한눈에 알 수 있다.

https://petstore.swagger.io/

해당 사이트를 보면 아래 주소를 조회하여 문서를 보여주고 있다.

https://petstore.swagger.io/v2/swagger.json

이 json은 swagger 2.0으로 만들어진 문서이고 대락 이런 식으로 api 문서가 구성되는구나 생각하면 된다.

이 규약이 이후 OpenAPI로 바뀌면서 swagger 관련 schema는 변경되어 쓰인다.

{
    "swagger": "2.0",
    "info": {
        "description": "This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.",
        "version": "1.0.6",
        "title": "Swagger Petstore",
        "termsOfService": "http://swagger.io/terms/",
        "contact": {
            "email": "apiteam@swagger.io"
        },
        "license": {
            "name": "Apache 2.0",
            "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
        }
    },
    "host": "petstore.swagger.io",
    "basePath": "/v2",
    "tags": [...],
    "schemes": [...],
    "paths": {...},
    "securityDefinitions": {...},
    "definitions": {...},
    "externalDocs": {
        "description": "Find out more about Swagger",
        "url": "http://swagger.io"
    }
}

 

어디선가 이러한 형태의 OpenAPI 문서를 만들면 이 문서를 Swagger UI가 조회하여 화면에 보여준다.

형식은 json 뿐만 아니라 yaml로도 사용할 수 있다.

Spring Rest Docs에서 OpenAPI 문서 만들기

markdown 문법으로 작성된 파일을 asciidoctor를 통해 html, pdf, epub, docbook 등과 같은 다양한 문서 파일을 만들 수 있다.

Spring Rest Docs는 정해진 문법으로 생성한 java의 테스트 코드를 실행한 내용에 대해 documentation snippet을 만들어 문서에 코드 부분을 추가하기 위해 만들어진 extension이다.

https://docs.spring.io/spring-restdocs/docs/current/reference/html5/

 

Spring REST Docs

Document RESTful services by combining hand-written documentation with auto-generated snippets produced with Spring MVC Test, WebTestClient, or REST Assured.

docs.spring.io

asciidoctor 자체가 문서를 만들기 위해 널리 쓰이기도 하고 수많은 extension이 있다.

또한 관련한 내용을 여러 번 작성한 적이 있다.

2019.06.14 - [Study/Java] - Spring Rest Docs 사용해보기

2020.06.12 - [Study/Java] - spring reference 문서는 어떻게 만들어질까?

2020.07.17 - [Study/Java] - spring-asciidoctor-extensions 사용해보기

2022.02.19 - [Study/Java] - java project에서 maven으로 asciidoctor-diagram 사용해보기

이런 수많은 extension 중엔 Spring이 asciidocotor에서 사용하기 위해 생성한 documentation snippet을 OpenAPI로 변경하기 위한 extension도 있다.

이 글에서는 Spring Rest Docs를 이미 사용하고 있다는 가정하에 작성하였기 때문에 관련 내용은 생략한다.

Spring REST Docs API specification Integration

Spring REST Docs API specification Integration은 Spring REST Docs의 output format에 API specification을 추가하는 extension이다.

다음과 같은 API specification을 지원한다.

  • OpenAPI 2.0
  • OpenAPI 3.0.1
  • Postman Collections 2.1.0

https://github.com/ePages-de/restdocs-api-spec

 

GitHub - ePages-de/restdocs-api-spec: Adds API specification support to Spring REST Docs

Adds API specification support to Spring REST Docs - GitHub - ePages-de/restdocs-api-spec: Adds API specification support to Spring REST Docs

github.com

다음과 같이 의존성을 추가한다.

<dependency>
    <groupId>com.epages</groupId>
    <artifactId>restdocs-api-spec</artifactId>
    <version>0.16.2</version>
</dependency>

Spring Rest Docs에서 documentation snippet을 생성하기 위해 테스트 코드를 사용하는데 mockmvc, restassured를 사용하고 있다면 각각에 해당하는 라이브러리를 추가하면 기존 코드를 좀 더 쉽게 migration 할 수 있다.

  • restdocs-api-spec-mockmvc
  • restdocs-api-spec-restassured
  • restdocs-api-spec-webtestclient

내 경우 mockmvc를 사용하여서 다음과 같이 추가하였다.

<dependency>
    <groupId>com.epages</groupId>
    <artifactId>restdocs-api-spec-mockmvc</artifactId>
    <version>0.16.2</version>
</dependency>

해당 라이브러리를 추가하면 MockMvcRestDocumentationWrapper를 사용할 수 있다.

기존 코드의 document 생성 부분에 다음과 같이 MockMvcRestDocumentationWrapper를 추가한다.

document(...)인 부분이 MockMvcRestDocumentationWrapper.document(...)로 바뀐 것 말고 나머지는 모두 그대로다.

resultActions
  .andDo(
    MockMvcRestDocumentationWrapper.document(operationName,
      requestFields(fieldDescriptors().getFieldDescriptors()),
      responseFields(
        fieldWithPath("comment").description("the comment"),
        fieldWithPath("flag").description("the flag"),
        fieldWithPath("count").description("the count"),
        fieldWithPath("id").description("id"),
        fieldWithPath("_links").ignored()
      ),
      links(linkWithRel("self").description("some"))
  )
);

restassured를 사용한다면 restdocs-api-spec-restassured dependency를 추가하고 동일한 형태로 RestAssuredRestDocumentationWrapper를 추가하면 된다.

webtestclient를 사용한다면 restdocs-api-spec-webtestclient dependency를 추가하고 동일한 형태로 WebTestClientRestDocumentationWrapper를 추가하면 된다. 

이렇게 테스트 코드 상 api 문서를 만들 준비가 끝났다.

여기까지 진행하고 문서를 생성하더라도 아무런 변화가 없다.

빌드 시 api 문서를 추가로 만드는 플러그인을 추가해야 한다.

restdocs-spec-maven-plugin 추가하기

gradle plugin의 경우 restdocs-api-spec에서 기본 제공된다.

관련 설정도 해당 프로젝트에 자세히 안내되어 있다.

https://github.com/ePages-de/restdocs-api-spec#gradle-plugin-configuration

maven plugin의 경우 따로 프로젝트가 있다.

https://github.com/BerkleyTechnologyServices/restdocs-spec

asciidoctor 빌드 시 설정한 기존 plugin인 설정에 이어 restdocs-spec-maven-plugin을 추가하면 된다.

<plugin>
    <groupId>io.github.berkleytechnologyservices</groupId>
    <artifactId>restdocs-spec-maven-plugin</artifactId>
    <version>${restdocs-spec-maven-plugin.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <specification>OPENAPI_V3</specification>
            </configuration>
        </execution>
    </executions>
</plugin>

좀 더 자세한 설정은 해당 사이트에 안내되어 있다.

별다른 설정 없이 plugin을 추가하면 기본 경로인  ${project.build.directory}/restdocs-spec에 api 문서가 생성된다.

Swagger UI에 추가하기

Swagger UI 다운로드하기

Swagger UI는 생성된 api 문서를 호출하여 화면에 뿌려준다.

Swagger UI는 html과 js, css로 이루어진 웹페이지이기 때문에 다운로드하여서 서버에 띄우고 호출하면 된다.

swagger ui github의 Releases에서 Source code를 다운로드하여 압축을 풀면 dist 폴더가 있다.

https://github.com/swagger-api/swagger-ui/releases

source code는 사용하지 않으니 dist 폴더의 내용을 적당한 웹서버에 올리면 된다.

Swagger UI 설정하기

Swagger UI의 설정은 swagger-initializer.js에서 한다.

해당 파일을 열어보면 처음에는 다음과 같다.

window.onload = function() {
  //<editor-fold desc="Changeable Configuration Block">

  // the following lines will be replaced by docker/configurator, when it runs in a docker-container
  window.ui = SwaggerUIBundle({
    url: "https://petstore.swagger.io/v2/swagger.json",
    dom_id: '#swagger-ui',
    deepLinking: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
  });

  //</editor-fold>
};

샘플 예제 주소인 https://petstore.swagger.io/v2/swagger.json를 호출해서 화면을 보여주는데 이 페이지의 경우 그냥 로컬에 있는 dist 폴더의 index.html을 열어도 확인할 수 있다.

이제 내가 사용하길 원하는 주소를 추가하면 되는데 단순히 url만 바꾸면 swagger ui의 최상단 Explore의 기본 호출 주소가 바뀌고 다른 주소를 가려면 일일이 다시 입력해야 한다.

사용하고자 하는 url만 모아서 보여주는 처리는 기존 url 설정을 지우고 urls 설정을 다음과 같이 추가하면 된다.

window.onload = function() {
  //<editor-fold desc="Changeable Configuration Block">

  // the following lines will be replaced by docker/configurator, when it runs in a docker-container
  window.ui = SwaggerUIBundle({
    urls: [ 
		{"name" : "테스트1", "url" : "https://petstore.swagger.io/v2/swagger.json"},
		{"name" : "테스트2", "url" : "https://다른API문서주소"}
	],
    dom_id: '#swagger-ui',
    deepLinking: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
  });

  //</editor-fold>
};

이렇게 추가하면 상단의 Explore가 다음과 같이 select 메뉴로 변경된다.

실제 사용하려면 호출 대상 서버에 Cors 설정을 하는 등의 추가 작업이 필요하겠지만 관련한 설명은 생략한다.

그 밖에도 다양한 설정을 할 수 있는데 이러한 설정에 대해서는 Swagger UI 문서를 참고하면 된다.

https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/

 

Swagger Documentation

Configuration How to configure Swagger UI accepts configuration parameters in four locations. From lowest to highest precedence: The swagger-config.yaml in the project root directory, if it exists, is baked into the application configuration object passed

swagger.io

Swagger UI에서 호출하는 API 문서에 host관련 설정이 있으면 Swagger UI에서는 해당 주소를 호출하여 API 동작을 직접 테스트할 수 있다.

호출 주소에 대한 설정은 API 문서를 만드는 대상 프로젝트 maven pom.xml의 restdocs-spec-maven-plugin configuration에 설정하면 된다.

<plugin>
    <groupId>io.github.berkleytechnologyservices</groupId>
    <artifactId>restdocs-spec-maven-plugin</artifactId>
    <version>${restdocs-spec-maven-plugin.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <specification>OPENAPI_V3</specification>
                <host>해당API주소</host>
            </configuration>
        </execution>
    </executions>
</plugin>

추가 설명

OpenApi.Tools 소개

이제까지 OpenAPI 문서를 사용하기 위해 Asciidoctor extension인 Spring Rest Docs와 restdocs-api-spec, restdocs-spec-maven-plugin 및 Swagger UI를 사용하는 것에 대해서 설명했다.

OpenAPI는 공개된 specification이기 때문에 이를 이용한 수많은 오픈 소스가 파생되고 있다.

어떤 게 있는지 궁금하다면 아래 사이트를 가보면 된다.

https://openapi.tools/

 

OpenAPI.Tools

Writing YAML by hand is no fun, and maybe you don't want a GUI, so use a Domain Specific Language to write OpenAPI in your language of choice. Name Language v3.1 v3.0 v2.0 GitHub BOATS - BOATS allows for larger teams to contribute to multi-file OpenAPI def

openapi.tools

이 글에서는 Swagger UI를 사용하는 것에 대해 설명했지만 위 사이트의 Tool Types에서 documentation 항목을 가보면 다양한 tool이 존재한다.

OpenAPI를 활용하는 방법은 다양하므로 위 사이트를 살펴보면서 상황에 맞는 tool을 찾아보면 좋을 것 같다.

SwaggerHub 소개

Swagger UI에서 사용하는 API 문서를 직접 만들어보거나 테스트하고 싶거나 혹 다른 사람이 만든 걸 참고하고 싶은 경우 Swagger Hub를 구경하면 된다.

https://app.swaggerhub.com/

swagger hub는 docker hub와 비슷한데 API document를 관리하는 곳이다.

3 public 까진 무료이고 팀 단위나 기업 단위로 사용하려면 비용이 든다.

https://swagger.io/tools/swaggerhub/pricing/

굳이 사용하지 않더라도 다른 사람의 설정들을 참고하기 좋기 때문에 소개해본다.

springdoc-openapi 소개

Rest Doc의 documentation snippet 기반의 API 문서 생성이 부담되고 좀 더 편하게 사용하길 원하는 경우,

Spring Controller annotation 기반으로 OpenAPI 문서를 자동으로 생성하여 사용하길 원하는 경우 springdoc-openapi를 사용하면 된다.

https://springdoc.org/

이전에는 springfox라는 라이브러리가 있었는데 2020년 10월 즈음 이후엔 더 이상 개발되지 않는 것 같다.

dependency만 추가해도 해당 프로젝트의 호출을 찾아서 문서화를 해주기 때문에 쉽게 쓸 수 있다.

현재 사용해보고 있는 설정

swagger ui configuration : https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/

아래와 같은 값들을 추가로 설정하고 있다.

window.ui = SwaggerUIBundle({
    urls: [
	    // … 이하 생략
    ],
    operationsSorter : "alpha",
    withCredentials : true,
    queryConfigEnabled : true,
    //... 이하 생략
}

추가로 설정한 옵션들의 역할은 다음과 같다.

Parameter Name Description
urls 기본 설정인 url을 사용하면 검색창에 해당 url이 설정되고 다른 url들을 검색할 수 있게 제공함
하지만 urls로 설정하면 설정된 url들만 사용할 수 있는 select 형태로 변경됨
operationSorter 기본 설정은 서버가 반환한 순서대로 이지만 'alpha' (주소를 알파벳 순 정렬) 또는 'method' (주소를 HTTP method 순으로 정렬) 로 설정할 수 있음
withCredentials true 로 설정 시 요청에 header cookie값을 같이 보냄
queryConfigEnabled 위에 선언한 urls의 셀렉트 박스를 통해 url을 설정하면 해당 선택에 대한 주소관련 parameter가 붙는데 이 parameter를 사용하는 옵션
(이 옵션을 활성화 해야 주소 복사로 공유가 가능)
반응형
profile

파란하늘의 지식창고

@Bluesky_

내용이 유익했다면 광고 배너를 클릭 해주세요