반응형
pom.xml에 의존성(Dependency)을 추가할 때, 우리는 종종 <scope> 태그를 생략하거나, 관성적으로 test만 사용하곤 합니다. 하지만 이 <scope> 태그를 얼마나 정확하게 이해하고 사용하느냐에 따라, 최종 빌드 결과물(JAR, WAR 파일)의 크기가 달라지고, 예기치 못한 배포 환경 에러를 막을 수 있습니다.
오늘은 Maven 의존성 스코프(Scope) 의 정확한 의미와, 각 스코프를 언제 어떻게 사용해야 하는지에 대한 디테일한 팁을 알아보겠습니다.
의존성 스코프란? "이 라이브러리, 언제 필요한가요?"
스코프는 해당 의존성이 언제, 어떤 단계의 클래스패스(Classpath)에 포함될지를 정의하는 규칙입니다. 즉, "이 라이-브러리는 컴파일할 때만 필요한가? 실행할 때도 필요한가? 아니면 테스트할 때만 필요한가?"를 메이븐에게 알려주는 것이죠.
가장 좋은 비유는 가구 DIY 키트를 조립하는 것입니다. 🪑
- compile 스코프: 조립에 필요한 핵심 부품 (나사, 나무판자). 최종 완성품에 당연히 포함되어야 합니다.
- provided 스코프: 조립에 필요한 도구 (전동 드릴). 조립 과정(컴파일)에서는 반드시 필요하지만, 완성된 가구(배포 결과물)를 배송할 때 전동 드릴까지 함께 보내지는 않습니다.
- runtime 스코프: 완성된 가구를 실제로 사용할 때 필요한 물건 (의자 다리 밑에 붙이는 흠집 방지 스티커). 조립(컴파일)할 때는 필요 없지만, 실제 사용(런타임) 시에는 필요합니다.
- test 스코프: 가구가 튼튼한지 품질 검사할 때만 필요한 도구 (내구성 테스트용 고무망치). 조립이나 실제 사용 시에는 전혀 필요 없습니다.
각 스코프(Scope) 상세 분석
1. compile (기본값)
- 언제? 컴파일, 테스트, 실행 등 모든 단계에서 필요하다.
- 결과물 포함? 예 (Yes). 최종 WAR/JAR 파일에 포함됩니다.
- 설명: 스코프를 생략하면 자동으로 compile이 됩니다. 대부분의 라이브러리(Spring-web, Lombok, Jackson 등)가 여기에 해당합니다.
- 예시:
-
XML
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2. provided
- 언제? 컴파일과 테스트 시에만 필요하다.
- 결과물 포함? 아니요 (No).
- 설명: "이 라이브러리는 개발할 때는 필요한데, 최종 배포 환경에는 이미 존재하니까 패키징할 때는 빼 줘!" 라는 의미입니다. 톰캣(Tomcat) 같은 웹 애플리케이션 서버(WAS)가 이미 제공하는 Servlet API (javax.servlet-api)가 가장 대표적인 예입니다. Lombok 역시 컴파일 시에만 바이트코드를 조작해주고, 실제 실행 시에는 필요 없으므로 provided로 설정하는 경우가 많습니다.
- 예시:
-
XML
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
3. runtime
- 언제? 테스트와 실행 시에만 필요하다. 컴파일 시에는 필요 없다.
- 결과물 포함? 예 (Yes).
- 설명: "코드 자체는 표준 인터페이스(JDBC)를 보고 짰는데, 실제 실행될 때는 이 구현체가 필요해" 라는 의미입니다. JDBC 드라이버(mysql-connector-java 등)가 완벽한 예시입니다. 코드에서는 java.sql.Driver 인터페이스만 참조하므로 컴파일 시에는 드라이버 자체가 없어도 되지만, 실제 실행 시에는 해당 DB에 맞는 구현체가 클래스패스에 있어야 합니다.
- 예시:
-
XML
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
4. test
- 언제? 오직 테스트 컴파일 및 실행 시에만 필요하다.
- 결과물 포함? 아니요 (No).
- 설명: JUnit, Mockito처럼 테스트 코드에서만 사용되는 라이브러리를 위한 스코프입니다. 이 스코프로 지정하면 메인 코드 컴파일이나 최종 패키징에는 전혀 영향을 주지 않습니다.
- 예시:
-
XML
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency>
마치며
Maven 의존성 스코프를 정확히 사용하는 것은 단순히 pom.xml을 예쁘게 꾸미는 일이 아닙니다. 그것은 빌드 결과물의 크기를 최적화하고, 불필요한 라이브러리 충돌을 막으며, 배포 환경의 특성을 명확하게 이해하고 있다는 것을 보여주는 프로 개발자의 디테일입니다.
이제부터 새로운 의존성을 추가할 때는 잠시 멈추고 질문해 보세요. "이 라이브러리, 정말 모든 곳에 필요한 핵심 부품일까, 아니면 특정 상황에만 필요한 도구일까?" 이 작은 고민 하나가 당신의 프로젝트를 훨씬 더 견고하고 전문적으로 만들어 줄 것입니다. ✨
반응형