Java Lambda 함수의 "ClassNotFoundException" 오류를 해결하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2020년 2월 28일

Java로 작성된 AWS Lambda 함수를 실행하면 "ClassNotFoundException" 또는 "NoSuchMethodError" 오류가 발생합니다. 이러한 문제를 해결하려면 어떻게 해야 합니까?

간략한 설명

Java 런타임에서 완전히 정규화된 이름(클래스 이름이 패키지)으로 클래스를 로드하려는데 클래스를 찾지 못하면 "ClassNotFoundException" 오류가 발생합니다. 참조된 종속성 버전이 패키지 버전과 다를 경우 런타임에서 "NoSuchMethodError" 오류가 발생합니다.

Java 함수 배포 패키지 구조에 대한 자세한 내용은 Java 함수에 대한 ZIP 배포 패키지 생성을 참조하십시오.

해결 방법

Java Lambda 함수 배포 패키지의 구조 및 내용을 검토하여 오류의 원인을 확인합니다. zipinfo를 사용하여 빌드 시스템의 출력 Java 파일을 보는 것이 좋습니다. 또는 다음 중 하나를 수행하여 패키지를 다운로드할 수 있습니다.

  • AWS 명령줄 인터페이스(AWS CLI)에서 Lambda get-function 명령을 실행합니다. 명령 출력에는 파일을 다운로드하는 데 사용할 수 있는 미리 서명된 URL이 표시됩니다. 자세한 내용은 Lambda 함수 검색을 참조하십시오.
    참고: 이 옵션을 사용하는 경우 출력에서 함수 핸들러의 값에 대한 구성도 확인합니다. 다음 단계에 이 값이 필요합니다.
  • Lambda 콘솔의 [Functions page(함수 페이지)]에서 함수를 선택합니다. [Actions(작업)]를 선택한 다음 [Export function(함수 내보내기)]을 선택합니다. [Export your function(함수 내보내기)] 대화 상자에서 [Download deployment package(배포 패키지 다운로드)]를 선택합니다.

다음 문제 중 하나를 찾습니다. 문제를 식별하고 해결한 후에는 Lambda 함수를 수동으로 번들링하고 업로드합니다. 그런 다음 여전히 오류가 발생하는지 확인합니다.

함수 핸들러 메서드 이름 확인

다음 중 하나를 수행하여 Lambda 함수 핸들러의 이름을 확인합니다.

자세한 내용은 Java에서 AWS Lambda 함수 핸들러를 참조하십시오.

배포 패키지 구조 보기

다음 명령을 실행하여 Lambda 함수 배포 패키지의 파일 구조를 확인합니다.

참고: 이 명령은 Linux/Unix/macOS 시스템에 대해서만 유효합니다. my-deployment-package.zip을 배포 패키지의 파일 이름으로 바꿉니다.

$ zipinfo my-deployment-package.zip

CI/CD 파이프라인 사용 시 문제 확인

지속적 통합 및 지속적 전달(CI/CD) 파이프라인을 사용하여 함수를 패키징하고 배포하는 경우 다음을 확인합니다.

  • 함수를 패키징할 때 필요한 모든 종속성이 번들링되었습니다.
  • 참조된 모든 종속성 버전이 정확합니다.
  • Amazon Simple Storage Service(Amazon S3) 버킷 소스를 사용하고 버킷 버전 관리가 활성화된 경우 S3 버킷 URL이 존재하며 파일의 최신 버전을 가리킵니다.
  • 코드 변경 사항은 핸들러 구성 변경을 배포하기 전에 배포되었습니다. (Lambda에는 하나의 원자성 변경으로 코드 및 구성을 업데이트하는 메커니즘이 없습니다.)

클래스 파일 문제 확인

"ClassNotFoundException" 오류에 이름이 명시된 클래스에 대해 다음을 확인합니다.

  • 배포 패키지에 포함되어 있습니다. 클래스를 찾을 수 없는 경우 배포 패키지를 생성할 때 번들링되지 않았을 수 있습니다.
  • 번들 클래스 이름은 함수의 핸들러 값과 동일합니다. 예를 들어 함수 핸들러 값이 com.amazonaws.lambda.demo.LambdaFunctionHandler”인 경우 Lambda는 함수 디렉터리 "/com/amazonaws/demo/"에 "LambdaFunctionHandler.class"라는 클래스 이름을 기대합니다. 자세한 내용은 Java에서 AWS Lambda 함수 핸들러를 참조하십시오.
  • 이는 /lib 또는 루트 디렉터리에 있습니다.
  • 위치는 Java CLASSPATH 환경 변수에 지정됩니다.
  • Lambda 계층으로 참조되는 경우 해당 콘텐츠가 java/lib 이외의 디렉터리로 추출되지 않았습니다.
  • 함수와 함께 패키징된 클래스와 동일한 버전입니다. 그렇지 않은 경우 로컬 시스템에 패키징된 버전과 다른 버전이 있는지 확인합니다.

Java 함수 패키징에 대한 자세한 내용은 Java의 AWS Lambda 배포 패키지를 참조하십시오.

JAR 파일 문제 확인

함수가 로컬 시스템에서 예상대로 실행되는지 또는 AWS Serverless Application Model(AWS SAM) 애플리케이션에서 실행되는지 확인합니다. 함수가 Lambda에서 호출할 때만 실패할 경우 참조된 종속성(JAR 파일)에 문제가 있을 수 있습니다.

팁: Eclipse IDE(통합 개발 환경)를 사용하여 Java Lambda 함수를 빌드하는 것이 좋습니다. Eclipse에서 사용할 수 있는 플러그인을 활용하여 프로젝트를 생성하면 적절한 빌드에 맞게 프로젝트가 자동으로 구성됩니다. 자세한 내용은 AWS Toolkit for Eclipse로 Lambda 사용을 참조하십시오.

로컬 디렉터리에 있고 Java CLASSPATH 환경 변수에 지정된 JAR 파일에 대해 다음을 확인합니다.

  • 파일은 함수의 배포 패키지에 포함되어 있습니다. 참조된 JAR 파일을 찾을 수 없는 경우 배포 패키지를 생성할 때 번들링되지 않았을 수 있습니다.
  • 파일 버전은 배포 패키지의 파일과 동일합니다.

파일이 없거나 버전이 잘못된 경우 모든 종속성(JAR 파일)을 /lib 또는 루트 디렉터리에 복사합니다. 올바른 버전을 참조해야 합니다. 그런 다음 압축된 콘텐츠를 업로드합니다.

참고: Apache Maven 또는 Gradle과 같은 빌드 도구를 사용하는 경우 배포 아티팩트를 빌드할 때 필요한 모든 플러그인(예: Apache Maven Shade 플러그인)을 사용하여 필요한 모든 종속성을 번들링해야 합니다.

Java 함수 패키징에 대한 자세한 내용은 Java의 AWS Lambda 배포 패키지를 참조하십시오.

권한 문제 확인

Lambda는 zip 패키지 파일에 전역 읽기 권한이 있어야 합니다. 자세한 내용은 배포 패키지를 업로드할 때 Lambda "permission denied(권한 거부됨)" 또는 "unable to import module(모듈을 가져올 수 없음)" 오류를 해결하려면 어떻게 해야 합니까?를 참조하십시오.