문제 상황
현재 진행하고 있는 프로젝트에서 Restdocs를 사용해 API문서화를 진행하도록 결정했습니다.
./gradlew clean build
명령어를 통해 API 문서가 지정한 경로에 제대로 생성되는 것을 확인했었습니다.
build된 jar 파일을 EC2에 전달 후 nohup 명령어를 통해 WAS를 띄운 후 http://{ec2주소}/docs/index.html 을 했을 때
404 Not Found 응답이 났습니다.
무엇이 문제일까?
문제의 build.gralde
plugins {
id 'org.asciidoctor.jvm.convert' version '3.3.2'
}
configurations {
asciidoctorExt
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'org.springframework.retry', name: 'spring-retry', version: '2.0.4'
// HATEOAS
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
// AWS
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
// rest docs
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
}
ext { // 전역 변수
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir snippetsDir
useJUnitPlatform()
}
asciidoctor {
configurations 'asciidoctorExt'
baseDirFollowsSourceFile()
inputs.dir snippetsDir
dependsOn test
outputDir file('build/docs/asciidoc')
}
task copyAsciidoc(type: Copy) {
from "build/docs/asciidoc/"
into "src/main/resources/static/docs"
include "index.html"
doFirst {
delete "src/main/resources/static/docs/index.html"
}
dependsOn asciidoctor
}
build {
dependsOn copyAsciidoc
}
version '1.0.1-SNAPSHOT-'+new Date().format("yyyyMMddHHmmss")
jar.enabled=false
해당 gradle 설정을 통해 ./gradlew clean build를 한 jar를 분해해봤습니다.
classpath의 경로에는 문서가 생겼지만 build된 jar내부에는 문서가 포함되지 않은 채 생성 된 것을 확인할 수 있습니다.
gradle build 과정
intelliJ를 통해 build시에 어떠한 순서로 build가 되는지 확인을 해본 결과 다음과 같았습니다.
현재 멀티모듈을 구성한 탓이 여러가지 모듈들도 같이 작업이 실행되는데 api 모듈만 따로 떼어보면 실행 순서는 다음과 같습니다.
compileJava -> processResources -> classes -> resolveMainClassName -> bootJar -> jar SKIPPED ->
assemble -> compileTestJava -> processTestResources -> testClasses -> test -> jacocoTestReport ->
check -> asciidoctor -> copyAsciidoc -> build
여러가지 과정을 거치지만 문서화를 하는데 있어 중요한 process들만 그 역할을 확인 해 보도록 하겠습니다.
- compileJava : src/main/java 에 있는 Java 소스 파일들을 컴파일
- bootJar : compileJava 작업에 의해 생성된 클래스와 리소스 파일들을 포함한 Spring Boot Jar 파일 생성
- test : 테스트 세트 실행
- asciidoctor : AsciiDoc 파일을 HTML등 다른 포맷으로 변환
- copyAsciidoc : asciidoctor 작업에 의해 생성된 문서를 지정된 위치로 복사
혹시 실행 순서에서 이상한 점을 눈치 채셨나요?
기존 build.gradle의 경우에는 문서를 복사하기 이전 시점에 jar 파일이 생성됩니다.
그렇기 때문에 jar 파일 내에는 asciidoctor를 통해 변환된 html파일을 가지고 있을 수 없습니다.
따라서 index.html을 조회하려고 했을 때 조회가 불가능합니다.
해결 방법
근본적인 문제는 jar가 생성되고 난 시점에 asciidoctor 그리고 copyAsciidoc 과정이 일어났기 때문입니다.
gralde의 build 순서를 조정해주면 됩니다.
수정된 build.gradle
plugins {
id 'org.asciidoctor.jvm.convert' version '3.3.2'
}
configurations {
asciidoctorExt
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'org.springframework.retry', name: 'spring-retry', version: '2.0.4'
// HATEOAS
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
// AWS
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
// rest docs
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
}
ext { // 전역 변수
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir snippetsDir
useJUnitPlatform()
}
asciidoctor {
configurations 'asciidoctorExt'
baseDirFollowsSourceFile()
inputs.dir snippetsDir
dependsOn test
outputDir file('build/docs/asciidoc')
}
bootJar {
dependsOn asciidoctor
from("${asciidoctor.outputDir}") {
into "static/docs"
}
}
version '1.0.1-SNAPSHOT-'+new Date().format("yyyyMMddHHmmss")
jar.enabled=false
gradle에서는 dependsOn을 사용해 특정 작업 이전에 실행할 작업을 지정할 수 있습니다.
bootJar 에 dependsOn asciidoctor를 사용해 asciidoctor가 먼저 실행 되도록 코드를 변경했고, asciidoctor를 통해 생성된 html을 build 경로의 static/docs 경로에 복사하게끔 코드를 수정했습니다.
그럼으로써 다음의 순서를 지킬 수 있었습니다.
asciidoctor -> asciidoctor 복사 -> jar 파일 생성
새로 짠 gradle 코드를 통해 ./gradlew clean build를 한 jar 내부는 다음과 같습니다.
jar 파일 내부에 static/docs/index.html이 존재하는 것을 확인할 수 있습니다.
Spring Boot에서는 내장된 Tomcat 서버를 통해 자동으로 /static 경로에 있는 정적 리소스들을 제공합니다.
따라서 nohup 명령어를 통해 jar를 띄워 http://localhost:8080/docs/index.html 을 조회하면 정상적으로 조회되는 것을 확인 할 수 있습니다.
'개발일지' 카테고리의 다른 글
kafka 성능 개선기 (feat. 배치 리스너) (0) | 2024.09.02 |
---|---|
[Git] SubModule에 대해서 (0) | 2024.04.16 |
커플 재결합 관련 Code Refactoring (2) | 2023.11.22 |
[Spring] Github Actions 테스트 시 credential 값 설정하는 방법 (5) | 2023.10.26 |