DevLog/Java
Gradle 의존성 정리
archive-log
2025. 4. 25. 22:13
implementation, api, compileOnly, runtimeOnly 차이?
이름만 보고 쓰기엔 헷갈려서 정리해두기로 했다.
✅ 기본 개념 요약
키워드 | 상황 | 컴파일 시 포함 | 실행 시 포함 | 다른 모듈에서 사용 |
implementation | 내부 구현용. 외부에는 노출하지 않음 | ✅ | ✅ | ❌ |
api | 외부에 노출되는 라이브러리 | ✅ | ✅ | ✅ |
compileOnly | 컴파일만 필요. 실행 시엔 없어야 함 | ✅ | ❌ | ❌ |
runtimeOnly | 런타임에만 필요. 컴파일엔 불필요 | ❌ | ✅ | ❌ |
📌 키워드별 설명과 예시
1. implementation
implementation 'org.springframework.boot:spring-boot-starter-web'
- 대부분의 의존성은 이걸로 선언하면 충분하다.
- implementation은 다른 모듈에서 이 모듈을 의존하더라도, 해당 라이브러리는 외부로 노출되지 않는다.
- 따라서 모듈 간 의존성을 최소화하면서 필요한 라이브러리만 사용하는 데 적합하다.
2. api
api 'org.springframework.boot:spring-boot-starter-validation'
- 공통 모듈에서 다른 모듈도 같이 써야 하는 라이브러리에 사용한다.
- api 는 이 모듈을 사용하는 다른 모듈에서도 해당 라이브러리를 함께 사용할 수 있도록 해준다.
- 예를 들어, 공통 모듈에서 spring-boot-starter-validation을 api로 선언해두면,
이를 사용하는 서비스 모듈에서도 별도 선언 없이 @Valid 등을 바로 사용할 수 있다.
- 예를 들어, 공통 모듈에서 spring-boot-starter-validation을 api로 선언해두면,
- 다만, 너무 많은 의존성을 api로 노출하면 모듈 간 의존성이 복잡해지고 유지보수가 어려워질 수 있다.
3. compileOnly
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
- compileOnly는 컴파일 시에는 클래스가 필요하지만, 런타임에 없어야 할 때 사용한다.
- 어노테이션 프로세서 등 컴파일 전용 도구에 적합하다.
- 대표적인 예로 Lombok이 있으며, annotationProcessor와 짝을 이루어 컴파일 타임에 코드 생성 처리를 한다.
- annotationProcessor 설정이 빠지면 빌드는 되지만 실행 시 NoClassDefFoundError가 발생할 수 있다.
- compileOnly를 implementation으로 쓰면 배포 시 불필요한 클래스 포함될 수 있다.
4. runtimeOnly
runtimeOnly 'com.mysql:mysql-connector-j'
- runtimeOnly는 애플리케이션 실행 시 필요한 라이브러리를 명시한다.
- 대표적인 예로 JDBC 드라이버가 있으며, 컴파일될 때는 인터페이스만 존재, 실제 DB 통신 구현체는 런타임에 주입된다.
- 테스트 환경에서는 H2, 운영환경에서는 MySQL을 쓰는 구조에도 적합하다.
- runtimeOnly를 빼먹으면 실행 시 ClassNotFoundException 발생할 수 있다.