<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Swagger on</title><link>https://taetaetae.github.io/tags/swagger/</link><description>Recent content in Swagger on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Tue, 22 Dec 2020 10:41:40 +0900</lastBuildDate><atom:link href="https://taetaetae.github.io/tags/swagger/index.xml" rel="self" type="application/rss+xml"/><item><title>Swagger와 Spring Restdocs의 우아한 조합 (by OpenAPI Spec)</title><link>https://taetaetae.github.io/posts/a-combination-of-swagger-and-spring-restdocs/</link><pubDate>Tue, 22 Dec 2020 10:41:40 +0900</pubDate><guid>https://taetaetae.github.io/posts/a-combination-of-swagger-and-spring-restdocs/</guid><description>&lt;p>　﻿MSA 환경에서의 API 문서화는 어떤 식으로 구성하는 걸까? 예컨대, 모듈이 10개 있다고 하면 각 모듈마다 API 문서가 만들어질 테고 API 문서를 클라이언트에 제공하기 위해서 각각의 (10개의) URL를 전달해야 할 텐데 이게 과연 효율적일까? 물론 기능별로 URL이 분리된다는 장점이 있고 굳이 모아보자면 각 API 문서를 다시 한번 크롤링 하여 검색할 수 있도록 제공하는 것도 하나의 방법이 될 수 있다. 하지만 이러한 방법들은 요구 사항을 위한 별도의 작업을 하게 되니 일을 위한 일이 되는 것 같아 뭔가 아쉬웠다. 좋은 방법이 없을까?&lt;/p>
&lt;h2 id="고민의-시작">고민의 시작&lt;/h2>
&lt;p>　한창 궁금증이 머릿속에서 지워지지 않았을때 &lt;a href="https://www.facebook.com/groups/springkorea/permalink/2731936460251299/" target="_blank" rel="noopener noreffer ">Spring 한국 스프링 사용자 모임 페이스북 그룹&lt;/a>에 문의도 해가며 방법을 찾아가고 있었다.&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-1.png" title="/images/a-combination-of-swagger-and-spring-restdocs/line-1.png" data-thumbnail="/images/a-combination-of-swagger-and-spring-restdocs/line-1.png" data-sub-html="&lt;h2>﻿닉네임이나 프로필 사진은 그들의 개인 정보를 위해 임의로 지정하였다.&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-1.png"
 data-srcset="https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-1.png, https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-1.png 1.5x, https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-1.png 2x"
 data-sizes="auto"
 alt="/images/a-combination-of-swagger-and-spring-restdocs/line-1.png" width="80%" />
 &lt;/a>&lt;figcaption class="image-caption">﻿닉네임이나 프로필 사진은 그들의 개인 정보를 위해 임의로 지정하였다.&lt;/figcaption>
 &lt;/figure>
&lt;p>　﻿필자와 함께 개발자의 인생을 시작한 멋진 친구들에게 정확히 올해 6월 초에 고민을 털어놓으며 좋은 방법이 없을지에 대한 논의를 했던 적이 있다. 그런데 친구 중 한 명이 잊고 있었던 그 이슈에 대해서 다시 꺼내며 URL 하나를 던져준다. 참 고마운 친구들.&lt;/p>
&lt;blockquote>
&lt;p>Shout out 34. &lt;a href="http://asuraiv.tistory.com/" target="_blank" rel="noopener noreffer ">asuraiv&lt;/a>, &lt;a href="https://black9p.github.io/" target="_blank" rel="noopener noreffer ">black9p&lt;/a>&lt;/p>&lt;/blockquote>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-2.png" title="/images/a-combination-of-swagger-and-spring-restdocs/line-2.png" data-thumbnail="/images/a-combination-of-swagger-and-spring-restdocs/line-2.png" data-sub-html="&lt;h2>언 반년이 지났으나 필자도 잊고 있었던 이슈를 그는 기억하고 있었다.&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-2.png"
 data-srcset="https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-2.png, https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-2.png 1.5x, https://taetaetae.github.io/images/a-combination-of-swagger-and-spring-restdocs/line-2.png 2x"
 data-sizes="auto"
 alt="/images/a-combination-of-swagger-and-spring-restdocs/line-2.png" width="40%" />
 &lt;/a>&lt;figcaption class="image-caption">언 반년이 지났으나 필자도 잊고 있었던 이슈를 그는 기억하고 있었다.&lt;/figcaption>
 &lt;/figure>
&lt;p>　﻿올해 NHN FORWARD에서 진행했던 세션 중에서 &lt;a href="https://forward.nhn.com/session/3" target="_blank" rel="noopener noreffer ">MSA 환경에서 API 문서 관리하기: 생성부터 배포까지&lt;/a>라는 제목의 내용이었고, 정확하게 필자가 고민했던 부분을 콕! 집어서 해결해 준 사례였다. 역시 세상엔 엄청난 고수들이 내가 고민했던 부분들을 이미(혹은 이후에라도) 고민하고 해결한 경우가 많다는 것을 느끼고 공유의 힘이 이렇게도 대단하구나 하며 놀라움을 금치 못하였다.﻿&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/qguXHW0s8RY?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video">&lt;/iframe>
 &lt;/div>

&lt;p>　﻿이번 포스팅에서는 OpenAPI Spec 을 활용하여 Spring Restdocs로 만들어지는 문서를 Swagger UI에서 보는 흐름을 실제로 구현해 보고자 한다. 즉, Swagger 나 Spring Restdocs 뭐로 만들든 간에 OpenAPI Spec에 맞춰서만 만든다면 한곳에서 볼 수 있겠다는 희망이 보였다. 며칠 전 작성한 &lt;a href="https://taetaetae.github.io/posts/openapi-and-swagger-ui-in-spring-boot/" rel="">OpenAPI 와 Swagger-ui 포스팅&lt;/a>을 본 독자들은 지금의 포스팅을 작성하기 위한 밑거름이었다는 사실을 눈치챘을 수도 있을 것 같다.&lt;/p>
&lt;blockquote>
&lt;p>﻿좋은 내용을 공유해 주신 (저의 고민을 완벽하게 해결해 주신) NHN FORWARD 발표자분께 이 포스팅을 빌어 감사의 인사를 보냅니다. :) 당장 팀 내에도 적용해봐야겠어요!!&lt;/p>&lt;/blockquote>
&lt;h2 id="spring-restdocs에서-openapi-spec-추출">﻿Spring Restdocs에서 OpenAPI Spec 추출&lt;/h2>
&lt;p>　﻿누가 또 친절하게 오픈소스로 만들어놨다. &lt;a href="https://github.com/ePages-de/restdocs-api-spec" target="_blank" rel="noopener noreffer ">https://github.com/ePages-de/restdocs-api-spec&lt;/a> 에서 관련 내용을 확인할 수가 있는데 해당 링크에서는 gradle 버전이고 &lt;a href="https://github.com/BerkleyTechnologyServices/restdocs-spec" target="_blank" rel="noopener noreffer ">https://github.com/BerkleyTechnologyServices/restdocs-spec&lt;/a> 는 maven 버전이라고 한다. 마침 필자의 Github에 Maven 버전으로 SpringRestdocs를 세팅해둔 &lt;a href="https://github.com/taetaetae/SpringRestDocs-In-SpringBoot" target="_blank" rel="noopener noreffer ">Repository&lt;/a> 가 있어서 이를 활용해보고자 한다.﻿&lt;/p>
&lt;h3 id="pomxml-추가">pom.xml 추가&lt;/h3>
&lt;p>　﻿관련 dependency를 추가하자. jcenter라고 bintray.com 에서 운영되는 Maven Repository에 올려진 오픈소스이니 repository 도 추가해 주자.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;properties&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;restdocs-api-spec.version&amp;gt;&lt;/span>0.10.0&lt;span class="nt">&amp;lt;/restdocs-api-spec.version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;restdocs-spec.version&amp;gt;&lt;/span>0.19&lt;span class="nt">&amp;lt;/restdocs-spec.version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/properties&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;repositories&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;repository&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">		&lt;span class="nt">&amp;lt;id&amp;gt;&lt;/span>jcenter&lt;span class="nt">&amp;lt;/id&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">		&lt;span class="nt">&amp;lt;url&amp;gt;&lt;/span>https://jcenter.bintray.com&lt;span class="nt">&amp;lt;/url&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;/repository&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/repositories&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>com.epages&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>restdocs-api-spec&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;version&amp;gt;&lt;/span>${restdocs-api-spec.version}&lt;span class="nt">&amp;lt;/version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;scope&amp;gt;&lt;/span>test&lt;span class="nt">&amp;lt;/scope&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>com.epages&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>restdocs-api-spec-mockmvc&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;version&amp;gt;&lt;/span>${restdocs-api-spec.version}&lt;span class="nt">&amp;lt;/version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;scope&amp;gt;&lt;/span>test&lt;span class="nt">&amp;lt;/scope&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/dependency&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>﻿위의 dependency에서 제공해 주는 모듈로 테스트의 SpringRestdocs를 만들었다면 OpenAPI Spec 을 만들어 주는 plugin 또한 추가해 주자&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;pluginRepositories&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;pluginRepository&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">		&lt;span class="nt">&amp;lt;id&amp;gt;&lt;/span>jcenter&lt;span class="nt">&amp;lt;/id&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">		&lt;span class="nt">&amp;lt;url&amp;gt;&lt;/span>https://jcenter.bintray.com&lt;span class="nt">&amp;lt;/url&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;/pluginRepository&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/pluginRepositories&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;plugin&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>com.github.berkleytechnologyservices.restdocs-spec&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>restdocs-spec-maven-plugin&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;version&amp;gt;&lt;/span>${restdocs-spec.version}&lt;span class="nt">&amp;lt;/version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;executions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">		&lt;span class="nt">&amp;lt;execution&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">			&lt;span class="nt">&amp;lt;goals&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">				&lt;span class="nt">&amp;lt;goal&amp;gt;&lt;/span>generate&lt;span class="nt">&amp;lt;/goal&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">			&lt;span class="nt">&amp;lt;/goals&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">			&lt;span class="nt">&amp;lt;configuration&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">				&lt;span class="nt">&amp;lt;specification&amp;gt;&lt;/span>OPENAPI_V3&lt;span class="nt">&amp;lt;/specification&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">				&lt;span class="nt">&amp;lt;format&amp;gt;&lt;/span>JSON&lt;span class="nt">&amp;lt;/format&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">				&lt;span class="nt">&amp;lt;outputDirectory&amp;gt;&lt;/span>${project.build.directory}/classes/static/docs&lt;span class="nt">&amp;lt;/outputDirectory&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">			&lt;span class="nt">&amp;lt;/configuration&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">		&lt;span class="nt">&amp;lt;/execution&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">	&lt;span class="nt">&amp;lt;/executions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/plugin&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>﻿위 plugin 설정을 보면 format 을 JSON으로 한 것을 볼 수 있는데 YAML로도 만들 수 있다. 자세한 사용방법은 위에서 명시한 링크를 참고해보는 게 좋을 것 같다.&lt;/p></description></item><item><title>OpenAPI 와 Swagger-ui 적용하기</title><link>https://taetaetae.github.io/posts/openapi-and-swagger-ui-in-spring-boot/</link><pubDate>Sun, 20 Dec 2020 11:42:40 +0900</pubDate><guid>https://taetaetae.github.io/posts/openapi-and-swagger-ui-in-spring-boot/</guid><description>&lt;p>　﻿API를 개발하고 사용방법에 대한 명세를 작성하는 방법은 여러 가지가 있다. 가장 심플하게 개발 코드와는 별도로 직접 수기로 작성하여 파일 혹은 문서 링크를 전달하는 방법이 있다. 하지만 개발 코드와 별도로 직접 작성을 한다는 점에서 오타/실수가 발생할 수 있고 최신화가 안되는 여러 가지 문제가 발생한다. 그에 등장한 API 문서화 자동화 툴의 양대 산맥인 SpringRestDocs 와 Swagger.&lt;/p>
&lt;p>　﻿과거 &lt;a href="https://taetaetae.github.io/2020/03/08/spring-rest-docs-in-spring-boot/" rel="">SpringRestDocs 에 대한 포스팅&lt;/a>을 했기에 이번엔 Swagger에 대한 사용방법에 대해 정리해보고자 한다. 이 둘의 장단점은 너무 뚜렷하기에 API문서를 제공하는 상황에 따라 적절하게 선택하여 사용할 수 있었으면 좋겠다.&lt;/p>
&lt;h2 id="springboot에-swagger-적용">﻿SpringBoot에 Swagger 적용&lt;/h2>
&lt;p>　기본 SpringBoot 가 셋팅되어 있다는 가정하에 Swagger 관련 dependency를 추가해주자. 아참, 이제부터의 프로젝트 셋팅은 Gradle로 하려한다. (물론 Maven으로 해도 무방하지만&amp;hellip;)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-gradle" data-lang="gradle">&lt;span class="line">&lt;span class="cl">&lt;span class="n">dependencies&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">implementation&lt;/span> &lt;span class="s2">&amp;#34;io.springfox:springfox-boot-starter:3.0.0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>　﻿이후 JavaConfig 을 아래와 같이 설정하는데 아래 내용은 아주 기본 세팅이니 자세한 내용은 &lt;a href="https://springfox.github.io/springfox/docs/current/#springfox-spring-mvc-and-spring-boot" target="_blank" rel="noopener noreffer ">공식 도큐문서&lt;/a>를 참고해 보면 좋을 것 같다. (물론 샘플 프로젝트를 만들며 필요할 것 같은 내용은 아래에서 설명하겠다.)﻿&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@EnableSwagger2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nd">@Configuration&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">class&lt;/span> &lt;span class="nc">SwaggerConfig&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="nd">@Bean&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Docket&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">api&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">		&lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">new&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Docket&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">DocumentationType&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">SWAGGER_2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">			&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">select&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">			&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">apis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RequestHandlerSelectors&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">any&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">			&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">paths&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PathSelectors&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">any&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">			&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>　﻿테스트할 컨트롤러를 아래처럼 심플하게 작성하고(사칙연산&amp;hellip;) 실행을 시킨 후 &lt;code>/swagger-ui/&lt;/code>에 접속을 해보면 swagger 관련 javaConfig 하나만 추가했는데 문서가 만들어진 것을 확인할 수 있다. (http method는 편의상 다양하게 작성했으니 왜 DELETE 인가라는 의문은 접어두자.)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@RestController&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">class&lt;/span> &lt;span class="nc">SampleController&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="nd">@GetMapping&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/addition&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">addition&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">		&lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="nd">@PostMapping&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/subtraction&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">subtraction&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">		&lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="nd">@PutMapping&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/multiplication&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">multiplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">		&lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="nd">@DeleteMapping&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/division&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">division&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">		&lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num2&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">	&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/default-config.png" title="/images/openapi-and-swagger-ui-in-spring-boot/default-config.png" data-thumbnail="/images/openapi-and-swagger-ui-in-spring-boot/default-config.png" data-sub-html="&lt;h2>기본 셋팅만 했는데 이런 화면이 나타났다.&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/default-config.png"
 data-srcset="https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/default-config.png, https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/default-config.png 1.5x, https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/default-config.png 2x"
 data-sizes="auto"
 alt="/images/openapi-and-swagger-ui-in-spring-boot/default-config.png" width="80%" />
 &lt;/a>&lt;figcaption class="image-caption">기본 셋팅만 했는데 이런 화면이 나타났다.&lt;/figcaption>
 &lt;/figure>
&lt;p>　﻿위에서 했던 설정들 중 몇 가지만 좀 더 자세히 살펴보자.&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>설정&lt;/th>
 &lt;th>설명&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Docket&lt;/td>
 &lt;td>﻿Springfox 프레임 워크의 기본 인터페이스가 될 빌더로 구성을 위한 여러 가지 기본값과 편리한 방법을 제공하고 있다. 이후 &lt;code>select()&lt;/code>로 ApiSelectorBuilder를 반환받아 사용할 수 있도록 해준다.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>apis&lt;/td>
 &lt;td>﻿어떤 위치에 있는 API들을 가져올 것인가에 대한 정의. &lt;code>RequestHandlerSelectors.any()&lt;/code>이라고 했으니 SpringBoot에서 기본으로 제공하는 &lt;code>basic-error-controller&lt;/code> 도 API 문서로 만들어진 것을 확인할 수 있다. 특정 패키지만 적용하기 위해서는 &lt;code>RequestHandlerSelectors.basePackage(&amp;quot;com.taetaetae.swagger.api&amp;quot;)&lt;/code> 와 같은 형식으로 지정하면 해당 패키지 하위에 있는 Controller를 기준으로 문서를 만들어 준다﻿.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>paths&lt;/td>
 &lt;td>﻿이름에서도 눈치를 챌 수 있듯이 특정 path만 필터링해서 문서를 만들어 준다.&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>useDefaultResponseMessages&lt;/td>
 &lt;td>﻿기본 http 응답 코드를 사용해야 하는지를 나타내는 플래그&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>﻿이외에도 security 나 공통으로 사용되는 파라미터 등 다양한 옵션을 설정할 수 있으니 가능하면 상황에 맞게 설정을 변경해 보는 것도 좋을 것 같다. 다른 설정들을 추가시켜서 좀 더 친절하게 만들어 보면 아래처럼 만들 수 있고 해당 코드는 &lt;a href="https://github.com/taetaetae/Swagger-In-SpringBoot" target="_blank" rel="noopener noreffer ">Github&lt;/a>에서 확인 가능하다.&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/change-config.png" title="/images/openapi-and-swagger-ui-in-spring-boot/change-config.png" data-thumbnail="/images/openapi-and-swagger-ui-in-spring-boot/change-config.png" data-sub-html="&lt;h2>API 문서화는 최대한 친절하게!!&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/change-config.png"
 data-srcset="https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/change-config.png, https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/change-config.png 1.5x, https://taetaetae.github.io/images/openapi-and-swagger-ui-in-spring-boot/change-config.png 2x"
 data-sizes="auto"
 alt="/images/openapi-and-swagger-ui-in-spring-boot/change-config.png" width="80%" />
 &lt;/a>&lt;figcaption class="image-caption">API 문서화는 최대한 친절하게!!&lt;/figcaption>
 &lt;/figure>
&lt;h2 id="openapi">OpenAPI&lt;/h2>
&lt;p>　﻿Swagger 공식 홈페이지를 이리저리 둘러보면 OpenAPI라는 내용이 많이 나온다. 그렇다면 OpenAPI는 무엇일까? 문서에 나와있는 내용을 직역해보면 Swagger 사양으로 알려져 있으며 RESTful 웹 서비스를 설명, 생성, 소비 및 시각화하기 위한 기계 판독 가능 인터페이스 파일에 대한 사양이라고 한다. 즉, API 자체를 설명하는 인터페이스 스펙이라고 이해를 해볼 수 있다. 위에서 만들어졌던 Swagger를 보면 http://localhost:8080/v2/api-docs?group=Test API 라고 나와있는데 이를 클릭해보면 아래와 같이 json 형태로 보인다. 다시 보면 우리가 이제까지 Swagger으로 만든 API 문서를 설명하는 인터페이스 스펙으로 이해할 수 있다. (꽤 길어서 덧셈 API를 제외하고 지웠다.) 그렇다면 이 JSON 파일을 어떻게 활용할 수 있을까?﻿&lt;/p></description></item></channel></rss>