1. 소개

이 예제에서는 mvn spring-boot : run 명령을 통해 Spring Boot 웹 애플리케이션을 시작하는 것과 java -jar 명령을 통해 jar / war 패키지로 컴파일 한 후 실행하는 것의 차이점을 살펴 봅니다.

여기서 Spring Boot 리 패키지 목표 의 구성에 이미 익숙하다고 가정 해 보겠습니다 . 이 주제에 대한 자세한 내용은 Create a Fat Jar App with Spring Boot를 참조하십시오 .

2. 스프링 부트 메이븐 플러그인

Spring Boot 애플리케이션을 작성할 때 Spring Boot Maven 플러그인 은 코드를 빌드, 테스트 및 패키징하는 데 권장되는 도구입니다.

이 플러그인은 다음과 같은 많은 편리한 기능과 함께 제공됩니다.

  • 우리를 위해 올바른 의존성 버전을 해결합니다.
  • 실행 가능한 단일 fat jar / war에 모든 의존성 (필요한 경우 임베디드 애플리케이션 서버 포함)을 패키지 할 수 있으며 다음 작업도 수행합니다.
    • 클래스 경로 구성을 관리하므로 java -jar 명령 에서 -cp 옵션을 건너 뛸 수 있습니다.
    • 이제 패키지 내부에 중첩 된 모든 외부 jar 라이브러리를 찾아로드 하는 사용자 정의 ClassLoader구현 합니다.
    • 자동으로 main () 메소드를 찾아 매니페스트에서 구성하므로 java -jar 명령 에서 기본 클래스를 지정할 필요가 없습니다.

3. Maven으로 분해 된 형태로 코드 실행

웹 애플리케이션을 작업 할 때 Spring Boot Maven 플러그인 의 또 다른 흥미로운 기능인 임베디드 애플리케이션 서버에 웹 애플리케이션을 자동으로 배포하는 기능을 활용할 수 있습니다 .

플러그인에 Tomcat을 사용하여 코드를 실행한다는 것을 알리려면 의존성이 하나만 필요합니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

이제 프로젝트 루트 폴더에서 mvn spring-boot : run 명령을 실행할 때 플러그인은 pom 구성을 읽고 웹 애플리케이션 컨테이너가 필요하다는 것을 이해합니다.

실행중인  실행 MVN 스프링 부팅을 명령 트리거를 아파치 톰캣의 다운로드와 톰캣의 시작을 초기화합니다.

해 보자:

$ mvn spring-boot:run
...
...
[INFO] --------------------< com.baeldung:spring-boot-ops >--------------------
[INFO] Building spring-boot-ops 0.0.1-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.1.3.RELEASE:run (default-cli) > test-compile @ spring-boot-ops >>>
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/tomcat/embed/tomcat-embed-core/9.0.16/tomcat-embed-core-9.0.16.pom
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/tomcat/embed/tomcat-embed-core/9.0.16/tomcat-embed-core-9.0.16.pom (1.8 kB at 2.8 kB/s)
...
...
[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:run (default-cli) @ spring-boot-ops ---
...
...
11:33:36.648 [main] INFO  o.a.catalina.core.StandardService - Starting service [Tomcat]
11:33:36.649 [main] INFO  o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.16]
...
...
11:33:36.952 [main] INFO  o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
...
...
11:33:48.223 [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
11:33:48.289 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''
11:33:48.292 [main] INFO  org.baeldung.boot.Application - Started Application in 22.454 seconds (JVM running for 37.692)

로그에 'Started Application'이 포함 된 줄이 표시되면 http : // localhost : 8080 / 주소에서 브라우저를 통해 웹 애플리케이션을 쿼리 할 준비가 된 것입니다.

4. 독립 실행 형 패키지 애플리케이션으로 코드 실행

개발 단계를 통과하고 애플리케이션을 프로덕션 단계로 진행하려면 애플리케이션을 패키징해야합니다.

불행히도 jar 패키지 로 작업하는 경우 기본 Maven 패키지 목표에는 외부 의존성이 포함되지 않습니다.

이것은 우리가 더 큰 프로젝트에서 라이브러리로만 사용할 수 있음을 의미합니다.

이러한 제한을 피하려면 Maven Spring Boot 플러그인 리 패키지 목표를 활용하여 jar / war를 독립형 애플리케이션으로 실행해야합니다.

4.1. 구성

일반적으로 빌드 플러그인 만 구성하면됩니다.

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

그러나 예제 프로젝트에는 둘 이상의 기본 클래스가 포함되어 있으므로 플러그인을 구성하여 실행할 클래스를 Java에 알려야합니다.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.baeldung.webjar.WebjarsdemoApplication</mainClass>
            </configuration>
        </execution>
    </executions>
</plugin>

또는 start-class 속성 을 설정하여  :

<properties>
    <start-class>com.baeldung.webjar.WebjarsdemoApplication</start-class>
</properties>

4.2. 응용 프로그램 실행

이제 두 가지 간단한 명령으로 예제 전쟁을 실행할 수 있습니다.

$ mvn clean package spring-boot:repackage
$ java -jar target/spring-boot-ops.war

jar 파일을 실행하는 방법에 대한 자세한 내용은 Run JAR Application With Command Line Arguments 문서에서 찾을 수 있습니다 .

4.3. 전쟁 파일 내부

위에서 언급 한 명령이 전체 서버 애플리케이션을 실행하는 방법을 더 잘 이해하기 위해 spring-boot-ops.war을 살펴볼 수 있습니다.

압축을 풀고 내부를 들여다 보면 일반적인 용의자를 찾습니다.

  • META-INF , 자동 생성 된  MANIFEST.MF 포함
  • WEB-INF / classes , 컴파일 된 클래스 포함
  • WEB-INF / lib- 전쟁 의존성 및 임베디드 Tomcat jar 파일을 보유합니다.

팻 패키지 구성에 특정한 폴더가 있기 때문에 그게 전부는 아닙니다.

  •  WEB-INF / lib-provided , 임베디드 실행시 필요하지만 배포시 필요하지 않은 외부 라이브러리 포함
  • org / springframework / boot / loader- Spring Boot 커스텀 클래스 로더를 보유합니다.이 라이브러리는 외부 의존성을로드하고 런타임에서 액세스 할 수 있도록합니다.

4.4. 전쟁 매니페스트 내부

앞서 언급했듯이 Maven Spring Boot 플러그인은 기본 클래스를 찾고 java 명령 을 실행하는 데 필요한 구성을 생성합니다 .

결과 MANIFEST.MF 에는 몇 가지 추가 행이 있습니다.

Start-Class: com.baeldung.webjar.WebjarsdemoApplication
Main-Class: org.springframework.boot.loader.WarLauncher

특히 마지막 것은 사용할 Spring Boot 클래스 로더 런처를 지정하는 것을 볼 수 있습니다.

4.5. Jar 파일 내부

기본 패키징 전략으로 인해 전쟁 패키징 시나리오는 Spring Boot Maven Plugin 사용 여부에 관계없이 크게 다르지 않습니다.

플러그인의 장점을 더 잘 이해하기 위해 pom 패키징 구성을 jar로 변경하고 mvn clean package를 다시 실행할 수 있습니다.

이제 우리의 fat jar가 이전 war 파일과 약간 다르게 구성되어 있음을 확인할 수 있습니다.

  • 모든 클래스 및 리소스 폴더는 이제 BOOT-INF / classes 아래에 있습니다.
  • BOOT-INF / lib 는 모든 외부 라이브러리를 보유합니다.

플러그인이 없으면 lib 폴더는 존재하지 않으며 BOOT-INF / classes 의 모든 내용은 패키지의 루트에 있습니다.

4.6. Jar Manifest 내부

또한 매니페스트. MF는 다음과 같은 추가 라인을 특징으로 변경되었습니다.

Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.1.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher

Spring-Boot-ClassesSpring-Boot-Lib 는 클래스 로더가 클래스와 외부 라이브러리를 찾을 위치를 알려주기 때문에 특히 흥미 롭습니다.

5. 선택 방법

도구를 분석 할 때 이러한 도구가 만들어진 목적을 고려하는 것이 중요합니다. 개발을 용이하게하고 싶습니까? 아니면 원활한 배포와 이동성을 보장하고 싶습니까? 이 선택의 영향을 가장 많이받는 단계를 살펴 보겠습니다.

5.1. 개발

개발자로서 우리는 종종 코드를 로컬에서 실행하기 위해 환경을 설정하는 데 많은 시간을 할애하지 않고 코딩에 대부분의 시간을 소비합니다. 간단한 응용 프로그램에서는 일반적으로 문제가되지 않습니다. 그러나 더 복잡한 프로젝트의 경우 환경 변수를 설정하고 서버를 시작하고 데이터베이스를 채워야 할 수 있습니다.

애플리케이션을 실행할 때마다 올바른 환경을 구성하는 것은 매우 비실용적입니다 . 특히 두 개 이상의 서비스를 동시에 실행 해야하는 경우 더욱 그렇습니다.

Maven으로 코드를 실행하면 도움이됩니다. 이미 전체 코드베이스를 로컬로 체크 아웃 했으므로 pom 구성 및 리소스 파일을 활용할 수 있습니다. 환경 변수를 설정하고, 메모리 내 데이터베이스를 생성하고, 올바른 서버 버전을 다운로드하고 하나의 명령으로 애플리케이션을 배포 할 수도 있습니다.

각 모듈에 다른 변수와 서버 버전이 필요한 다중 모듈 코드베이스에서도 Maven 프로필을 통해 적절한 환경을 쉽게 실행할 수 있습니다.

5.2. 생산

우리가 생산으로 더 많이 이동할수록 대화는 안정성과 Security으로 더 많이 이동합니다. 그렇기 때문에 개발 기계에 사용 된 프로세스를 실제 고객이있는 서버에 적용 할 수 없습니다.

이 단계에서 Maven을 통해 코드를 실행하는 것은 여러 가지 이유로 나쁜 습관입니다.

  • 먼저 Maven을 설치해야합니다.
  • 그런 다음 코드를 컴파일해야하기 때문에 전체 JDK (Java Development Kit)가 필요합니다.
  • 다음으로 코드베이스를 서버에 복사하고 모든 독점 코드를 일반 텍스트로 남겨 두어야합니다.
  • MVN 명령은 수명주기의 모든 단계를 실행해야한다 (찾기 소스, 컴파일 및 실행)
  • 이전 포인트 덕분에 우리는 CPU와 클라우드 서버의 경우 돈을 낭비했습니다.
  • Maven은 각각 메모리를 사용하는 여러 Java 프로세스를 생성합니다 (기본적으로 각 프로세스는 상위 프로세스와 동일한 메모리 양을 사용함).
  • 마지막으로 배포 할 서버가 여러 대인 경우 위의 모든 작업이 각 서버에서 반복됩니다.

이것은 응용 프로그램을 패키지로 배송하는 것이 생산에 더 실용적인 이유 입니다.

6. 결론

이 예제에서는 Maven과 java -jar 명령을 통해 코드를 실행하는 것의 차이점을 살펴 보았습니다 . 또한 몇 가지 실제 사례 시나리오에 대한 간략한 개요를 실행했습니다.

이 기사에 사용 된 소스 코드는 GitHub에서 사용할 수 있습니다 .