rest docs build시 자동으로 .adoc 파일을 .html로 build하고 static파일에 옮기려면 build.gradle에 여러 설정을 해야한다. 그래서 build.gradle에 쓰이는 코드가 비대해지고 어떤 설정을 했는지 한눈에 파악하기가 쉽지 않다.
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.9'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id "org.asciidoctor.jvm.convert" version "3.3.2" // asciidoc
}
group = 'com.almondia'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
asciidoctorExtensions // asciidoc
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
// aws S3
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.429'
testImplementation 'io.findify:s3mock_2.13:0.2.6'
// querydsl
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
// json object
implementation 'org.json:json:20211205'
// db
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.mysql:mysql-connector-j'
// lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok:'
testAnnotationProcessor 'org.projectlombok:lombok'
// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.3'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.3'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.3'
// webflux
implementation 'org.springframework.boot:spring-boot-starter-webflux'
// ulid-creator
implementation group: 'com.github.f4b6a3', name: 'ulid-creator', version: '5.1.0'
// mock web server
testImplementation("com.squareup.okhttp3:mockwebserver:4.10.0")
// asciidoc
asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor:2.0.6.RELEASE'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc:2.0.6.RELEASE'
// reactor test
testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
clean {
delete file('src/main/generated')
}
// 전역 변수
ext {
snippetsDir = file('build/generated-snippets') // rest-docs 스니펫 위치 설정
}
asciidoctor {
inputs.dir snippetsDir
configurations 'asciidoctorExtensions'
dependsOn test
sources {
include("**/index.adoc", "**/common/*.adoc")
}
baseDirFollowsSourceDir()
}
asciidoctor.doFirst {
delete file('src/main/resources/static/docs')
}
task copyDocument(type: Copy) {
dependsOn asciidoctor
from file("build/docs/asciidoc")
into file("src/main/resources/static/docs")
}
build {
dependsOn copyDocument
}
tasks.named('test') {
useJUnitPlatform()
outputs.dir snippetsDir // asciidoc
}
이것은 기존 프로젝트에 rest docs를 적용한 build.gradle의 모습이다. 일일히 뜯어보면 이해할 수 있기는 하지만 전체 설정과 rest docs의 설정이 뒤엉켜서 관리하기가 쉽지 않다. 그래서 주석으로 asciidoc의 설정이라고 구분지어 줬지만 역시 가독성은 떨어졌다.
점점 많아지면 build.gradle은 설정을 감당하기 힘들것이고 해당 스크립트가 여러 task가 뒤죽박중 엉키면서 스파게티 코드를 생성할 우려가 있다. 그래서 다음과 같이 개선하면 좋을 것 같다는 생각이 들었다.
다행히도 gradle에서는 apply를 활용해 분리된 gradle 등록이 가능하다!!
apply from을 통해 build.gradle을 3개의 gradle로 분리했다. 그 중 중요한 asciidoc.gradle과 build.gradle을 확인해보자
// asciidoc.gradle
configurations {
asciidoctorExtensions
}
// 변수 선언
ext {
snippetsDir = file('build/generated-snippets') // rest-docs 스니펫 위치 설정
}
dependencies {
asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor:2.0.6.RELEASE'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc:2.0.6.RELEASE'
}
asciidoctor {
inputs.dir snippetsDir
configurations 'asciidoctorExtensions'
dependsOn test
sources {
include("**/index.adoc", "**/common/*.adoc")
}
baseDirFollowsSourceDir()
}
asciidoctor.doFirst {
delete file('src/main/resources/static/docs')
}
task copyDocument(type: Copy) {
dependsOn asciidoctor
from file("build/docs/asciidoc")
into file("src/main/resources/static/docs")
}
build {
dependsOn copyDocument
}
tasks.named('test') {
outputs.dir snippetsDir
}
위의 코드는 asciidoc.gradle로 분리한 코드이다. 자동으로 adoc로부터 html을 생성하고 resources/static/docs로 파일을 복사까지의 과정을 자동화한 코드로 asciidoc에 관련된 내용만 담겨 있다. 이를 메인 gradle인 build.gradle에선 apply만 해주면 된다.
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.9'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id "org.asciidoctor.jvm.convert" version "3.3.2"
}
group = 'com.almondia'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
apply from: 'asciidoc.gradle' // asciidoc
apply from: 'default-dependencies.gradle'
가독성이 훨씬 좋아지고 dependency와 task를 해당 라이브러리에 포커싱을 맞추어서 다룰 수 있게 되었다. gradle의 분리를 통해 커스텀 task나 여러 설정시에 부담되는 긴 스크립트를 짧게 줄일 수 있어서 큰 도움이 됬다.