[Gradle] 적절한 의존성 설정을 통한 빌드 최적화

🌈 m1naworld ·2025년 1월 4일
post-thumbnail

SpringBoot 프로젝트에서 의존성을 설정할 때, build.gradle 파일에서 다양한 의존성을 정의한다. 의존성을 설정하기 위해 검색을 하다 보면 implementation를 통해 의존성을 설정하는 경우도 있고, runtimeOnly를 사용하는 예시도 자주보게 된다.

아니 그래서 차이가 뭐고 언제 무엇을 사용해야 하는 건데??


의존성 설정시 사용되는 configuration에 대해 알아보자!

Gradle의 공식문서에 따르면, Java 라이브러리 플러그인을 사용할 때의 구성이 어떻게 설정되는지 아래와 같이 나타낸다.

  • The configurations in green are the ones a user should use to declare dependencies
  • The configurations in pink are the ones used when a component compiles, or runs against the library
  • The configurations in blue are internal to the component, for its own use

우선 implementation, runtimeOnly, compileOnly, api, compileOnlyApi 는 Gradle에서 의존성을 관리할 때 사용하는 configuration이다.
각 configuration은 의존성의 사용 목적라이프 사이클에 따라 구분되며, 이를 적절히 구분해서 사용하는 것은 프로젝트의 의존성 관리를 효율적으로 하고, 빌드 성능을 최적화하는 데 도움이 된다고 한다.

1. implementation와 api

implementationapi컴파일과 실행시 모두 필요한 라이브러리에 사용되며, 둘의 차이점은 외부 프로젝트의 의존성 전파 유무에 있다.

implementation의존성이 프로젝트 내부에서만 필요하고, 외부에 노출되지 않아도 될 때 사용하는 반면, api프로젝트 내 의존성이 외부에 노출되어야 할 때(Public 메서드와 필드, 상속 등 외부에서 직접 의존성을 사용해야 하는 경우)에 사용된다.

예시) implementation이 적합한 경우

private void doSomethingWithLibraryA() {
    LibraryAType obj = new LibraryAType();
    obj.doSomething();
}

// LibraryAType은 프로젝트 내부에서만 사용되므로, 다른 모듈에서는 LibraryAType이 의존 될 필요가 없다. 

예시) api가 적합한 경우

public List<LibraryBType> getLibraryAObjects() {
    return new ArrayList<>();
}

/* LibraryBType이 public 메서드의 반환 타입으로 노출되어 
프로젝트를 사용하는 다른 모듈에서도 LibraryBType에 의존해야 한다. */ 

📌 핵심 요약

api로 의존성이 노출되면 외부 모듈에서 이를 사용하게 되어 의존성 그래프가 복잡해지고, 컴파일 시 더 많은 클래스패스를 관리해야 한다. 이는 불필요한 리컴파일과 빌드 시간 증가를 초래할 수 있다.
반면, implementation은 의존성을 프로젝트 내에서만 사용하도록 제한하여 더 작은 클래스패스를 유지하고, 불필요한 의존성 검사를 줄여 빌드 시간을 단축시킨다.
따라서 Gradle은 api 보단 implementation 사용을 권장하며, 외부에 노출될 필요가 없는 의존성에는 implementation을 사용하는 것이 효율적이다.

2. runtimeOnly

컴파일 시에는 필요없고, 실행 시에만 필요한 라이브러리를 정의한다. 예를 들어, 데이터베이스 드라이버나 로그 라이브러리처럼 애플리케이션 실행에만 필요한 의존성을 설정할 때 사용된다.

  • 컴파일 시 의존성에 포함되지 않기 때문에 빌드 성능이 향상 될 수 있음
  • 컴파일 타임에 불필요한 의존성 파일을 포함하지 않으므로 빌드 결과물이 더 가벼움
  • 실행 시에만 필요한 라이브러리를 따로 관리할 수 있어 더 깔끔한 의존성 관리를 할 수 있음

3. compileOnly와 compileOnlyApi

컴파일 시에는 필요하지만, 실행 시에는 포함되지 않는 라이브러리를 정의한다. 예를 들어, 어노테이션 처리기나 플러그인 의존성을 설정할 때 사용된다. compileOnly와 compileOnlyApi 또한 의존성 전파 유무의 차이가 있으며, compileOnlyApi는 다른 모듈에서도 컴파일 시 필요하지만, 런타임에는 필요하지 않는 경우에 사용된다.

  • 컴파일 시 의존성을 제공하지만, 런타임에는 포함되지 않으므로 실행 파일이 가벼워짐

마무리

이번 글을 통해 Gradle에서의 의존성 관리 설정인implementation, api, runtimeOnly, compileOnly, compileOnlyApi를 알아보았다. 이를 적절히 활용하면 의존성 관리 효율성 뿐만 아니라 빌드 성능을 최적화할 수 있다. 다음엔 기존 프로젝트에 적용하여 빌드 성능 향상 정도를 확인해 보고, 이를 바탕으로 게시글을 작성 해보고자 한다 🧚‍♀️


Ref.

profile
개발자로 사는 내 삶은 즐거워 👾

0개의 댓글