์ด์ ๊ธ์์ Swagger UI์ ๊ฐ๋
์ฑ ๋ฌธ์ ๋ฅผ ๊ฒช๊ณ Stoplight Elements๋ก ์ ํํ์๋ค. ๋น์ ๋ง๋ฌด๋ฆฌ์์ "์ถํ Spring REST Docs + RestDocs-Api-Spec ์กฐํฉ์ผ๋ก ๊ตฌ์ฑํ ์์ " ์ด๋ผ๊ณ ๋จ๊ฒผ๋๋ฐ, ์ด๋ฒ ํ๋ก์ ํธ์์ ์ค์ ๋ก ํด๋ดค๋ค.
๊ธฐ์กด ๋ฐฉ์์ ๋ฌธ์
์ด๋
ธํ
์ด์
๊ธฐ๋ฐ ๋ฌธ์ํ๋ ์ฝ๋์ ๋ฌธ์๊ฐ ๋ถ๋ฆฌ๋์ง ์๋ ๊ฒ์ฒ๋ผ ๋๊ปด์ง์ง๋ง, ์ฌ์ค์ ๋ฐ๋ก ๋
ผ๋ค.
ํ๋ก๋์
์ฝ๋์ @Operation, @Schema ๊ฐ์ ๋ฌธ์์ฉ ์ด๋
ธํ
์ด์
์ด ๊ฐ๋ ๋ถ๊ณ , ์ค์ ๋ก API๊ฐ ๊ทธ ์ค๋ช
๋๋ก ๋์ํ๋์ง๋ ๊ฒ์ฆ๋์ง ์๋๋ค. ํ๋ผ๋ฏธํฐ ํ์
์ด ๋ฐ๋์ด๋, ์๋ต ๊ตฌ์กฐ๊ฐ ๋ฌ๋ผ์ ธ๋ ๋ฌธ์๋ ๋ชจ๋ฅธ๋ค.
๊ทธ๋์ ๋งค๋ฒ API์ ์์ฒญ/์๋ต ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ด๋
ธํ
์ด์
์ ๋ด์ฉ๋ ํจ๊ป ๋ณ๊ฒฝํด์ค์ผ ํ๋ ์ปจํ
์คํธ๋ฅผ ๊ธฐ์ตํด์ผ ํ๋ค. ํ์ง๋ง, ์ด๋ฌํ ์ปจํ
์คํธ์ ์ฆ๊ฐ๋ ๊ฐ๋ฐ์์๊ฒ ์ข์ง ์์ ์ ํธ์ด๊ธฐ์ ํ
์คํธ๊ฐ ํต๊ณผํด์ผ๋ง ๋ฌธ์๊ฐ ์์ฑ๋๋ ๊ตฌ์กฐ๊ฐ ํ์ํ๋ค.
๊ทธ๋์ ํ๋ก์ ํธ ์ด๊ธฐ ํ์์๊ฒ ์ด๋ฌํ ์๊ฒฌ์ ์ ๋ฌํ์๊ณ , ํ์๋ ๊ณต๊ฐํ์ฌ Spring REST docs + Restdocs-api-spec ์กฐํฉ์ผ๋ก ๋ฌธ์ํ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๋ค. ํ์ง๋ง, ์์ง ์๋๋ก์ด๋ ๊ฐ๋ฐ์๋ก๋ถํฐ ์ค์ง์ ์ธ ๊ฐ๋
์ฑ ๋ฌธ์ ์ ๋ํ ์๊ธฐ๊ฐ ์์์ผ๋ฏ๋ก swagger-ui๋ฅผ ํตํด ์๋์ผ๋ก ์์ฑ๋๋ ๋ฌธ์ ํ์ด์ง๋ฅผ ์ฌ์ฉํ๋๋ก ํฉ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฐ์ํ ๋ฌธ์ ๋ค
ํ ์คํธ์ ์ ์ฉํ ๋ด์ฉ์ด ๋ฐ์๋์ง ์์์!
๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๊ณ ๋ฌธ์ ํ
์คํธ๋ ์ ์์ฑํ๊ณ ๋ ๋ค, ๋ง๋ค์ด์ง ๋ฌธ์๋ฅผ ๋ณด๋ฉด์ ์ด์ํ ๋ถ๋ถ๋ค์ด ๋ชฉ๊ฒฉ๋์๋ค. ๋ถ๋ช
๋ฌธ์ ํ
์คํธ์๋ .summary(), .description()์ ํ๊ธ๋ก ์ ์์ฑํ๋๋ฐ ๋ฌธ์์์๋ ์ด์ํ๊ฒ ์์ด๋ก ํ์๋๊ฑฐ๋ ๋ฌด์๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ contentType์ด๋ ๊ธฐํ ์ฌ๋ฌ ํ
์คํธ ํญ๋ชฉ๋ค์ด ์ ๋๋ก ๋จนํ์ง ์๋ ์ด์๊ฐ ์์๋ค.

๊ทธ๋์ ์ ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋์ง ๋ฉด๋ฐํ ์์ธ์ ์กฐ์ฌํด๋ดค๋ค.
๋ฌธ์ ์ ์์ธ์ springdoc์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐํ์์ ํด๋์ค๋ฅผ ์ค์บํด์ ์์ฒด ์คํ์ /v3/api-docs๋ก ์๋ ์์ฑํ๋ค๋ ๊ฒ์ด์๋ค. ์ด๋ก ์ธํด ๋ณ๋ ์ค์ ์ ํ์ง ์์ ํ์ฌ ์ํฉ์์ ๊ธฐ๋ณธ URL์ ๋ฐ๋ผ๋ณด๋ ํ
์คํธ์์ ์์ฑ๋ ๋ด์ฉ์ด ์๋ ๋ฐํ์์ ์์ฑ๋ openapi3.yaml์ ์ฝ๊ณ ์๋ ๊ฒ์ด๋ค.
๊ทธ๋์ application.yml์ ์๋ ๋ด์ฉ์ ์ถ๊ฐํ์ฌ ํด๊ฒฐํ๋ค. [๊ด๋ จ PR]
springdoc:
swagger-ui:
url: /api-docs/openapi3.yaml
Swagger-ui์ ๊ฐ๋ ์ฑ ๋ฌธ์
๋ฌธ์ ํ ์คํธ๋ ์ ์์ฑํ๊ณ , ์ค๋ช ๋ ์ถฉ์คํ ํ๋ค๊ณ ์๊ฐํ๊ณ ์์์ง๋ง ์ง์์ ์ผ๋ก ์๋๋ก์ด๋ ๊ฐ๋ฐ์ ๋ถ๋ค์๊ฒ ์ค๋ ๋ฉ์์ง๊ฐ ์์๋ค. ๊ทธ๊ฒ ๋ฐ๋ก ์๋์ ๊ฐ์ ๋ฉ์์ง์ด๋ค.



์ด๊ฑด ๋ค๋ฅธ ํ๋ก์ ํธ์ธ '๋ฐ์ธ๊ถ'์์๋ ๊ฒช์๋ ๋ฌธ์ ์ธ๋ฐ, ์ค๋ช
์ ์ ์์ฑํด๋์๋ swagger-ui ํน์ฑ์ ์ด๋ฅผ ํ์ธํ๊ธฐ๊ฐ ์ฝ์ง ์๋ค. ์๋ฅผ ๋ค์ด id์ ๋ํ ์ค๋ช
์ด ๊ถ๊ธํ๋ค๋ฉด ์๋ ์ฌ์ง์ฒ๋ผ Schema๋ฅผ ์ ํํ๊ณ ๊ฐ ํญ๋ชฉ๋ค์ ํ ๊ธ์ ๋๋ฌ์ผ ํ์ธ ๊ฐ๋ฅํ๋ค.

ํ๋ก์ ํธ ์ด๊ธฐ๋ถํฐ ์ง๊ธ๊น์ง ์ง์์ ์ผ๋ก ์ด๋ฌํ ์ด์ผ๊ธฐ๊ฐ ๋์ค๋ ๊ฒ์ swagger-ui ๋ณด๋ ๋ฒ์ ๊ฐ๋ฅด์ณ์ฃผ๋ ๊ฒ๋ณด๋ค ์ถํ ์๋ก์ด ํ์ ํน์ ๋ณด๋ ๋ฐฉ๋ฒ์ ๊น๋จน์์ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด์ ์์ ์๋ก์ด ํด์ธ 'Stoplight'๋ก ๋ณ๊ฒฝํ๊ธฐ๋ก ํ๋ค.
Stoplight๋ฅผ ์ ํํ ์ด์ ๋ ์ด์ ๊ธ์์ ์ ํํ ์ด์ ์ ๋์ผํ๋ฉฐ, ํ์ฌ ์ต์ํ ํด์ด์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ตฌ์ฑํ ํ์ดํ๋ผ์ธ
docsTest (RestDocs ํ๊ทธ ํ
์คํธ)
→ openapi3 (์ค๋ํซ → OpenAPI YAML ์์ฑ)
→ copyOpenApiToStatic (YAML์ ์๋น ๊ฒฝ๋ก๋ก ๋ณต์ฌ)
→ bootJar / bootRun
๊ฐ ๋จ๊ณ๋ฅผ Gradle ํ์คํฌ๋ก ์ฐ๊ฒฐํ๋ค. docsTest๋ @Tag("restdocs")๊ฐ ๋ถ์ ํ
์คํธ๋ง ๊ณจ๋ผ ์คํํ๊ณ , ์ค๋ํซ์ build/generated-snippets์ ์๋๋ค. openapi3 ํ์คํฌ(epages ํ๋ฌ๊ทธ์ธ)๊ฐ ์ค๋ํซ์ ์ฝ์ด YAML๋ก ๋ง๋ ๋ค.
Stoplight Elements๋ ๋ณ๋ ์๋ฒ๊ฐ ํ์ ์๋ค. HTML ํ์ผ ํ๋๊ฐ ์ ๋ถ๋ค.
<elements-api
apiDescriptionUrl="/api-docs/openapi3.yaml"
router="hash"
layout="sidebar"
/>
springdoc ์์กด์ฑ๋ ์ ๊ฑฐํ๋ค. Stoplight HTML์ด ์ง์ YAML์ ์ฝ๊ธฐ ๋๋ฌธ์ springdoc์ด ํ ์ผ์ด ์์ด์ก๋ค.
์ด๋ฌํ ํ์ดํ ๋ผ์ธ์ ์ ์ฉํ๋ฉด์๋ ์ฌ๋ฌ๊ฐ์ง ๋ณ๊ฒฝ ์ฌํญ์ ์ถ๊ฐ๋ก ์ ์ฉํ๋ค.
JWT ๋ณด์ ์คํค๋ง ์๋ ํจ์น ์ ๊ฑฐ
swagger-ui์์๋ ๋ณด์ ์คํค๋ง๋ฅผ ๋ถ์ฌ์ฃผ์ง ์์ผ๋ฉด, ๊ฐ API ์์ฝ ์์ ์๋ฌผ์ ์์ด์ฝ์ด ๋ถ์ง ์๋๋ค.

๊ทธ๋์ ํค๋์๋ง ํ ํฐ์ด ํ์ํจ์ ๋ถ์ฌ๋์ผ๋ฉด ์ด๋ฅผ ํ ๋์ ํ์
ํ๊ธฐ๊ฐ ์ฝ์ง ์์๋ค. ํ์ง๋ง, Stoplight๋ ๋ณด์ ์คํค๋ง๋ฅผ ์ ์ฉํ์ง ์๊ณ , ํค๋์๋ง ๋
ธ์ถํด๋ ํฌ๊ฒ ๋ถํธํ ์ ์ด ์๋ค.

์ฌ์ง์ฒ๋ผ ํค๋๊ฐ ๋ช
์๋๊ธฐ ๋๋ฌธ์ด๋ค. ์คํค๋ง๋ฅผ ์ ์ฉํ๋ค๊ณ ํด๋ ํค๋ ๋ฐฉ์๊ณผ ํฐ ์ฐจ์ด์ ์ด ์๋ค.
๊ทธ๋์ build.gradle์์ ์๋น์๋ฅผ ์ฐจ์งํ๋ jwt ๋ณด์ ์คํค๋ง ์๋ ํจ์น๋ฅผ ์ ๊ฑฐํ๋ค.
์ด์ ์๋ฒ ๋ ธ์ถ ๋ฌธ์
๊ตฌ์ฑ์ ๋ง์น๊ณ ๋ฌธ๋ "์ด์ ์๋ฒ์์๋ ๋ฌธ์๊ฐ ๋ณด์ด๋ ๊ฑฐ ์๋์ผ?" ๋ผ๋ ์ง๋ฌธ์ด ์๊ฐ๋ฌ๋ค.
์ฒ์์ static/docs/index.html์ Spring์ ์ ์ ๋ฆฌ์์ค ๊ฒฝ๋ก์ ๋๋๋ฐ, ์ด ๊ฒฝ๋ก๋ ๋ชจ๋ ํ๊ฒฝ์ JAR์ ํฌํจ๋๋ค. ์ด์ ์ Springdoc์ ์ธ ๋๋ application-prod.yml์์ swagger-ui.enabled: false๋ก ๋ง์์ง๋ง, ์ ์ ํ์ผ์ ๊ทธ ์ค์ ์ผ๋ก ์ ์ด๊ฐ ์ ๋๋ค.
ํ์ง๋ง ์ ๊น ์๊ฐํด๋ณด๋ ๊ตณ์ด ๋ณต์กํ๊ฒ ๋ง์ ํ์๊ฐ ์์๋ค.
์ด์ ๋น๋ ์คํฌ๋ฆฝํธ๋ ./gradlew clean build -x test -x docsTest๋ก docsTest๋ฅผ ์คํตํ๋ค. docsTest๊ฐ ์คํต๋๋ฉด ์ค๋ํซ์ด ์์ฑ๋์ง ์๊ณ , ์ค๋ํซ์ด ์์ผ๋ฉด YAML๋ ์์ฑ๋์ง ์๋๋ค. YAML ์์ด bootJar๋ฅผ ์คํํ๋ฉด JAR์ YAML์ด ํฌํจ๋์ง ์๋๋ค. HTML ํ์ด์ง๊ฐ ์ด๋ ค๋ YAML์ ๋ถ๋ฌ์ค์ง ๋ชปํด ๋น ์๋ฌ ํ๋ฉด๋ง ๋ณด์ธ๋ค.
์๋์ ์ผ๋ก ๋ง์ง ์์๋ ๋น๋ ๊ตฌ์กฐ๊ฐ ์์ฐ์ค๋ฝ๊ฒ ์ด์ ํ๊ฒฝ์์์ ๋
ธ์ถ์ ๋ฐฉ์งํด์ฃผ๋ ์
์ด๋ค.
์ด์ ๋ฐํด ๊ฐ๋ฐ ์๋ฒ ๋น๋๋ ./gradlew clean build -x test๋ก docsTest๊ฐ ์คํ๋๊ณ , YAML์ด ์์ฑ๋์ด JAR์ ํฌํจ๋์ด ๋ฌธ์๊ฐ ์ ์ ์๋น๋๋ค.
๋ง์น๋ฉฐ
REST Docs ๊ธฐ๋ฐ์ผ๋ก ๋ฐ๊พธ๊ณ ๋์ ๊ฐ์ฅ ์ข์ ์ ์ ๋ฌธ์ ์ ๋ขฐ๋๋ค. ํ
์คํธ๊ฐ ๊นจ์ง๋ฉด YAML๋ ์์ฑ์ด ์๋๋, ๋ฌธ์์ ์ค์ API๊ฐ ๋ค๋ฅผ ์ ์๋ค. ์ด๋
ธํ
์ด์
์ ์์ ๋ ๋์ ํ
์คํธ ์ฝ๋๊ฐ ๋ฌธ์์ ์ญํ ์ ๊ฒธํ๊ฒ ๋์ด ํ๋ก๋์
์ฝ๋๊ฐ ํจ์ฌ ๊น๋ํด์ก๋ค.
Stoplight Elements๋ ์ฌ์ ํ ๋ง์กฑ์ค๋ฝ๋ค. CDN ํ ์ค๋ก ์์ฑ๋๋ UI์น๊ณ ๋ ํ๋ฆฌํฐ๊ฐ ์ข๋ค. [๊ด๋ จ PR]

'๊ฐ๋ฐ > DND' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| ํ์ํํด๋ฅผ ์ด๋ป๊ฒ ์ค๊ณํ ๊น (0) | 2026.02.10 |
|---|