티스토리 뷰
이동욱 님의 블로그에서 정말 친절한 설명과 함께 Gradle 세팅을 진행해보았다
진행 중인 개인 프로젝트는 멀티 모듈로 나눌 필요가 없는 규모다
요즘 관심사가 스프링이 가진 다양한 기능들을 접해보는 데 있기 때문에 경험 삼아 시도했다
혼자 진행하고 있는 프로젝트이기 때문에 front까지 루트에서 모듈로 관리하기로 했고
현재는 api, common, service, vue로 나눠둔 상태다, 이 구조는 딱히 좋다고 말할 수 없다
편의상 front / back을 한 곳에 몰아넣은 것뿐이고 협업을 하거나 개별적인 빌드를 위해서는
모듈을 분리하는 편이 훨씬 낫다
그럼에도 불구하고 왜 넣었는가 하면 스프링부트에서 npm plugin을 이용해 front까지 통합 빌드 후
결과물을 backend module에 resources/static/ 경로 밑에 둬서 서버에서 모든 처리를 가능하게 할 수 있기 때문이다
분리할 필요가 생긴다면 front 모듈을 그저 프로젝트 외부로 옮기기만 하면 된다
추후 Spring Batch 를 학습하면서 batch 모듈을 추가할 계획이다
실습해볼 때 폴더 구조, 파일 이름을 바꿔서 해보는 게 도움이 많이 되는 것 같다
그래야 빌드 시에 에러가 나고! 에러 스택 트레이스를 읽어보며
빌드가 된 부분은 왜 된 것이고, 안 된 부분은 무엇 때문에 안 된 건지 이해할 수 있었다
블로그 글들을 보면서 한 번에 이해하는 게 가장 좋겠지만 부딪혀봐야 더 기억에 잘 남는 것 같다
현재 build.gradle의 subproject에서는 뭉탱이로 dependencies를 관리하고 있는데
프로젝트 진척시키면서 개선해가야겠다
Spring Restdocs 설정까지 마쳤고, module-api에서 문서가 만들어지게끔 해놨다
Spring boot, Vue.js 빌드를 통합하기 위해 node plugin을 다운로드하였고 task를 설정해 front 빌드가 우선적으로 된 후 backend 빌드가 수행되도록 세팅했다 common에서는 querydsl 이용을 위한 세팅을 따로 잡아줬는데,
기본 세팅은 김영한 님의 인프런 강의를 통해 했던 설정을 그대로 가져왔는데
gradle 버전이 달라지면서 에러가 나서 검색을 통해 설정을 바꿔줬다
기존 JPA QueryDSL 설정은 나중에 또 필요할 때 써먹도록 다른 글로 옮겨 두었다
완성본은 아니기에 필요 없는 설정도 많이 들어가 있지만 프로젝트가 돌아갈 수 있도록 세팅해놨기 때문에
이 글을 참고한다면 필요에 맞게 라이브러리를 넣고 빼고 하시면 되겠다
21.12.08
현재는 restdocs 관련 task들은 module-api로 querydsl 관련 설정들은 module-core로 옮겨둔 상태이다
module-vue 빌드에는 npm이 아닌 yarn으로 바꿨고 등등.. 너무 많이 바뀌어서 글을 새로 써야겠다
그래도 아래에서 달라진 건 dependency와 package manager 뿐이므로 충분히 참고할 수 있을 것이다
루트 경로 build.gradle에는 프로젝트 전체에서 필요한 dependency와 build task만 남겨두도록 하는 것이 좋아 보인다
buildscript {
ext {
springBootVersion = '2.5.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}'
classpath 'io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE'
}
}
plugins {
id 'org.springframework.boot' version '2.5.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id "org.asciidoctor.jvm.convert" version "3.3.2"
id "com.github.node-gradle.node" version "3.1.0"
id 'java'
}
repositories {
mavenCentral()
}
subprojects {
apply plugin: 'java'
apply plugin: 'org.asciidoctor.jvm.convert'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.woomool-market'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
targetCompatibility = '11'
repositories {
mavenCentral()
}
configurations {
asciidoctorExtensions
compileOnly {
extendsFrom annotationProcessor
}
}
ext {
snippetsDir = file('build/generated-snippets')
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.session:spring-session-core'
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.mapstruct:mapstruct:1.4.1.Final'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.8'
// Java 8 date/time type `java.time.LocalDateTime` not supported by default:
// add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
// (through reference chain: com.woomoolmarket.service.member.dto.response.MemberResponse["createdDate"])
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
// Argon2PasswordEncoder 쓸라면 넣어줘야 됨
implementation 'org.bouncycastle:bcprov-jdk15on:1.69'
// Restdocs 왜 인식을 못 하니 이녀석아
asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java'
implementation 'org.mariadb.jdbc:mariadb-java-client'
// lombok -> mapstruct -> binding 순서 안 맞추면 안 돌아감... 주의
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.1.Final'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
// jjwt ?!
implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.7.2'
// security test
testImplementation 'org.springframework.security:spring-security-test'
}
test {
outputs.dir snippetsDir
useJUnitPlatform()
}
asciidoctor {
configurations 'asciidoctorExtensions'
inputs.dir snippetsDir
dependsOn test
}
task copyDocument(type: Copy) {
dependsOn asciidoctor
// 소스 코드에 html파일을 복사
from "${asciidoctor.outputDir}"
into 'src/main/resources/static/docs'
}
build {
dependsOn copyDocument
}
}
node {
version = '16.6.1'
npmVersion = "7.20.3"
workDir = file("./module-vue")
npmWorkDir = file("./module-vue")
nodeModulesDir = file("./module-vue")
}
task setUp(type: NpmTask) {
description = "Install Node.js packages"
args = ['install']
inputs.files file('package.json')
outputs.files file('node_modules')
}
task buildVue(type: NpmTask, dependsOn: setUp) {
description = "Build vue.js"
args = ['run', 'build']
}
processResources.dependsOn 'buildVue'
project(':module-api') {
dependencies {
implementation project(':module-common')
}
}
project(':module-api') {
dependencies {
implementation project(':module-service')
}
}
project(':module-service') {
dependencies {
implementation project(':module-common')
}
}
bootJar {
mainClassName = 'com.woomoolmarket.ModuleApiApplication'
dependsOn asciidoctor
copy {
from "${asciidoctor.outputDir}"
into 'src/main/resources/static/docs'
}
}
2022.01.28
세부 모듈 build.gradle 까지 첨부하기에는 너무 방대하므로 링크로 대신함
module-core / module-service / module-api
Project Root, build.gradle
buildscript {
ext {
springBootVersion = '2.5.3.RELEASE'
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}'
classpath 'io.spring.gradle:dependency-management-plugin:1.0.11.RELEASE'
}
}
plugins {
id 'org.springframework.boot' version '2.5.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id "org.asciidoctor.jvm.convert" version "3.3.2"
id "com.github.node-gradle.node" version "3.1.0"
id 'jacoco'
id 'java'
}
repositories {
mavenCentral()
}
group = 'com.woomool-market'
version = '1.0'
sourceCompatibility = '11'
targetCompatibility = '11'
subprojects {
apply plugin: 'java'
apply plugin: 'jacoco'
apply plugin: 'org.asciidoctor.jvm.convert'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
repositories {
mavenCentral()
}
// log4j2 이슈 대응하기 위한 버전 변경
// tomcat 대신 undertow 사용해보기 위해 tomcat module 제외
configurations {
compileOnly {
extendsFrom annotationProcessor
}
all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
exclude module: 'spring-boot-starter-tomcat'
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'org.apache.logging.log4j') {
details.useVersion '2.15.0'
}
}
}
}
ext {
set('springCloudVersion', "2020.0.3")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-undertow'
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-log4j2:2.6.1'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.security.oauth:spring-security-oauth2'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure'
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation 'org.mapstruct:mapstruct:1.4.1.Final'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.7.1'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java'
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.1.Final'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.7.2'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
jacoco {
toolVersion = "0.8.7"
reportsDirectory = file("$buildDir/customJacocoReportDir")
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/jacocoHtml")
}
}
test {
useJUnitPlatform()
}
}
// npm -> yarn 으로 변경
node {
version = '16.6.1'
yarnVersion = "1.22.17"
download = true
distBaseUrl = 'https://nodejs.org/dist'
workDir = file("./module-vue-ts/nodejs")
yarnWorkDir = file("./module-vue-ts/yarn")
nodeModulesDir = file("./module-vue-ts")
}
task setUp(type: YarnTask) {
description = "Install Node.js packages"
args = ['install']
inputs.files file('package.json')
outputs.files file('node_modules')
}
task buildVue(type: YarnTask, dependsOn: setUp) {
description = "Build vue.js"
args = ['run', 'build']
}
processResources.dependsOn 'buildVue'
bootJar {
mainClassName = 'com.woomoolmarket.ModuleApiApplication'
}
'Spring > Spring Setting' 카테고리의 다른 글
[Intellij] 구글 코드 스타일 적용, if문 & for문 자동 괄호 없애기 (0) | 2022.02.20 |
---|---|
[P6Spy] p6spy 콘솔에 찍고 로그 파일 저장하기 (0) | 2022.02.18 |
[P6Spy] Log4j2, p6spy 적용해보기 (0) | 2021.11.29 |
[Gradle] Gradle Build & Test 병렬 실행으로 최적화하기 (0) | 2021.09.09 |
[JPA] Spring Data JPA, QueryDSL setting (0) | 2021.09.03 |