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 등을 바로 사용할 수 있다.
  • 다만, 너무 많은 의존성을 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 발생할 수 있다.

 

 

📚 참고 자료