티스토리 뷰
- 현업을 경험해보기 전에는 프로젝트가 비교적 단순했기 때문에 gradle 설정도 간단했고 멀티 프로젝트라는 개념도 눈에 들어오지 않았습니다.
- 이번에 맡게된 프로젝트를 뜯어보면서도 어떤 구조로 설계되었는지, 어떠한 로직들로 구성되었는지를 파악하는 데에만 집중하였고 application.yml 이나 build.gradle 설정들은 신경쓰지 못했던 것 같습니다.
- 중요하지만 간과하기 쉬운 부분을 다지는 의미에서 직접 멀티 모듈 프로젝트를 구성해보며 해당 내용을 정리하게 되었습니다.
프로젝트 구성
- multi-project(root 프로젝트. 전역 설정을 담당)
- module-boot(프로젝트 부팅을 담당)
- module-domain(엔티티)
- module-controller(컨트롤러)
- 전역 설정을 담당하는 multi-project를 구성하면서 전역에서 함께 사용할 디펜던시를 추가해주었습니다.
- 그러면 처음에는 위와 같은 구조로 프로젝트가 생성이 됩니다.
- 그리고 multi-project 하위에 각 모듈들을 추가해줍니다.
- 그러면 각 모듈들도 루트 프로젝트와 마찬가지로 gradle폴더와 build.gradle, settings.gradle을 갖게 됩니다. 우선 이 파일들이 어떤 역할을 하는지 알아보아야 할 것 같습니다.
build.gradle / settings.gradle / gradle.wrapper
build.gradle
- 프로젝트의 의존관계나 태스크를 정의할 때 사용됩니다. 일반적으로 gradle 프로젝트는 이 파일만으로 빌드가 가능합니다.
settings.gradle
- settings.gradle은 빌드에 포함될 프로젝트들을 설정하는 스크립트입니다. 빌드에 참여하는 프로젝트들의 계층 구조를 정의하고 구성하는 데 필요한 설정을 작성합니다.
rootProject.name = 'multi-project'
include 'module-boot'
include 'module-domain'
include 'module-controller'
- 기본적으로
rootProject.name = '[프로젝트 이름]'
이 입력되어서 생성이 되는데요. 하위 프로젝트는 include 를 통해 정의할 수 있습니다. - gradle은 빌드가 실행될 때마다 settings.gradle 파일을 찾아, 해당 파일을 참고하여 빌드를 초기화합니다.
- 만약 settings.gradle 파일이 없는 디렉토리에서 gradle을 실행하는 경우 다음 순서를 따릅니다.
- 우선 상위 디렉토리에서 찾습니다.
- 상위 디렉토리에서 찾았다면, 현재 프로젝트가 multi-project 빌드에 참여하는지 확인합니다. 참여한다면 multi-project로 빌드됩니다.
- 만약 찾지 못했다면 단일 프로젝트로 빌드됩니다.
gradle.wrapper
- gradle 프로젝트를 빌드하고 실행하기 위해서는 로컬 컴퓨터에 해당 프로젝트와 동일한 버전이 존재해야 합니다. 만약 이들이 일치하지 않는다면, 당연하게도 오류가 발생합니다.
- 따라서, 항상 사용하려는 프로그램의 gradle 버전과 동일하게 gradle을 설치해주어야 하는데 이는 굉장히 비효율적인 방법입니다.
- gradle Wrapper는 지정된 버전의 gradle을 실행하는 스크립트로, 필요한 경우 gradle 배포판(distribution)을 배포 서버에서 다운로드하여 위 과정들을 자동화해줍니다.
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
- gradle-wrapper.properties를 보면 위와 같은 코드를 볼 수가 있는데 distributionUrl에 지정되어 있는 gradle버전을 사용하여 빌드를 하게 됩니다.
gradle-wrapper.jar
- gradle 배포판을 다운로드하는 코드가 포함된 JAR 파일입니다.
gradle-wrapper.properties
- 현재 프로젝트와 호환되는 Gradle 배포판의 버전을 포함하여 Gradle Wrapper의 런타임 속성이 포함됩니다.
gradlew, gradle.bat
- wrapper를 통해 빌드를 실행하는 스크립트로 gradlew은 맥과 리눅스용, gradle.bat은 윈도우용 스크립트입니다.
- gradle 빌드는 항상 Wrapper를 통해 실행하는 것이 권장됩니다.
- gradle build를 사용하면 로컬에 설치된 gradle과 java를 기준으로 build하지만, ./gradlew build를 실행하면 build.gradle파일에 정의한 내용을 기준으로 build되기 때문에 로컬 환경과 관계없이 프로젝트를 빌드할 수 있습니다.
- wrapper는 gradlew를 통해 다음과 같이 사용할 수 있습니다.
./gradlew [태스크 이름]
- 위는 gradle [태스크 이름]과 동일한 역할을 하는데, 컴퓨터에 설치된 gradle이 아닌 wapper를 사용한다는 것이 차이점입니다.
gradle.bat은 다음과 같이 사용할 수 있습니다.
gradlew.bat [태스트 이름]
- settings.gradle 같은 경우는 루트 프로젝트에서 하위 프로젝트를 정의하는 데 사용할 수 있으므로 하위 모듈들은 갖고 있을 필요가 없을 것입니다.
- wrapper 또한 루트 프로젝트만 갖고 있어야 되겠지요! 따라서 필요한 파일들만 남기고 모두 삭제해줍니다.
전역 build.gradle 설정
// multi-project의 build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.3'
id 'io.spring.dependency-management' version '1.1.4'
}
// 전역 모듈은 Main Class() 가 존재하지 않으므로 bootJar를 만들지 않음
bootJar.enabled = false
// 모든 프로젝트에 공통으로 적용할 사항.
allprojects {
group = 'org.example'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
}
}
// 하위 프로젝트에 공통으로 적용할 사항
subprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.withType(Test).tap {
configureEach {
enabled = false
}
}
// 컨트롤러와 도메인 모듈은 Main Class()를 사용하지 않으므로 bootJar 작업을 비활성화!
project(':module-controller') {
bootJar.enabled = false
}
project(':module-domain') {
bootJar.enabled = false
}
}
- 전역 설정으로 하위 프로젝트에 공통으로 롬복을 포함한 디펜던시들을 정의해주었습니다.
- module-domain 에는 따로 디펜던시를 설정하지 않았지만 domain 모듈에서 롬복을 사용할 수 있는 모습입니다.
마무리
- 멀티 프로젝트를 구성하는 것 자체는 어렵지 않았지만 여러가지 생각할 거리들이 많았습니다.
- 하위 모듈간 의존을 위한 implements나 api project와 같은 키워드도 알아볼 필요성을 느꼈고
- 전체적인 프로젝트 구성을 어떻게 하느냐에 따라 설계 방식도 많이 달라질 것 같다는 생각을 하였습니다.
- 그리고 의존성을 주입하는 것도 전역에서 주입을 할 것인지 특정 모듈에만 주입을 할 것인지에 대한 고민도 필요한 것 같습니다.
관련 자료
반응형
'개발냥이 > 자바(Java)' 카테고리의 다른 글
[자바] 단위 테스트 도구, JUnit 기초 (0) | 2023.10.12 |
---|---|
[자바] 비트 연산자 알아보기! (2) | 2023.10.05 |
[자바] Record 찍먹 (0) | 2023.08.08 |
[스프링부트] Logback 설정해보기 (1) | 2023.06.05 |
[자바] 제네릭의 와일드카드 & 공변성 뿌시기 (1) | 2023.05.28 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 자바
- Comparator
- JavaScript
- 타입스크립트
- java
- dfs
- 자바스크립트
- 해시맵
- 백준
- 정렬
- Nest
- BFS
- 이분탐색
- 리액트
- DP
- 자바dp
- Spring
- JPA
- 자바트리
- SQLD
- Algorithm
- Queue
- 프로그래머스
- 알고리즘
- 자바bfs
- SQL
- CS
- 형변환
- 스프링부트
- 스프링
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함