빌드노트
pluginManagement에 execution을 넣었는데 Maven이 실행하지 않는 이유
pluginManagement의 execution은 관리 기본값이다. AntRun 파일 생성이 빠지는 두 POM을 비교하고 build/plugins 참조로 연결하는 방법을 설명한다. jar 기본 생명주기에 연결된 Resources는 별도로 구분한다.
pom.xml의 pluginManagement에 실행할 goal과 phase까지 넣었는데, 빌드는 성공하고 생성 파일은 나오지 않을 수 있다. 관리 목록에 실행 설정을 보관하는 것과 그 플러그인을 빌드에 연결하는 것은 별개다. AntRun처럼 기본 생명주기에 연결되지 않은 플러그인은 build/plugins에도 참조가 있어야 관리하던 실행 설정이 적용된다.
관리 목록에만 있는지 확인한다
먼저 실행 대상 모듈의 최종 POM을 확인한다. 소스 POM에서 이름을 검색하는 것만으로는 부모에게 받은 설정과 관리 목록을 구별하기 어렵다. Maven과 JDK를 사용할 수 있는 환경에서 해당 모듈의 pom.xml이 있는 폴더로 이동한다. 아래는 PowerShell 명령이며, Help 플러그인이 없으면 저장소에서 받아야 한다. 기존 빌드에 -P나 -D 조건을 줬다면 조회에도 같은 조건을 붙인다.
다음 명령은 부모 설정과 활성 profile 등이 반영된 POM을 effective-pom.xml에 저장한다.
mvn.cmd -B -ntp org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom "-Doutput=effective-pom.xml"
명령이 성공하면 XML에서 대상 플러그인의 groupId·artifactId와 그 위치를 함께 본다. Help 플러그인 문서 (새 탭에서 열림)는 이 출력에 활성 profile을 반영한다고 설명한다.
project/build/pluginManagement/plugins/plugin에만 있다면 관리 기본값이다.project/build/plugins/plugin에도 있다면 빌드에 포함된 플러그인이다. 그 안에 기대한 execution과 goal이 들어왔는지 확인한다.
조회 자체가 의존 파일 다운로드 오류 등으로 실패했다면 실행 연결 여부를 아직 판정할 수 없다. XML에 같은 이름이 한 번 나왔다는 이유만으로 연결됐다고 판단하지 않는다.
관리 설정을 쓰려는 모듈에서는 기존 build/plugins에 다음 참조를 추가한다. 이 예시는 관리 목록에 maven-antrun-plugin의 버전과 execution이 이미 있을 때의 수정이다.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
이 plugins는 build 바로 아래에서 pluginManagement와 나란히 놓는다. 기존 plugins가 있으면 그 안에 plugin만 추가한다. 같은 플러그인이 이미 선언돼 있다면 그 선언을 확인한다. 관리 설정을 복사하거나 같은 플러그인을 중복 선언할 필요는 없다.
Maven POM 문서의 Plugin Management (새 탭에서 열림)는 현재 POM이나 자식 POM이 참조하는 플러그인에 관리 설정을 적용한다고 설명한다. 관리 목록에 버전만 있다면 참조를 추가해도 사용자 정의 작업이 새로 생기지는 않는다. 생명주기에서 실행하려면 goal과 단계 사이의 연결이 필요하다. 이 글의 비교에서는 goal과 phase를 모두 관리 목록에 명시했다.
같은 validate가 서로 다른 결과를 냈다
이 차이는 새 최소 POM 두 개로 확인했다. 실제 서비스의 빌드 실패를 재현한 것이 아니라, 실행 연결만 비교하기 위한 별도 실험이다. 두 POM은 packaging이 pom이며 별도로 지정한 부모 POM·profile·소스 코드가 없다. 모두 관리 목록에 org.apache.maven.plugins:maven-antrun-plugin:3.2.0을 넣었다. 두 번째에만 위의 build/plugins 참조를 추가했다.
관리한 execution은 validate 단계에서 run goal을 실행해 짧은 파일 하나를 쓰도록 했다. 핵심 입력은 다음과 같다.
<execution>
<id>write-marker</id>
<phase>validate</phase>
<goals><goal>run</goal></goals>
<configuration>
<target>
<mkdir dir="${project.build.directory}"/>
<echo file="${project.build.directory}/marker.txt">marker-created</echo>
</target>
</configuration>
</execution>
이 블록은 관리 플러그인의 executions 안에 넣은 내용이다. AntRun의 run 문서 (새 탭에서 열림)에서 설명하는 target 설정을 사용했다. 각 POM은 표식이 없는 새 폴더에서 실행했다.
이 예제의 실행 여부는 validate 로그와 파일 존재를 함께 보면 구별된다.
mvn.cmd -B -ntp validate
Test-Path ./target/marker.txt
관리 목록에만 둔 POM은 종료 코드 0과 BUILD SUCCESS를 출력했다. 그러나 write-marker 실행 행은 없었고 파일 조회는 False였다. 최종 POM에서도 AntRun은 관리 목록에만 남았다.
참조를 추가한 POM도 종료 코드 0이었지만, 이번에는 로그에 다음 행이 생겼다.
[INFO] --- antrun:3.2.0:run (write-marker) @ marker-lab ---
파일 조회는 True였고 내용은 marker-created였다. 최종 POM의 build/plugins에도 버전 3.2.0과 write-marker execution이 들어왔다. 참조에 execution을 다시 적지 않아도 관리 설정이 적용된 것이다.
이 비교에서 성공 종료는 두 조건 모두에 나왔다. 따라서 필요한 작업이 실행됐는지는 해당 goal의 실행 행과 새 산출물로 확인해야 한다. 이전 실행의 파일이 남아 있으면 파일 존재만으로도 오판할 수 있다. 실제 설정의 phase가 generate-resources라면 validate까지만 실행해서는 그 작업에 도달하지 않는다. 이때는 그 단계까지 실행하는 명령으로 확인한다. goal을 명령줄에서 직접 실행하는 방법은 생명주기 연결을 확인하는 이 비교와 다르다.
Resources는 참조 없이도 실행됐는데?
기본 생명주기에 이미 연결된 플러그인은 구분해야 한다. Maven 생명주기 문서 (새 탭에서 열림)에 따르면 jar 패키징에는 process-resources 단계의 resources:resources 같은 기본 연결이 있다. 소스 POM에 build/plugins를 직접 쓰지 않았어도 이 연결이 존재한다.
이를 확인하려고 별도의 jar POM에는 Resources 3.5.0의 버전과 outputDirectory만 관리 목록에 넣었다. 출력 위치를 target/managed-resources로 정하고, src/main/resources/probe.txt 하나를 준비했다. 명시적인 build/plugins 참조나 사용자 execution은 추가하지 않았다.
process-resources를 실행하자 다음 로그가 나왔고, 지정한 경로에 원문 그대로 복사됐다.
[INFO] --- resources:3.5.0:resources (default-resources) @ resource-lab ---
[INFO] Copying 1 resource from src\main\resources to target\managed-resources
최종 POM에도 Resources가 build/plugins에 나타났고 관리한 버전·출력 경로가 반영됐다. 출력 경로를 바꾼 것은 적용 여부를 구별하기 위한 실험 조건이다. 여기서 실행을 연결한 것은 jar의 기본 생명주기다. 이 결과를 근거로 AntRun의 관리 목록도 자동 실행된다고 해석하면 안 된다.
직접 확인한 환경은 Windows 11, Maven 3.9.16, JDK 17.0.2, PowerShell 7.6.6이다. 프로젝트와 로컬 저장소를 분리해 실행했으며 위 파일 생성·복사를 확인했다. Maven 4와 복잡한 부모·자식 execution 병합은 실행하지 않았다. 자신의 프로젝트에서는 최종 POM의 위치, 실행할 단계, 해당 goal의 로그를 함께 대조하면 관리 설정을 더 고칠지 실제 참조를 추가할지 판단할 수 있다.