본문 바로가기
Computer/Android&iOS

Android Gradle 빌드 에러 해결: Duplicate class org.jetbrains.annotations

by ywlee 2025. 10. 13.


 문제 상황

  Android 프로젝트를 빌드할 때 다음과 같은 에러가 발생했습니다:

  Caused by: java.lang.RuntimeException: Duplicate class org.jetbrains.annotations.Nls
  found in modules
    - annotations-23.0.0.jar -> annotations-23.0.0 (org.jetbrains:annotations:23.0.0)
    - kotlin-gradle-plugin-2.1.0-gradle85.jar -> kotlin-gradle-plugin-2.1.0-gradle85
  (org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0)

  Duplicate class org.jetbrains.annotations.Nls$Capitalization found in modules
    - annotations-23.0.0.jar -> annotations-23.0.0 (org.jetbrains:annotations:23.0.0)
    - kotlin-gradle-plugin-2.1.0-gradle85.jar -> kotlin-gradle-plugin-2.1.0-gradle85
  (org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0)

 


 

에러 분석

  이 에러는 org.jetbrains.annotations 패키지의 클래스들이 두 개의 서로 다른 라이브러리에
  중복으로 포함되어 발생하는 의존성 충돌(Dependency Conflict) 문제입니다.

  - org.jetbrains:annotations:23.0.0
  - org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0 (내부에 동일한 클래스 포함)

 


문제 원인 찾기

1. 의존성 트리 확인

  먼저 어디서 충돌이 발생하는지 확인하기 위해 의존성 트리를 검색했습니다:

  ./gradlew :app:dependencies --configuration debugRuntimeClasspath | grep
  "kotlin-gradle-plugin"



  2. 전체 프로젝트 검색

  모든 build.gradle.kts 파일에서 kotlin-gradle-plugin을 참조하는 곳을 찾았습니다:

  # 또는 IDE에서 전체 프로젝트 검색

 


  검색 결과:
  - build-logic/convention/build.gradle.kts - 정상 (빌드 로직에서 사용)
  - gradle/libs.versions.toml - 정상 (버전 카탈로그 정의)
  - domain/build.gradle.kts - 문제 발견!

  근본 원인
  domain 모듈에서 사용하는 build.gradle.kts 파일에서 다음과 같이 잘못된 의존성이 추가되어 있었습니다:

  dependencies {
      implementation(projects.core.model)
      implementation(projects.core.util)

      implementation(libs.kotlin.gradlePlugin)  // 문제의 원인! (앱 모듈에 이미 정의되어있음)

      implementation(libs.timber)
      implementation(libs.javax.inject)
  }



왜 문제가 되는가?

kotlin-gradle-plugin은 빌드 스크립트 전용 라이브러리입니다.

  - 올바른 사용처: buildSrc 또는 build-logic 같은 빌드 스크립트 모듈에서 compileOnly로
  사용
  - 잘못된 사용: 앱이나 라이브러리 모듈에서 implementation으로 사용

  kotlin-gradle-plugin은 내부적으로 org.jetbrains.annotations 클래스들을 포함하고 있어,
  런타임 의존성으로 추가하면 다른 라이브러리와 충돌이 발생합니다.

  해결 방법

  domain/build.gradle.kts에서 해당 의존성을 제거했습니다:

  dependencies {
      implementation(projects.core.model)
      implementation(projects.core.util)

      // implementation(libs.kotlin.gradlePlugin)  // 제거!

      implementation(libs.timber)
      implementation(libs.javax.inject)
  }

 


  시도했던 다른 방법들 (실패)

문제 해결 과정에서 다음과 같은 방법들을 시도했으나 효과가 없었습니다:

  1. Packaging 옵션에서 pickFirst 사용 (클로드가 알려줌)

// 효과 없음 (심지어 deprecated 된 기능)
  android {
      packaging {
          resources {
              pickFirst("org/jetbrains/annotations/Nls.class")
              pickFirst("org/jetbrains/annotations/Nls\$Capitalization.class")
          }
      }
  }

  → 이 방법은 패키징 단계의 충돌을 해결하지만, 의존성 해결 단계에서 이미 에러가 발생하므로
   소용없습니다.

 


  2. gradle.properties 설정 변경

  # 효과 없음 (deprecated)

  android.enableDexingArtifactTransform.desugaring=false



  3. ResolutionStrategy로 버전 강제

  // 효과 없음
  configurations.all {
      resolutionStrategy {
          force("org.jetbrains:annotations:23.0.0")
      }
  }


  → 버전 충돌이 아니라 같은 클래스가 두 개의 다른 artifact에 존재하는 문제이므로 해결되지
  않습니다.

  4. Exclude로 의존성 제외

  // 또 다른 문제 발생
  configurations.all {
      exclude(group = "org.jetbrains", module = "annotations")
  }


  → annotations를 완전히 제외하면 Kotlin 컴파일러가 필요한 클래스를 찾지 못해 다른 에러가
  발생합니다:

  Caused by: java.lang.ClassNotFoundException: org.jetbrains.annotations.NotNull

  올바른 kotlin-gradle-plugin 사용법

  kotlin-gradle-plugin은 다음 위치에서만 사용해야 합니다:

  build-logic/convention/build.gradle.kts

  plugins {
      `kotlin-dsl`
  }

  dependencies {
      compileOnly(libs.android.gradlePlugin)
      compileOnly(libs.kotlin.gradlePlugin)  //  <--- compileOnly로 사용
  }



  gradle/libs.versions.toml

  [libraries]
  kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin",
  version.ref = "kotlin" }



  이렇게 정의하고, 빌드 로직에서만 compileOnly로 사용하는 것이 올바른 방법입니다.

 


결론

  - 증상: Duplicate class org.jetbrains.annotations 에러
  - 원인: 앱/라이브러리 모듈에서 kotlin-gradle-plugin을 런타임 의존성으로 추가
  - 해결: 해당 의존성을 제거
  - 교훈: Gradle 플러그인 관련 라이브러리는 빌드 스크립트 모듈에서만 사용해야 함

  디버깅 팁

  비슷한 문제가 발생했을 때 다음 순서로 확인해보세요:

  1. 에러 메시지 확인: 어떤 클래스가 어떤 두 라이브러리에서 중복되는지 확인
  2. 의존성 트리 검색: ./gradlew :module:dependencies --configuration runtimeClasspath
  3. 전체 프로젝트 검색: 의심되는 라이브러리를 모든 build.gradle.kts에서 검색
  4. 잘못된 위치에 추가된 의존성 제거

  특히 -plugin, -compiler, -gradle 같은 이름이 들어간 라이브러리는 일반 앱 모듈에 추가하면
   안 되는 경우가 많으니 주의하세요!