의존성 충돌

sun·2025년 1월 30일
0

spring

목록 보기
2/2
post-thumbnail

의존성 충돌?
소프트웨어 프로젝트에서 특정 라이브러리나 패키지가 서로 다른 버전의 동일한 라이브러리를 요구할 때 발생하는 문제.
이로 인해 빌드 실패, 런타임 오류 등 예기치 않은 동작이 발생할 수 있음.

✒️ 왜 의존성 충돌이 발생할까?

1. 라이브러리 간 호환성 문제

ex) A라이브러리는 v1.0의 Library X를 요구하고 B라이브러리는 v2.0의 Library X를 요구하는 경우

2. 트랜스티브 의존성(Transitive Dependency)

  • 프로젝트에서 직접 명시하지 않았지만 의존하는 라이브러리A가 다른 라이브러리B를 의존할 때 B가 자동으로 포함되는 의존성
  • 프로젝트에서 직접 참조하지 않는 라이브러리(간접 의존성)가 서로 다른 버전을 요구할 때 발생하는 경우

ex) Spring Boot 프로젝트에서 spring-boot-starter-web을 추가하면 내부적으로 spring-web과 spring-core 같은 라이브러리가 포함됨.
spring-boot-starter-web을 추가했더니 spring-web 5.3.0을 필요로 하고 spring-core 5.3.0도 함께 필요함.
그런데 추가적으로 다른 라이브러리를 사용했는데 spring-core 5.2.0을 필요로 한다면 어떤 버전을 쓸 것인지 충돌 발생

✒️ 의존성 충돌의 증상은?

1. 빌드 오류

"Dependency conflict" 또는 "Duplicate class" 같은 메시지

2. 런타임 오류

ClassNotFoundException, NoSuchMethodError 등

3. 예기치 않은 동작

잘못된 버전의 라이브러리가 로드되어 기능이 올바르게 동작하지 않음

✒️ Gradle의 의존성 충돌 해결 방식

1. Gradle의 충돌 해결 원칙

  • 최신 버전 우선 정책 (Conflict Resolution)
    • Gradle은 의존성 충돌이 발생하면 기본적으로 최신 버전을 선택
  • 의존성 트리 시각화
    • Gradle은 ./gradlew dependencies 명령을 통해 의존성 트리를 시각적으로 보여줌
    • 이를 통해 충돌 원인을 쉽게 파악 가능

2. Gradle의 해결 방법

  • 강제 버전 지정
    • 특정 라이브러리의 버전을 강제로 지정하여 충돌을 해결
configurations.all {
    resolutionStrategy {
        force 'com.example:library:1.2.3'
    }
}
  • Exclusion
    • 트랜스티브 의존성을 제외하여 충돌 방지
implementation('com.example:library') {
    exclude group: 'com.other', module: 'conflicting-library'
}
  • Version Alignment
    • BOM(Bill of Materials) 또는 platform 기능을 사용하여 버전을 통일
    • 여러 라이브러리 버전을 한번에 설정
implementation platform('org.springframework.boot:spring-boot-dependencies:2.5.0')
  • Component Metadata Rules
    • Gradle은 특정 라이브러리의 버전 충돌을 해결하는 사용자 정의 규칙을 설정 가능

✒️ Maven의 의존성 충돌 해결 방식

1. Maven의 충돌 해결 원칙

  • 선행 선언 우선 정책 (Nearest Definition Wins)
    • Gradle은 의존성 충돌이 발생하면 POM 파일에서 먼저 선언된 의존성을 우선으로 선택
    • 의존성이 여러 경로로 포함된 경우, 루트에서 가장 가까운 의존성을 선택
  • 의존성 트리 확인
    • mvn dependency:tree 명령으로 트리를 확인하고 충돌 원인을 파악

2. Maven의 해결 방법

  • Dependency Management (BOM)
    • <dependencyManagement> 태그를 사용하여 버전을 명시적으로 고정
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.7.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
</dependencies>
  • Exclusion
    • 트랜스티브 의존성을 제외하여 충돌 방지
<dependency>
    <groupId>com.example</groupId>
    <artifactId>library</artifactId>
    <version>1.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.other</groupId>
            <artifactId>conflicting-library</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • Enforcer Plugin
    • Maven Enforcer Plugin을 사용하여 의존성 충돌을 검사하고 규칙을 설정
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>enforce-dependency-convergence</id>
            <goals>
                <goal>enforce</goal>
            </goals>
        </execution>
    </executions>
</plugin>
profile
Please, Steadily

0개의 댓글

관련 채용 정보