개발/Spring

Spring Boot & Maven Scope (compile, provided, runtime 등 차이점)

피터JK 2025. 2. 13. 16:22
728x90

Maven에서 scope는 특정 의존성이 컴파일, 실행, 테스트, 패키징 과정에서 어떻게 동작하는지를 결정합니다. scope에는 다음과 같은 옵션이 있습니다:

  1. compile (기본값)
  2. provided
  3. runtime
  4. test
  5. system
  6. import

아래에서 각각을 자세히 설명하겠습니다.


1. compile (기본값)

  • 설명: 기본 설정으로, 컴파일, 실행, 테스트, 패키징 시 모두 포함되는 가장 일반적인 스코프입니다.
  • 특징:
    • 컴파일 시 필요하며, 패키징된 결과물에도 포함됨.
    • 모든 단계(컴파일, 테스트, 런타임)에서 사용 가능.
  • 사용 예시:
    • 일반적인 유틸리티 라이브러리 (commons-lang3, gson 등)
    • Spring Core 및 일반적인 애플리케이션 라이브러리
  • 예제 (Maven):
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>
    
    (별도 scope 지정이 없으면 기본값 compile이 적용됨.)

2. provided

  • 설명: 컴파일 시에는 필요하지만 실행 시에는 컨테이너(Tomcat, WildFly, JBoss 등)에서 제공되므로 패키징에는 포함되지 않는 스코프.
  • 특징:
    • 컴파일 시 포함되지만, 패키징 결과물에는 포함되지 않음.
    • 컨테이너가 실행 시 필요한 라이브러리를 제공하는 경우 사용.
  • 사용 예시:
    • javax.servlet-api (Tomcat, Jetty 등에서 실행 시 제공됨)
    • Spring Boot WAR 배포 시 spring-boot-starter-tomcat
  • 예제 (Maven):
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
    (패키징된 WAR 파일에는 포함되지 않으며, Tomcat이 실행 시 제공함.)

3. runtime

  • 설명: 컴파일 시에는 필요하지 않지만, 실행 시 필요한 라이브러리.
  • 특징:
    • 컴파일 시에는 필요 없음 (compile classpath에는 없음).
    • 실행 시 (runtime classpath)에는 포함됨.
    • 패키징할 때 JAR/WAR에 포함됨.
  • 사용 예시:
    • JDBC 드라이버 (mysql-connector-java, postgresql 등)
    • SLF4J, Logback 같은 로깅 라이브러리
  • 예제 (Maven):
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
        <scope>runtime</scope>
    </dependency>
    
    (컴파일 시 필요 없지만, 실행 시 데이터베이스 연결을 위해 포함됨.)

4. test

  • 설명: 오직 테스트 코드를 실행할 때만 필요한 의존성.
  • 특징:
    • 일반 코드에서는 사용 불가능 (test classpath에서만 동작).
    • mvn test 실행 시만 로드됨.
  • 사용 예시:
    • JUnit, Mockito, AssertJ 등의 테스트 프레임워크
  • 예제 (Maven):
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
    
    (JAR 파일을 만들 때 포함되지 않으며, 테스트 실행 시에만 사용됨.)

5. system

  • 설명: system 스코프는 로컬 파일 시스템에 존재하는 JAR 파일을 직접 지정하는 방식으로, 거의 사용되지 않음.
  • 특징:
    • 컴파일 및 실행 시 포함되지만, 리모트 저장소(Maven Repository)에서 다운로드되지 않음.
    • 반드시 <systemPath>를 사용해야 함.
    • Maven이 라이브러리를 자동으로 관리하지 않으므로 유지보수가 어려움.
  • 사용 예시:
    • 네트워크가 차단된 환경에서 특정 JAR을 직접 사용해야 할 때.
  • 예제 (Maven):
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>custom-library</artifactId>
        <version>1.0</version>
        <scope>system</scope>
        <systemPath>${project.basedir}/libs/custom-library.jar</systemPath>
    </dependency>
    
    (지정된 libs/custom-library.jar 파일을 직접 참조함.)

6. import

  • 설명: BOM(Bill of Materials)을 가져올 때 사용하는 특수한 스코프.
  • 특징:
    • <dependencyManagement> 내부에서만 사용 가능.
    • 직접 의존성을 추가하는 것이 아니라, 다른 의존성의 버전 관리를 중앙에서 통제하는 용도로 사용.
  • 사용 예시:
    • Spring Boot가 제공하는 BOM을 사용하여 버전을 자동으로 관리할 때.
  • 예제 (Maven):
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.0</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    (BOM을 가져와서 해당 버전에 맞는 라이브러리 버전을 자동으로 적용함.)

scope 비교표

Scope  컴파일 시 포함  실행 시 포함  패키징 포함  사용 예시
compile 일반 라이브러리 (commons-lang3)
provided ❌ (컨테이너 제공) Servlet API, Tomcat 관련 라이브러리
runtime JDBC 드라이버, 로깅 라이브러리
test ❌ (테스트 전용) JUnit, Mockito
system ✅ (로컬 JAR 사용) 직접 지정한 JAR 파일
import ❌ (BOM 관리 전용) Spring Boot BOM

언제 어떤 scope를 사용해야 할까?

  1. 일반 라이브러리 → compile (기본값)
  2. 컨테이너 제공 라이브러리 → provided
  3. JDBC 드라이버, 실행 시만 필요한 라이브러리 → runtime
  4. 테스트 전용 라이브러리 → test
  5. 로컬 JAR 직접 지정 (거의 사용 안 함) → system
  6. BOM(Bill of Materials) 사용 → import

결론

Maven scope는 빌드 및 실행 환경을 효율적으로 관리하는 데 매우 중요합니다. compile이 기본값이지만,
컨테이너 실행 환경인지, 독립 실행 환경인지, 실행 시 필요한지 여부에 따라 적절한 scope를 선택하는 것이 핵심입니다. 

728x90