Theme:

Nexus에 새 버전을 배포했는데 Jenkins 빌드에서 "cannot find symbol" 에러가 나온다면, Maven의 로컬 캐시가 구버전을 참조하고 있을 가능성이 높습니다.

문제 상황

내부에서 개발한 라이브러리의 새 버전(예: 1.1.0-SNAPSHOT)을 Nexus에 배포했음에도, Jenkins 빌드에서 최신 메서드를 찾지 못하고 실패하는 문제가 발생했습니다.

PLAINTEXT
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------

[ERROR] /var/lib/jenkins/workspace/$workspace_name/src/test/java/kr/co/.../.../$ClassName.java:[103,30]
error: cannot find symbol
  symbol:   method connect()
  location: variable connector of type $ClassName

분명히 connect() 메서드를 추가하고 Nexus에 배포했는데, Jenkins 빌드에서 "cannot find symbol" 에러가 발생합니다. 이는 Jenkins가 구버전 라이브러리 캐시 를 참조하고 있을 가능성이 높습니다.

원인 분석

Maven의 로컬 리포지토리 캐싱

Maven은 의존성을 처음 다운로드하면 로컬 리포지토리(~/.m2/repository)에 캐시합니다. 이후 빌드에서는 원격 리포지토리(Nexus)에 다시 요청하지 않고 캐시된 JAR을 사용합니다.

PLAINTEXT
빌드 요청 → Maven이 로컬 캐시 확인 → 캐시에 있으면 그대로 사용 (구버전!)
                                    → 캐시에 없으면 Nexus에서 다운로드

SNAPSHOT 버전의 특수성

SNAPSHOT 버전은 개발 중인 버전으로, 동일 버전(1.1.0-SNAPSHOT)이라도 내용이 계속 변경됩니다. 문제는 Maven이 SNAPSHOT의 갱신 여부를 매번 확인하지 않는다는 점입니다.

상황Maven의 동작
SNAPSHOT 첫 다운로드Nexus에서 다운로드 후 로컬에 캐시
동일 SNAPSHOT 재빌드로컬 캐시 사용 (Nexus 확인 안 함)
Nexus에 새 SNAPSHOT 배포 후 재빌드** 여전히 구버전 캐시 사용**

Jenkins 환경에서의 캐시 경로

Jenkins에서 Maven 빌드를 실행하면, 로컬 리포지토리는 기본적으로 아래 경로에 위치합니다.

PLAINTEXT
/var/lib/jenkins/.m2/repository/

진단 절차

1. pom.xml 의존성 버전 확인

먼저 프로젝트의 pom.xml에서 해당 라이브러리의 버전이 올바른지 확인합니다.

BASH
# Jenkins 워크스페이스의 pom.xml 확인
cat /var/lib/jenkins/workspace/$workspace_name/pom.xml | grep -A 5 "라이브러리명"

2. 캐시된 JAR 파일 확인

로컬 리포지토리에 캐시된 JAR이 최신인지 확인합니다.

BASH
# 캐시된 라이브러리의 타임스탬프 확인
ls -la /var/lib/jenkins/.m2/repository/kr/co/회사명/라이브러리명/1.1.0-SNAPSHOT/

파일의 수정 날짜가 Nexus에 배포한 시점보다 이전이라면, 구버전 캐시가 사용되고 있는 것입니다.

해결 방법

방법 1: 캐시 수동 삭제

해당 라이브러리의 캐시 디렉토리를 직접 삭제합니다.

BASH
rm -rf /var/lib/jenkins/.m2/repository/kr/co/회사명/라이브러리명/1.1.0-SNAPSHOT/

이후 Jenkins Job을 재빌드하면 Nexus에서 최신 버전을 다운로드합니다.

방법 2: Maven -U 옵션 사용

Maven 빌드 시 -U(Update Snapshots) 옵션을 추가하면, SNAPSHOT 의존성을 강제로 원격 리포지토리에서 갱신합니다.

GROOVY
// Jenkinsfile
stage('Build') {
    steps {
        sh 'mvn clean package -U -DskipTests'
    }
}
옵션설명
-USNAPSHOT 의존성을 원격 리포지토리에서 강제 갱신
-DskipTests테스트 스킵 (빌드 속도 향상)

방법 3: pom.xml에 updatePolicy 설정

pom.xml의 리포지토리 설정에서 SNAPSHOT 갱신 정책을 always로 지정하면, 매 빌드마다 자동으로 최신 SNAPSHOT을 확인합니다.

XML
<repositories>
    <repository>
        <id>nexus-snapshots</id>
        <url>http://nexus.example.com/repository/maven-snapshots/</url>
        <snapshots>
            <enabled>true</enabled>
            <updatePolicy>always</updatePolicy>
        </snapshots>
    </repository>
</repositories>

재발 방지 전략

전략설명
Jenkinsfile에 -U 옵션 기본 적용SNAPSHOT 의존성이 있는 프로젝트는 항상 -U 옵션 사용
updatePolicy: always 설정pom.xml에서 SNAPSHOT 리포지토리의 갱신 정책을 always로 설정
Release 버전 사용안정된 라이브러리는 SNAPSHOT 대신 Release 버전으로 배포
빌드 전 캐시 정리 단계 추가파이프라인에 특정 라이브러리 캐시 삭제 스텝 추가

** 핵심:** SNAPSHOT 버전은 개발 편의를 위한 것이지만, CI/CD 환경에서는 캐시 문제를 유발할 수 있습니다. SNAPSHOT 의존성을 사용하는 Jenkins 빌드에는 반드시 -U 옵션을 적용하거나, updatePolicyalways로 설정하는 것을 권장합니다.

댓글 로딩 중...