Spring – 프로젝트 분할

Spring 프로젝트를 분할하여 라이브러리 한 후, 불러오는 방법, 그리고, 외부 라이브러리 저장소 (Nexus)등으로 올린 후, 불러와서 사용하는 법에 대하여 다루어 본다.

Maven 저장소 타입

Java 프로젝트는 Meven저장소를 이용하여 자바 프로젝트의 의존성과 아티팩트 배포를 관리한다. 저장소는 크게 다음과 같은 저장소로 나눌 수 있다.

  1. 로컬 저장소 (Local Repository)
  • 개발자가 자신의 시스템에 보유한 Maven 저장소
  • 기본적으로 Maven은 ~/.m2/repository 또는 C:\Users\<username>\.m2\repository 경로에 로컬 저장소를 생성함
  • 프로젝트 빌드를 실행할 때, Maven은 먼저 로컬 저장소에서 의존성 라이브러리를 찾음
  1. 중앙 저장소 (Central Repository)
  • Maven의 기본 저장소로 Apache에서 관리하는 중앙 서버
  • 전 세계 개발자들이 만든 수많은 오픈 소스 라이브러리, 플러그인, 아티팩트 들이 저장되어 있음
  • Maven의 기본 설정에 포함되어 있으며, https://repo.maven.apache.orb/maven2/ 주소로도 접근 가능함
  1. 원격 저장소 (Remote Repository)
  • Apache에서 관리하는 중앙 저장소 외에 다른 서버에서 호스팅 되는 Maven 저장소로 기업 내부에서 사용하는 개인 저장소나, 다른 공개 저장소들이 이에 해당함
  • Nexus나 Artifactory 같은 시스템을 이용해 자체적으로 Maven 저장소를 운영
  • 프로젝트에서 필요한 의존성이 로컬 저장소에 없을 경우, 해당 서버에서 의존성을 다운로드 함

 

Maven 저장소의 기본 역할

Maven 저장소의 기본 역할은 다음과 같다.

  1. 의존성 관리 : 프로젝트에서 필요한 라이브러리, 플러그인 등의 아티팩트를 쉽게 관리할 수 있음, 라이브러리는 groupId, artifactId, version으로 고유하게 식별됨
  2. 아티팩트 배포 : Maven 저장소에 라이브러리를 업로드 하여 다른 프로젝트에서도 사용할 수 있도록 함
  3. 버전 관리 : 러이브러리의 여러 버전이 한 저장소에 같이 존재할 수 있으며, Maven은 필요에 맞는 버전을 자동으로 다운로드 하여 의존성을 주입할 수 있음

 

빌드 자동화와 의존성 관리 도구

Maven

Maven은 빌드를 설정할 때 pom.xml파일을 사용하며, 이 파일은 선언적 방식으로 의존성, 플러그인, 빌드 설정 등을 명시한다.

Maven은 다음과 같은 특징을 가지고 있다.

  1. Maven은 XML 기반의 선언적 빌드 도구이다.
  2. pom.xml 파일에 프로젝트의 의존성, 플러그인, 빌드 설정 등을 정의한다.
  3. 프로젝트 모델을 엄격하게 정의하며, 표준화된 디렉터리 구조와 생명 주기를 따른다.
  4. 의존성 관리는 중앙 저장소(Maven Central)에서 제공하며, XML 설정으로 의존성을 선언한다.
  5. 의존성을 groupId, artifactId, version의 형식으로 정의한다.
  6. 단 방향 빌드를 사용하기 때문에, 빌드 과정이 선형적으로 진행되며, 이로 인해 빌드 속도가 상대적으로 느릴 수 있다.

코드 예시

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.10</version>
</dependency>
</dependencies>

 

Gradle

Gradle은 build.gradle 또는 build.gradle.kts 파일을 사용하며, Groovy 또는 Kotlin DSL을 사용하여 빌드 과정을 명령형으로 구성할 수 있다. 이는 더 유연하고 프로그램적으로 제어할 수 있는 장점을 가진다.

Gradle은 다음과 같은 특징을 가지고 있다.

  1. Gradle은 **DSL(Domain-Specific Language)**을 사용하는 빌드 도구이다. 기본적으로 Groovy 또는 Kotlin DSL을 사용해 build.gradle 또는 build.gradle.kts 파일을 작성한다.
  2. 동적이고 유연한 빌드 시스템으로, XML 기반의 선언적 방식과 달리 스크립트 기반의 명령형 빌드 설정을 사용한다.
  3. Gradle은 Maven보다 더 유연하고 확장성이 뛰어나며, 성능도 우수하다는 평가를 받는다. Gradle은 병렬 처리나 캐싱을 통해 빌드 속도를 최적화할 수 있다.
  4. Gradle은 Maven과 동일한 방식으로 의존성을 관리하지만, 더 유연한 방식으로 추가적인 저장소나 의존성 전략을 설정할 수 있다.
  5. 병렬 빌드와 캐시를 활용하여 빌드 성능을 크게 개선할 수 있다. Incremental Build와 Build Caching을 지원하여 동일한 작업을 반복 할 때 속도 개선 효과를 얻을 수 있다.

 

코드 예시

dependencies {
implementation ‘org.springframework:spring-core:5.3.10’
}

 

도구 비교

항목

Maven

Gradle

설정파일

pom.xml (XML)

build.gradle (Groovy/Kotlin DSL)

의존성 관리

중앙 저장소 (Maven Central) 사용

중앙 저장소와 다양한 커스텀 저장소 지원

성능

상대적으로 느림

명렬 빌드, 캐싱, 성능 최적화

유연성

표준화된 방식, 덜 유연함

높은 유연성, 커스터마이징 가능

빌드 모델

선언적 방식 (표준화된 생명주기)

명령형 방식 (스크립트 기반)

플러그인 시스템

표준화된 플러그인 사용

강력하고 유연한 플러그인 시스템

커스터마이징

제한적

자유롭게 커스터마이즈 가능

주요 사용 사례

표준화된 대규모 프로젝트

성능 최적화가 필요한 프로젝트, Android 개발 등

 

프로젝트 분할

Gradle을 이용하여 프로젝트 빌드 설정을 진행하며, 기존에 개발된 하나의 프로젝트를 기반으로 소스를 분리하고, 프로젝트를 분리하여 의존성을 설정하는 방법으로 프로젝트를 분리하려 한다.

분할 목표 프로젝트 구조

분할된 프로젝트는 루트 프로젝트서브 프로젝트로 나누어 볼 수 있다.

  1. 루트 프로젝트는 전체 프로젝트의 루트 디렉토리에 존재하는 프로젝트를 의미하며, 모든 서브 프로젝트의 설정을 포함한다.
  2. 서브 프로젝트는 루트 프로젝트 아래에 위치한 개별적인 모듈을 말하며, 별도의 build.gradle파일을 가지며, 여기에서 서브 프로젝트의 빌드 설정 및 의존성을 관리한다.

기본 구조는 다음과 같다.

my-multi-project/

├── settings.gradle // 프로젝트 설정
├── build.gradle // 루트 프로젝트의 빌드 설정

├── module1/ // 서브 프로젝트 1
│ └── build.gradle

├── module2/ // 서브 프로젝트 2
│ └── build.gradle

└── module3/ // 서브 프로젝트 3
└── build.gradle

 

 

 

settings.gradle 파일 설정

Settings.gradle파일은 Gradle이 멀티 프로젝트를 인식하고, 각 서브 프로젝트를 포함하도록 지정하는 파일이다. 이 파일에서 모든 서브 프로젝트를 정의한다.

코드 예시

// 루트 프로젝트의 이름
rootProject.name = ‘my-multi-project’

// 서브 프로젝트 지정
include ‘module1’, ‘module2’, ‘module3’

 

루트 프로젝트의 build.gradle 설정

루트 프로젝트의 build.gradle에서는 공통 설정이나 모든 서브 프로젝트에 적용될 설정을 정의할 수 있다. 예를 들어, 모든 서브 프로젝트에 공통 의존성을 추가하거나 플러그인을 적용할 수 있다.

코드 예시

// 루트 프로젝트를 포함한 모든 프로젝트에 적용될 설정
allprojects {
repositories {
mavenCentral() // 모든 서브 프로젝트에서 Maven 중앙 저장소를 사용
}

dependencies {
// 모든 프로젝트에서 공통으로 사용할 의존성 설정 (예: logging 라이브러리)
implementation ‘org.slf4j:slf4j-api:1.7.32’
}
}

subprojects {
// 서브 프로젝트들에 대해서만 적용되는 설정
apply plugin: ‘java’

// Java 플러그인 적용 후 공통 설정
sourceCompatibility = ‘1.8’
targetCompatibility = ‘1.8’

// 서브 프로젝트에서만 사용하는 추가 의존성
dependencies {
implementation ‘org.springframework:spring-context:5.3.10’
}
}

 

서브 프로젝트의 build.gradle 설정

각 서브 프로젝트는 독립적인 build.gradle 파일을 가지며, 해당 파일에서는 해당 모듈에서만 필요한 빌드 설정을 추가한다.

코드 예시

apply plugin: ‘java’

dependencies {
// 이 모듈에만 필요한 의존성 추가
implementation project(‘:module2’) // 다른 서브 프로젝트를 의존성으로 추가
}

 

IntelliJ에서의 프로젝트 설정

IntelliJ에서는,

  1. 루트 프로젝트를 “New Project”로 생성
  2. 적절한 위치에, “New -> Module” 메뉴를 통해 서브 프로젝트 생성
  3. 서브 프로젝트 정리 시에, “gradle” 폴더와, “build.gradle” 파일은 제거하지 말 것

빌드 방법

위와 같은 방식으로 분할된 프로젝트를 빌드할 때는 다음과 같은 명령으로 다양한 형태로 빌드를 수행할 수 있다.

  1. 루트 프로젝트에서 전체 빌드할 때,

    ./gradlew build

  2. 특정 서브 프로젝트만 빌드할 때,

    ./gradlew :bodule1:build

     

라이브러리 배포 설정

이렇게 분할된 서브 프로젝트는, 위에서 설명한 Maven 중앙 저장소나, 로컬 저장소, 혹은 사내 커스텀 저장소에 올려 배포할 수 있다.

해당 설정은 서브 프로젝트의 성격에 따라 루트 프로젝트나 서브 프로젝트에 설정을 추가할 수 있다.

로컬 저장소에 배포

코드 예시

apply plugin: ‘java’
apply plugin: ‘maven-publish’

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
repositories {
maven {
url = uri(“file://${buildDir}/repo”) // 로컬 저장소로 배포
}
}
}

 

사설 저장소에 배포

다음과 같은 형태로, https://repo.repository.com/repository/maven-releases 주소를 가지는 사설 저장소에, user1 / password 계정 정보로 배포하는 설정은 다은과 같이 설정할 수 있다.

코드 예시

gradle.build

apply plugin: ‘java’
apply plugin: ‘maven-publish’

repositories {
mavenCentral()
}

dependencies {
implementation ‘org.springframework:spring-context:5.3.10’
}

// 배포 설정
publishing {
publications {
mavenJava(MavenPublication) {
from components.java // Java 컴포넌트(라이브러리)를 배포
}
}

repositories {
maven {
name = “MyPrivateRepo” // 저장소 이름 (임의 설정 가능)
url = uri(“https://repo.repository.com/repository/maven-releases/”) // 사설 저장소 URL

credentials {
username = project.findProperty(“repoUser”) ?: “user01” // 사용자명 (프로젝트 속성 또는 기본값)
password = project.findProperty(“repoPassword”) ?: “password” // 비밀번호 (프로젝트 속성 또는 기본값)
}
}
}
}

 

repoUser, repoPassword 는 다음과 같이 외부로 추출하여 보안을 강화할 수도 있다.

gradle.properties

repoUser=user1
repoPassword=password

 

버전 설정 방법

아래와 같이 버전을 Project Property로 받아올 수 있게 변경한 후, 빌드 명령 뒤에 –Pversion 형태로 인자를 전달하면 된다.

 

[build.gradle]

version = project.hasProperty(‘version’) ? project.version : ‘0.0.1’

 

C:\> .\gradlew.bat build -Pversion=”[VERSION]”
C:\> .\gradlew.bat publish -Pversion=”[VERSION]”

 

배포 방법

이렇게 분할되고, 배포될 저장소 설정 까지 마무리 되었으면, 아래 명령을 통해 배포를 수행할 수 있다.

./gradlew publish

 

버전 및 배포 파일에 대한 설명 추가 방법

배포 시, 해당 프로젝트의 정보를 추가하려면, 프로젝트에 다음과 같이 설정하면 된다.

publishing {
publication {
mavenJava(MavenPublication) {

// 1. Group ID 설정
groupId = ‘com.company.lib’

// 2. Artifact ID 설정
artifactId = ‘module1’

// 3. Version 설정
version = ‘0.0.1’

// 4. Artifact 파일 정의
artifact(“$buildDir/build/libs/module.jar”)

// 5. pom 설정
pom {
// 5-1. 프로젝트 이름 설명
name.set(“Module 1”)

// 5-2. 프로젝트 상세 설명
description.set(“Common Module”)

// 5-3. URL 설명
url.set(https://common.campany.com/module1)

// 5-4. Licnese설명
licenses {
license {
name.set(“The Apache License, Version 2.0”)
url.set(http://www.apache.org/licenses/LICENSE-2.0)
}
}

// 5-5. 개발자 정보
developers {
developer {
id.set(“johnkim”)
name.set(“John Kim”)
email.set(john@company.com)
}
}

// 5-6. 저장소 정보
scm {
developerConnection.set(“scm:git:ssh://git@gitlab.company.com/common/module1.git”)
url.set(https://gitlab.company.com/common/module1.git)
}

// 5-7. POM 정보 생성
pom.withXml pomfileManualGenerator

}
}
}
}

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다