토리맘의 한글라이즈 프로젝트 logo 토리맘의 한글라이즈 프로젝트

스프링 부트 공식 레퍼런스를 한글로 번역한 문서입니다.

전체 목차는 여기에 있습니다.

목차


12.16. Build

스프링 부트는 메이븐과 그래들을 위한 빌드 플러그인을 함께 제공하고 있다. 이번 섹션에선 이 플러그인들과 관련해서 많이들 물어보는 질문에 답해본다.

12.16.1. Generate Build Information

메이븐 플러그인과 그래들 플러그인은 모두 프로젝트의 그룹, 이름, 버전 정보를 가지고 있는 빌드 정보를 생성할 수 있다. 플러그인 설정을 통해 별도 프로퍼티도 추가해줄 수 있다. 스프링 부트는 이런 설정 파일이 있으면 BuildProperties 빈을 자동으로 설정한다.

메이븐으로 빌드 정보를 생성하려면 다음 예제와 같이 build-info goal을 위한 execution 설정을 추가해라:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.5.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

자세한 내용은 스프링 부트 메이븐 플러그인 문서를 참고해라.

위와 동일한 그래들 설정은 다음과 같다:

springBoot {
    buildInfo()
}

자세한 내용은 스프링 부트 그래들 플러그인 문서를 참고해라.

12.16.2. Generate Git Information

메이븐과 그래들 모두 프로젝트를 빌드하는 시점에 git 소스 코드 레포지토리의 상태 정보를 가지고 있는 git.properties 파일을 생성할 수 있다.

메이븐 사용자라면, spring-boot-starter-parent POM에 git.properties 파일을 생성하기 위한 플러그인이 미리 설정돼 있다. 이 플러그인을 사용하려면 POM 파일에 Git Commit Id Plugin 선언을 추가해라:

<build>
    <plugins>
        <plugin>
            <groupId>pl.project13.maven</groupId>
            <artifactId>git-commit-id-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Gradle 사용자는 아래 예제처럼 gradle-git-properties 플러그인을 이용하면 같은 효과를 볼 수 있다:

plugins {
    id "com.gorylenko.gradle-git-properties" version "2.2.4"
}

메이븐 플러그인과 그래들 플러그인에선 모두 git.properties에 포함시킬 프로퍼티를 설정할 수 있다.

git.properties에 있는 commit time은 yyyy-MM-dd'T'HH:mm:ssZ 포맷과 일치할 거다. 이 포맷은 위에서 설명한 플러그인들이 사용하는 디폴트 포맷이다. 이 포맷을 사용하면 커밋 시간을 Date로 파싱할 수 있으며, JSON으로 직렬화할 때도 Jackson의 date 직렬화 설정으로 제어할 수가 있다.

12.16.3. Customize Dependency Versions

spring-boot-dependencies POM에서는 공통 의존성 버전들을 관리하고 있다. 메이븐과 그래들 전용 스프링 부트 플러그인을 이용하면, 여기서 관리하고 있는 의존성 버전들을 빌드 프로퍼티를 통해 커스텀할 수 있다.

스프링 부트는 매번 미리 정해둔 써드 파티 의존성 셋에 맞춰 설계하고 테스트해서 릴리즈된다. 버전을 재정의하게 되면 호환성 문제가 발생할 수도 있다.

메이븐으로 의존성 버전을 재정의하려면 메이븐 플러그인 문서에 있는 섹션을 참고해라.

그래들로 의존성 버전을 재정의하려면 그래들 플러그인 문서에 있는 섹션을 참고해라.

12.16.4. Create an Executable JAR with Maven

spring-boot-maven-plugin은 실행 가능한executable “fat” JAR를 생성할 때도 활용할 수 있다. spring-boot-starter-parent POM을 사용고 있다면, 아래와 같이 플러그인을 선언하면 jar가 리패키징될 거다:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

이 플러그인은 부모 POM을 사용하지 않을 때도 쓸 수 있다. 단, 다음과 같이 <executions> 섹션을 따로 추가해야 한다:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>{spring-boot-version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

전체 사용 가이드는 플러그인 문서를 확인해봐라.

12.16.5. Use a Spring Boot Application as a Dependency

war 파일과 마찬가지로 스프링 부트 애플리케이션은 의존성으로 사용할 용도로 만들지는 않는다. 스프링 부트 애플리케이션 안에 다른 프로젝트와 공유하려는 클래스들이 들어 있을 때는, 그 코드를 별도 모듈로 이동시키는 걸 권장한다. 그러면 현재 애플리케이션과 다른 프로젝트에서 이 별도 모듈을 의존할 수 있다.

위에서 말한 권장 방식대로 코드를 재배치하기 힘들 때는, 반드시 스프링 부트의 메이븐/그래들 플러그인을 설정해서 의존성으로 사용하기 적합한 별도 아티팩트를 생성하도록 만들어 줘야 한다. 실행 가능한executable jar 포맷을 사용하면 애플리케이션 클래스들을 BOOT-INF/classes로 패키징하기 때문에, 실행 가능한executable 아카이브를 의존성으로 사용할 수는 없다. 의존성에 실행 가능한executable jar를 선언하면 클래스들을 찾을 수 없다는 뜻이다.

의존성으로 사용할 수 있는 아티팩트와 실행할 수 있는 아티팩트를 나눠서 따로 두 개를 생성하려면 반드시 classifier를 지정해줘야 한다. 이 classifier는 실행 가능한executable 아카이브의 이름에 적용되며, 의존성으로 사용할 디폴트 아카이브는 그대로 남겨둔다.

메이븐에서 exec classifier를 설정하려면 아래와 같이 작성해주면 된다:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
    </plugins>
</build>

12.16.6. Extract Specific Libraries When an Executable Jar Runs

실행 가능한executable jar에 중첩돼 있는 라이브러리들은 대부분 압축을 풀지 않아도 실행할 수 있다. 하지만 일부 라이브러리에선 문제가 생길 수도 있다. 예를 들어, JRuby는 자체적으로 jar 중첩을 지원하고 있어서, 항상 jruby-complete.jar라는 파일을 직접 사용할 수 있다고 가정한다.

이런 문제가 있는 라이브러리를 처리할 때는, 실행 가능한executable jar를 처음 실행할 때 중첩돼 있는 특정 jar는 자동으로 압축을 풀도록 플래그를 지정하면 된다. 이렇게 중첩돼 있는 jar는 시스템 프로퍼티 java.io.tmpdir로 식별하는 임시 디렉토리에 작성된다.

어플리케이션이 실행 중일 때 운영 체제에서 임시 디렉토리에 압축을 풀어둔 jar를 삭제하도록 설정하지는 않았는지 반드시 확인해봐야 한다.

예를 들어, 메이븐 플러그인을 이용해 JRuby는 압축을 풀어야 한다는 플래그를 지정할 때는 아래 설정을 추가하면 된다:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <requiresUnpack>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                    </dependency>
                </requiresUnpack>
            </configuration>
        </plugin>
    </plugins>
</build>

12.16.7. Create a Non-executable JAR with Exclusions

실행 가능한executable jar와 실행 불가능한non-executable jar를 별도로 나눠서 빌드할 때는 보통, 실행 가능 버전에는 라이브러리 jar에선 필요하지 않은 추가 설정 파일이 들어간다. 예를 들어 application.yml 설정 파일은 실행할 수 없는 JAR에선 제외시켜도 된다.

메이븐에선 실행 가능한executable jar를 반드시 메인 아티팩트로 다뤄야 하며, 다음과 같이 라이브러리를 위한 jar를 별도로 분리시킬 수 있다:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <id>lib</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>lib</classifier>
                        <excludes>
                            <exclude>application.yml</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

12.16.8. Remote Debug a Spring Boot Application Started with Maven

메이븐으로 실행시킨 스프링 부트 애플리케이션에 원격 디버거를 연결하려면 메이븐 플러그인jvmArguments 프로퍼티를 이용하면 된다.

자세한 내용은 이 예제를 참고해라.

12.16.9. Build an Executable Archive from Ant without Using spring-boot-antlib

Ant로 빌드하려면 의존성을 모아 컴파일한 다음 jar나 war 아카이브를 만들어야 한다. 실행 가능한executable 파일을 만들려면 spring-boot-antlib 모듈을 이용하거나 아래 가이드대로 따라하면 된다:

  1. jar를 빌드한다면 중첩되어 있는 BOOT-INF/classes 디렉토리로 애플리케이션의 클래스와 리소스들을 패키징해라. war를 빌드하고 있다면, 평소대로 중첩된 WEB-INF/classes 디렉토리에 애플리케이션의 클래스를 패키징해라.
  2. jar에선 중첩된 BOOT-INF/lib 디렉토리에, war에선 WEB-INF/lib에 런타임 의존성을 추가해라. 이 아카이브에 있는 항목들은 압축하지 않는다는 걸 명심해라.
  3. jar에선 중첩된 BOOT-INF/lib 디렉토리에, war에선 WEB-INF/lib-providedprovided (임베디드 컨테이너) 의존성을 추가해라. 이 아카이브에 있는 항목들은 압축하지 않는다는 걸 명심해라.
  4. 아카이브의 루트에 spring-boot-loader 클래스들을 추가해라 (Main-Class를 사용할 수 있도록).
  5. manifest의 Main-Class 속성에 적절한 런처(jar 파일에선 JarLauncher)를 사용하고, 필요한 다른 프로퍼티들도 manifest 항목으로 지정해라 (보통 Start-Class 속성을 이용한다).

다음은 Ant를 사용해 실행 가능한executable 아카이브를 빌드하는 방법을 보여주는 예시다:

<target name="build" depends="compile">
    <jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
        <mappedresources>
            <fileset dir="target/classes" />
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="src/main/resources" erroronmissingdir="false"/>
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="${lib.dir}/runtime" />
            <globmapper from="*" to="BOOT-INF/lib/*"/>
        </mappedresources>
        <zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
        <manifest>
            <attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
            <attribute name="Start-Class" value="${start-class}" />
        </manifest>
    </jar>
</target>

전체 목차는 여기에 있습니다.

<< >>

TOP