Maven은 소스코드 빌드를 돕는 도구이다. 그런데 소스코드는 우리가 직접 개발하는 것 외에 수 많은 외부 라이브러리에 의존한다. 따라서 Maven이 빌드 도구로서 수행하는 중요한 역할 중 하나는 우리 프로젝트에서 의존하는 외부 라이브러리 패키지를 다운로드하고 관리하는 것이다. 우리는 프로젝트에서 새로운 라이브러리를 사용하기 원하는 경우 pom.xml (pom : Project Object Model) 파일에 라이브러리 패키지 정보를 추가한다. Maven은 빌드 시 해당 설정을 보고 먼저 Maven 로컬 저장소(내 컴퓨터)에서 해당 패키지를 찾는다. 만약 패키지가 로컬 저장소에 존재하지 않는 경우 리모트 저장소(Maven Central Repository)에서 해당 패키지를 다운로드 받는다. 조금 더 자세히 살펴보자.
먼저 프로젝트 외부에 존재하는 라이브러리 패키지를 내 프로젝트에서 사용할 수 있도록 추가해 보자. 이를 위해 프로젝트 루트 경로에 존재하는 pom.xml 파일의 dependencies 섹션에 사용하기 원하는 의존 패키지를 명시해 줄 수 있다. 기본적으로 섹션에 하위 섹션을 추가한다.
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.99.Final</version>
</dependency>
</dependencies>
내가 원하는 패키지를 사용하기 위해 명시할 정보는 Maven Repository 웹 사이트에서 원하는 이름을 검색해서 찾을 수 있다. 예를들면 Netty 프로젝트의 최신 버전을 사용하고 싶다면 다음과 같은 정보를 얻을 수 있고 복사해서 그대로 pom.xml dependencies 섹션 안에 붙여 넣으면 된다.
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.99.Final</version>
</dependency>
pom.xml 파일에 명시한 패키지 정보는 기본적으로 groupId / artifactId / version 으로 구성되는데 이는 일종의 패키지를 유일하게 식별하기 위한 폴더 구조와도 같다고 볼 수 있다. 실제로 위의 Netty 최신 패키지를 Maven Central Repository에서 찾아보면 정확히 매칭되는 경로(/io/netty/netty-all/4.1.99.Final)를 가지는 것을 확인할 수 있고, 해당 경로에 {artifactId}-{version}.jar 이름 형식의 파일을 찾을 수 있다.
Maven은 빌드 시 pom.xml 파일을 보고 먼저 Maven 로컬 저장소(내 컴퓨터)에서 의존 패키지를 찾는데 만약 로컬 저장소에 존재하지 않는 경우 리모트 저장소(Maven Central Repository)에서 해당 패키지를 다운로드 받는다.
mvn clean package
패키지가 다운로드된 로컬 저장소를 보면 Maven Central Repository에서 확인했던 것과 동일한 폴더 경로에 패키지가 다운로드 된 것을 확인할 수 있다. 인텔리제이를 사용하고 있다면 Menu > File > Settings > Build, Execution, Deployment > Build Tools > Maven > Repositories 에서 local 저장소 경로를 확인할 수 있다.
<dependency>
<groupId>io.joosing</groupId>
<artifactId>fireball</artifactId>
<version>0.0.1</version>
</dependency>
만약에 Maven Central Repository에 없는 사내에서만 사용하는 공통 라이브러리를 pom.xml 에서 참조한다면 해당 공통 라이브러리 프로젝트를 직접 빌드해서 로컬 저장소에 설치해 줄 수도 있다. 이때 공통 라이브러리 프로젝트를 열고 빌드 시 install 단계까지 수행하도록 하면 된다.
mvn clean install
이때 패키지가 로컬 저장소에 설치되는 경로는 공통 라이브러리 프로젝트의 pom.xml 파일에 명시된 자신의 패키지 정보가 폴더 경로 정보로 사용된다. 만약 아래와 같다면 .m2/io/joosing/fireball/0.0.1/ 경로에 fireball-0.0.1.jar 패키지가 설치된다.
<groupId>io.joosing</groupId>
<artifactId>fireball</artifactId>
<version>0.0.1</version>
<name>fireball</name>
Maven 로컬 저장소가 아니라 프로젝트 하위 경로에서 패키지를 참조하게 할 수도 있다. pom.xml 파일에 다음과 같이 의존성을 설정해 주면 pom.xml 파일이 존재하는 프로젝트 루트 경로로부터 의존 패키지를 참조하게 된다. 그러나 해당 설정은 deprecated 되어있음으로 권고하지 않는다.
<dependency>
<groupId>io.joosing</groupId>
<artifactId>fireball</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/fireball-0.0.1.jar</systemPath>
</dependency>
매번 스프링 부트 이니셜라이저로 프로젝트를 생성하다 보니 Maven에 대해 잘 알지 못한 채 그저 편리함에 기대어 온 것 같다. 낯선 형식의 프로젝트를 마주하며 Maven에 대해 더 깊이 알게 되어 기쁘다.