소개
Maven으로 프로젝트를 수행하는 경우 Sub Module을 처리하는 방법은 여러 가지가 있습니다. 특히 Sub Module을 조직화하고 릴리즈 관리를 하는 것은 매우 어려운 일입니다. 다음은 Sub Module로 구성된 프로젝트의 구조를 시각화한 도식입니다.

이를 이해하기 위해서 상기 도식에서 사용한 용어에 대해서 먼저 정의를 해보겠습니다.
용어 | 세부 설명 |
---|
POM | Maven의 Project Object Module. 개별 프로젝트 및 Sub Module은 POM을 정의해야 한다. POM은 pom.xml 파일로 정의한다. |
Super POM | POM의 <package> 을 pom 으로 정의한 POM <module> 을 통해 Sub Module이 정의될 수 있음
Sub Module (Child POM)에서 공통으로 사용하는 것들을 정의 (예; dependency, plugin 등) |
Dependency | POM의 <dependency> 로 정의하는 의존성 라이브러리 |
Transitive Dependency | Dependency를 추가함으로써 딸려오는 Dependency |
Module | Sub Project 또는 Sub Module의 개념 Module은 POM을 가질 수 있음 Parent POM에서 <module> 을 통해 정의 가능 |
Inherit | POM을 상속 Sub Module은 부모의 POM을 상속받음 |
Parent POM | 부모 역할을 하는 POM (자바의 상속과 동일) |
Sub Module을 처리하면서 어려운 문제들
- Parent POM을 지정하면 POM을 상속받아서 dependency도 모두 따라옵니다.
- 만약 다른 프로젝트에서 해당 POM을 dependency로 추가하면 빌드시 모든 dependency를 다운로드합니다. → 오랜 시간이 소요됩니다.
- Parent POM의 자식 POM(module)은 모두 한꺼번에 빌드가 됩니다. → 만약 특정 Module이 수정되지 않는다면 버전 관리가 애매해집니다.
- 모두 한꺼번에 빌드가 되기 때문에 모든 module의 버전을 하나로 통일해서 관리하기는 매우 좋습니다.
- 단, 특정 모듈이 수정이 없는 경우 → 수정이 없음애도 버전을 올라갈 수 있는 여지가 있습니다.
의존 관계의 한 dependency(=artifact)가 여러 버전이 있는 경우 Maven은 어떻게 버전을 선택할까요? 다음은 X를 의존하는 여러 개의 모듈이 있습니다. 이 경우 Maven은 depth를 고려하여 depth가 깊지 않은 것을 먼저 선택하므로 X 1.0을 선택합니다.
eyJleHRTcnZJbnRlZ1R5cGUiOiIiLCJnQ2xpZW50SWQiOiIiLCJjcmVhdG9yTmFtZSI6IkVkd2FyZCIsIm91dHB1dFR5cGUiOiJibG9jayIsImxhc3RNb2RpZmllck5hbWUiOiJFZHdhcmQiLCJsYW5ndWFnZSI6ImVuIiwidWlDb25maWciOiJ7fSIsImRpYWdyYW1EaXNwbGF5TmFtZSI6IiIsInNGaWxlSWQiOiIiLCJhdHRJZCI6IjcyNTE1NjE4IiwiZGlhZ3JhbU5hbWUiOiLqsIDquYzsmrQgZGVwZW5kZW5jeSDshKDtg50gKEdsaWZmeSkiLCJhc3BlY3QiOiIiLCJsaW5rcyI6ImF1dG8iLCJjZW9OYW1lIjoiTWF2ZW4gU3ViIE1vZHVsZSDrsI8gIERlcGVuZGVuY3kiLCJ0YnN0eWxlIjoidG9wIiwiY2FuQ29tbWVudCI6ZmFsc2UsImRpYWdyYW1VcmwiOiIiLCJjc3ZGaWxlVXJsIjoiIiwiYm9yZGVyIjpmYWxzZSwibWF4U2NhbGUiOiIxIiwib3duaW5nUGFnZUlkIjo0MjI3MTQ1LCJlZGl0YWJsZSI6ZmFsc2UsImNlb0lkIjo0MjI3MTQ1LCJwYWdlSWQiOiIiLCJsYm94Ijp0cnVlLCJzZXJ2ZXJDb25maWciOnsiZW1haWxwcmV2aWV3IjoiMSJ9LCJvZHJpdmVJZCI6IiIsInJldmlzaW9uIjoyLCJtYWNyb0lkIjoiYmRiZThiZDktMWZlMy00OGRhLTg5MjMtMTgyMjRlNDQwOTdmIiwicHJldmlld05hbWUiOiLqsIDquYzsmrQgZGVwZW5kZW5jeSDshKDtg50gKEdsaWZmeSkucG5nIiwibGljZW5zZVN0YXR1cyI6Ik9LIiwic2VydmljZSI6IiIsImlzVGVtcGxhdGUiOiIiLCJ3aWR0aCI6Ijk5MSIsInNpbXBsZVZpZXdlciI6ZmFsc2UsImxhc3RNb2RpZmllZCI6MTY5NjcyODk3MTUwMCwiZXhjZWVkUGFnZVdpZHRoIjpmYWxzZSwib0NsaWVudElkIjoiIn0=
다음은 depth가 동일한 경우입니다. 이 경우는 먼저 선언한 것을 선택하므로 X 2.0을 선택하게 됩니다.
eyJleHRTcnZJbnRlZ1R5cGUiOiIiLCJnQ2xpZW50SWQiOiIiLCJjcmVhdG9yTmFtZSI6IkVkd2FyZCIsIm91dHB1dFR5cGUiOiJibG9jayIsImxhc3RNb2RpZmllck5hbWUiOiJFZHdhcmQiLCJsYW5ndWFnZSI6ImVuIiwidWlDb25maWciOiJ7fSIsImRpYWdyYW1EaXNwbGF5TmFtZSI6IiIsInNGaWxlSWQiOiIiLCJhdHRJZCI6IjcyNTE1NjIyIiwiZGlhZ3JhbU5hbWUiOiLslZ7shKAgZGVwZW5kZW5jeSDshKDtg50gKEdsaWZmeSkiLCJhc3BlY3QiOiIiLCJsaW5rcyI6ImF1dG8iLCJjZW9OYW1lIjoiTWF2ZW4gU3ViIE1vZHVsZSDrsI8gIERlcGVuZGVuY3kiLCJ0YnN0eWxlIjoidG9wIiwiY2FuQ29tbWVudCI6ZmFsc2UsImRpYWdyYW1VcmwiOiIiLCJjc3ZGaWxlVXJsIjoiIiwiYm9yZGVyIjpmYWxzZSwibWF4U2NhbGUiOiIxIiwib3duaW5nUGFnZUlkIjo0MjI3MTQ1LCJlZGl0YWJsZSI6ZmFsc2UsImNlb0lkIjo0MjI3MTQ1LCJwYWdlSWQiOiIiLCJsYm94Ijp0cnVlLCJzZXJ2ZXJDb25maWciOnsiZW1haWxwcmV2aWV3IjoiMSJ9LCJvZHJpdmVJZCI6IiIsInJldmlzaW9uIjoxLCJtYWNyb0lkIjoiMDEyMjkxNTItODczYy00ZTljLTllZjMtMzkyY2U3YTk5ZTY3IiwicHJldmlld05hbWUiOiLslZ7shKAgZGVwZW5kZW5jeSDshKDtg50gKEdsaWZmeSkucG5nIiwibGljZW5zZVN0YXR1cyI6Ik9LIiwic2VydmljZSI6IiIsImlzVGVtcGxhdGUiOiIiLCJ3aWR0aCI6Ijc3NCIsInNpbXBsZVZpZXdlciI6ZmFsc2UsImxhc3RNb2RpZmllZCI6MTY5NjcyOTAyMDQwMywiZXhjZWVkUGFnZVdpZHRoIjpmYWxzZSwib0NsaWVudElkIjoiIn0=
Dependency Management
동일 dependency의 버전 고정하기
동일 dependency를 사용하지만 Sub Module간의 버전이 다르다면? 다음의 도식을 살펴보겠습니다.
eyJleHRTcnZJbnRlZ1R5cGUiOiIiLCJnQ2xpZW50SWQiOiIiLCJjcmVhdG9yTmFtZSI6IkVkd2FyZCIsIm91dHB1dFR5cGUiOiJibG9jayIsImxhc3RNb2RpZmllck5hbWUiOiJFZHdhcmQiLCJsYW5ndWFnZSI6ImVuIiwidWlDb25maWciOiJ7fSIsImRpYWdyYW1EaXNwbGF5TmFtZSI6IiIsInNGaWxlSWQiOiIiLCJhdHRJZCI6IjcyNTE1NjI0IiwiZGlhZ3JhbU5hbWUiOiJTdWIgTW9kdWxl7J2YICDshJzroZwg64uk66W4IGRlcGVuZGVuY3kgKEdsaWZmeSkiLCJhc3BlY3QiOiIiLCJsaW5rcyI6ImF1dG8iLCJjZW9OYW1lIjoiTWF2ZW4gU3ViIE1vZHVsZSDrsI8gIERlcGVuZGVuY3kiLCJ0YnN0eWxlIjoidG9wIiwiY2FuQ29tbWVudCI6ZmFsc2UsImRpYWdyYW1VcmwiOiIiLCJjc3ZGaWxlVXJsIjoiIiwiYm9yZGVyIjpmYWxzZSwibWF4U2NhbGUiOiIxIiwib3duaW5nUGFnZUlkIjo0MjI3MTQ1LCJlZGl0YWJsZSI6ZmFsc2UsImNlb0lkIjo0MjI3MTQ1LCJwYWdlSWQiOiIiLCJsYm94Ijp0cnVlLCJzZXJ2ZXJDb25maWciOnsiZW1haWxwcmV2aWV3IjoiMSJ9LCJvZHJpdmVJZCI6IiIsInJldmlzaW9uIjoxLCJtYWNyb0lkIjoiYmRhOWE5MzQtY2I2Ni00ZjUwLWE1M2MtMDA3OTEwMzE1ZGJhIiwicHJldmlld05hbWUiOiJTdWIgTW9kdWxl7J2YICDshJzroZwg64uk66W4IGRlcGVuZGVuY3kgKEdsaWZmeSkucG5nIiwibGljZW5zZVN0YXR1cyI6Ik9LIiwic2VydmljZSI6IiIsImlzVGVtcGxhdGUiOiIiLCJ3aWR0aCI6Ijc3MSIsInNpbXBsZVZpZXdlciI6ZmFsc2UsImxhc3RNb2RpZmllZCI6MTY5NjcyOTA4ODI2MSwiZXhjZWVkUGFnZVdpZHRoIjpmYWxzZSwib0NsaWVudElkIjoiIn0=
A와 B Sub Module의 X dependency 버전이 다른 것을 확인할 수 있습니다. 만약에 Sub Module에서 X의 버전을 하나로 통일하고자 한다면 Super POM에 다음과 같이 추가합니다.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>X</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</dependencyManagement>
일괄 버전 고정하기
규모가 큰 프로젝트는 여러 모듈로 쪼개져 있습니다(예; Spring Boot). 통상적으로 문제가 안되지만 Spring Boot를 dependency로 하는 다른 외부 dependency를 추가하다보면 Spring Boot의 버전이 다를 수 있습니다.
eyJleHRTcnZJbnRlZ1R5cGUiOiIiLCJnQ2xpZW50SWQiOiIiLCJjcmVhdG9yTmFtZSI6IkVkd2FyZCIsIm91dHB1dFR5cGUiOiJibG9jayIsImxhc3RNb2RpZmllck5hbWUiOiJFZHdhcmQiLCJsYW5ndWFnZSI6ImVuIiwidWlDb25maWciOiJ7fSIsImRpYWdyYW1EaXNwbGF5TmFtZSI6IiIsInNGaWxlSWQiOiIiLCJhdHRJZCI6IjcyNTE1NjI2IiwiZGlhZ3JhbU5hbWUiOiJCT00g7KCB7JqpIChHbGlmZnkpIiwiYXNwZWN0IjoiIiwibGlua3MiOiJhdXRvIiwiY2VvTmFtZSI6Ik1hdmVuIFN1YiBNb2R1bGUg67CPICBEZXBlbmRlbmN5IiwidGJzdHlsZSI6InRvcCIsImNhbkNvbW1lbnQiOmZhbHNlLCJkaWFncmFtVXJsIjoiIiwiY3N2RmlsZVVybCI6IiIsImJvcmRlciI6ZmFsc2UsIm1heFNjYWxlIjoiMSIsIm93bmluZ1BhZ2VJZCI6NDIyNzE0NSwiZWRpdGFibGUiOmZhbHNlLCJjZW9JZCI6NDIyNzE0NSwicGFnZUlkIjoiIiwibGJveCI6dHJ1ZSwic2VydmVyQ29uZmlnIjp7ImVtYWlscHJldmlldyI6IjEifSwib2RyaXZlSWQiOiIiLCJyZXZpc2lvbiI6MSwibWFjcm9JZCI6ImQ4NDkwZTFiLTVjNjgtNDFlZi04YWY3LWNiN2JiNTZjMDRiYSIsInByZXZpZXdOYW1lIjoiQk9NIOyggeyaqSAoR2xpZmZ5KS5wbmciLCJsaWNlbnNlU3RhdHVzIjoiT0siLCJzZXJ2aWNlIjoiIiwiaXNUZW1wbGF0ZSI6IiIsIndpZHRoIjoiODkxIiwic2ltcGxlVmlld2VyIjpmYWxzZSwibGFzdE1vZGlmaWVkIjoxNjk2NzI5MjY2MjYwLCJleGNlZWRQYWdlV2lkdGgiOmZhbHNlLCJvQ2xpZW50SWQiOiIifQ==
상기와 같은 경우 Spring Boot의 POM을 import하여 버전을 일괄 적용할 수 있습니다. 상기와 같은 구조를 가진 프로젝트에서는 Super POM에 다음과 같이 추가하면 됩니다.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>