
Sent 프로젝트를 개발하면서 클라이언트가 직접 API 명세서를 확인할 수 있도록 문서 제공 환경을 구축할 필요가 생겼다. 초기에는 기존 개발 서버에 명세서를 함께 제공하려 했지만, 최종적으로는 GitHub Pages를 활용한 별도 배포 방식으로 결정하게 되었다.
이 글에서는 왜 GitHub Pages를 선택했는지, CI/CD 구성은 어떻게 했는지를 정리한다.
./gradlew asciidoctor 실행 시 생성되는 HTML 파일을 resources/static/docs 경로에 복사/docs/index.html로 접근 가능
build/docs/asciidoc 결과물을 Nginx 설정을 통해 /docs 경로로 서빙개발 서버와는 분리된 환경에서 문서를 배포할 수 있고, 정적 호스팅에 최적화된 GitHub Pages가 가장 적절해 보였다.
기껏 구축해놓은 개발서버를 사용하지 않고 개발서버와 별개로 Github Page를 사용하기로 했다.
“서비스 코드가 배포된 후 최신 코드로 문서를 빌드해야 한다”는 관점에서는 deploy.yml → docs.yml 순서가 필요하다.
왜 이런 순서가 필요할까?
만약 docs.yml이 먼저 실행되면?
만약 deploy.yml이 먼저 실행되면?
위와 같이 생각을 하고 지나갔으나, 파이프라인을 짜면서 커밋을 기점으로 코드를 가지고 왔기 때문에 이미 최신화 된 코드를 가지고 ./gradlew asciidoctor 명령어를 사용해서 최신 문서화를 뽑아낸다는 것을 다시금 깨달았다.
하지만 이래도 docs.yml을 통해 개발 서버에 띄우는 방법을 사용하지 않는 이유에 대해 설명한다.
현재 개발 서버는 Github Actions를 통하여 Docker 기반으로 배포를 진행하고 있다.
개발 서버에서 docs.yml을 통해서 명세서를 제공하는 방법은 위에서 말한 두 가지를 다시금 충족한다.
./gradlew asciidoctor 명령어만 deploy.yml에서 빼서 돌리더라도 Nginx를 사용하지 않을 거라면 이 명령어로 만들어진 build/docs에 있는 파일을 static/resources로 다시 옮긴 다음에 이미지를 말아서 다시 스프링부트를 띄우면 :8080/docs/index.html에서 볼 수 있을 것이다.name: Spring Rest Docs
on:
push:
branches:
- develop
workflow_dispatch:
concurrency:
group: github-pages
cancel-in-progress: true
jobs:
deploy:
permissions:
pages: write
id-token: write
environment:
name: github-pages
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Pages
uses: actions/configure-pages@v5
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "21"
cache: gradle
- name: Build Asciidoc
run: ./gradlew asciidoctor
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: "./build/docs/asciidoc"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
concurrency:
group: github-pages
cancel-in-progress: true
동시 실행 제어
같은 그룹의 워크플로우가 여러 번 실행될 때 이전 실행을 취소하고 최신만 유지
jobs:
deploy:
permissions:
pages: write
id-token: write
environment:
name: github-pages
runs-on: ubuntu-latest
배포 작업 정의
permissions: GitHub Pages 배포에 필요한 권한 부여
environment: github-pages 환경 사용
runs-on: Ubuntu 최신 러너에서 실행
steps:
- name: Checkout
uses: actions/checkout@v4
코드 체크아웃: 현재 커밋의 코드를 빌드 서버로 가져옴
- name: Set up Pages
uses: actions/configure-pages@v5
GitHub Pages 환경 설정: Pages 배포에 필요한 환경 준비
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "21"
cache: gradle
JDK 21 설치: Gradle 빌드에 필요한 Java 21 환경 준비
cache: gradle: Gradle 의존성 캐시 활용
- name: Build Asciidoc
run: ./gradlew asciidoctor
명세서 빌드: asciidoctor로 API 문서 생성
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: "./build/docs/asciidoc"
빌드된 HTML을 Pages 아티팩트로 업로드 이후 step에서 GitHub Pages로 배포할 수 있도록 준비
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
GitHub Pages로 실제 배포
업로드된 HTML 파일을 Pages 사이트로 공개

결론적으로 이러한 yml 파일을 작성하여, 배포할 때 분리해서 실행한다.
paths:
- 'api/src/docs/asciidoc/**'
- '.github/workflows/docs.yml'
나는 추가로 이러한 설정을 해주었다.
paths 옵션을 추가하면 develop 브랜치에서 명세서 소스 (api/src/docs/asciidoc/**)나 docs.yml이 변경될 때만 워크플로우가 실행된다.
명세서가 바뀌지 않으면 워크플로우가 실행되지 않아 효율적이다.
결론적으로 개발서버에 API 명세서를 빌드하지 않고, Github Pages를 통해서 처음으로 API 명세서를 배포하였다.
스웨거를 사용할까도 하였지만 스웨거를 여러 번 사용해본 경험자로서 이번 프로젝트에서는 코드 품질에 대해 신경을 좀 더 쓰면서 개발을 진행하고 있기에 컨트롤러단을 더럽히고 싶지 않아서 Spring Rest Docs를 사용하고 있다.
테스트 코드를 작성하는 습관이 들어있지않고 아직도 너무나 어렵지만 AI의 도움덕에 테스트코드 작성 난이도도 굉장히 내려갔고, AI의 도움을 받더라도 작성을 아예 하지 않는 것보다는 Spring Rest Docs는 테스트코드 강제성을 부여한다는 점에서 도움이 많이 되고 있다.
개발단에서의 인프라 구축이 모두 끝나서 홀가분하다.