본문 바로가기
개발/ERROR 모음

ClassNotFoundException vs NoClassDefFoundError 차이와 해결 (원인/대응 총정리)

by chansungs 2026. 2. 6.
728x90
반응형

Java에서 자주 발생하는 ClassNotFoundException과 NoClassDefFoundError의 차이를 정리하고, 각각의 대표 원인과 해결 방법을 체크리스트로 제공합니다. 의존성 누락, 런타임 클래스패스 문제, WAR/JAR 배포 환경, 톰캣 로딩 이슈까지 실무 사례 중심으로 정리했습니다.

 

 

 

 

ClassNotFoundException / NoClassDefFoundError 차이와 해결 (원인/대응 총정리)

자바 프로젝트를 하다 보면 꼭 한 번은 만나게 되는 에러가 있습니다.

  • java.lang.ClassNotFoundException
  • java.lang.NoClassDefFoundError

둘 다 “클래스를 못 찾는다”처럼 보이는데, 의미와 원인/해결 방향이 완전히 다릅니다.
이 글에서는 두 에러의 차이를 실무 기준으로 깔끔하게 정리해보겠습니다.


1. 두 에러의 핵심 차이 한 줄 요약

ClassNotFoundException

“지금 로딩하려고 했는데 클래스패스에서 클래스를 못 찾음” (대부분 클래스패스/의존성 누락)

NoClassDefFoundError

“예전에 로딩/컴파일은 됐는데, 실행 중에 갑자기 클래스 정의를 못 가져옴” (대부분 런타임 환경 문제/의존성 충돌)


2. ClassNotFoundException이란?

ClassNotFoundException은 체크 예외(Exception) 입니다.

보통 아래처럼 동적으로 클래스를 로딩할 때 많이 발생합니다.

 
Class.forName("com.example.Foo");

이때 com.example.Foo가 런타임 클래스패스에 없으면 발생합니다.

✅ 대표 상황

  • 라이브러리(jar)가 아예 빠짐
  • IDE에서는 되는데 서버 배포하면 빠짐 (WAR에 미포함)
  • 클래스명 오타 / 패키지 경로 변경
  • 리플렉션으로 로딩하는 문자열이 잘못됨

3. NoClassDefFoundError란?

NoClassDefFoundError는 이름 그대로 Error 입니다. (예외가 아니라 에러)

뜻은:

JVM이 어떤 클래스를 “이미 로딩하려고 시도했거나 로딩했던 적이 있는데”,
실행 시점에 그 클래스 정의를 사용할 수 없게 됐다.

즉 “클래스가 없다”라기보다, 실행 환경에서 클래스를 정상적으로 사용할 수 없는 상태가 핵심입니다.

✅ 대표 상황

  • A 클래스는 있는데, A가 의존하는 B 클래스가 없음 → 실행 중 터짐
  • 버전 충돌로 메소드/필드가 달라서 로딩 실패
  • 서버(ClassLoader) 격리 문제(톰캣, WAS)
  • static 초기화 블록에서 예외가 터져 로딩 실패 → 이후 NoClassDefFoundError로 보일 수 있음

4. 차이점 비교표

구분ClassNotFoundExceptionNoClassDefFoundError
타입 Exception(체크 예외) Error
발생 시점 클래스 로딩 “시도” 시점 클래스 로딩 실패/정의 사용 불가
흔한 원인 클래스패스에 아예 없음 의존성 누락/버전 충돌/초기화 실패
해결 방향 jar 포함/클래스패스 수정 의존성 트리 정리/버전 충돌 해결/배포 구조 점검

5. 발생 원인 TOP 6 (실무)

원인 1) 의존성(jar) 누락

  • 로컬에서는 있는데 서버 WAR/JAR에 빠짐

✅ 확인: 빌드 산출물에 jar가 포함됐는지


원인 2) 버전 충돌 (가장 흔한 NoClassDefFoundError 원인)

예: A 라이브러리는 commons-logging 1.2를 기대하는데
런타임에는 1.0이 들어가 있다면 로딩 중 실패할 수 있습니다.

✅ 해결: dependency tree 확인

Maven:

 
mvn dependency:tree

Gradle:

 
./gradlew dependencies

원인 3) 톰캣/WAS 클래스 로더 문제

  • WEB-INF/lib에 있어야 할 jar가 서버 공용 lib에 있거나
  • 반대로 서버 lib가 먼저 로딩되어 충돌

✅ 해결:

  • jar를 한 군데로 정리
  • 서버 공용 lib에 넣은 jar는 최소화

원인 4) packaging 문제 (war/jar)

  • war로 배포해야 하는데 jar로 돌리거나, 그 반대
  • provided scope 설정이 꼬여서 배포 산출물에 빠짐

✅ Maven 예: provided 조심

 
<scope>provided</scope>

이걸 걸면 배포물에 포함 안 될 수 있음 (서버가 제공한다고 가정)


원인 5) 빌드/IDE 캐시 꼬임

  • “클래스 파일은 있는데 못 찾음”이라고 느껴질 때 의외로 많음

✅ 해결:

  • Clean / Rebuild
  • IDE 캐시 정리

원인 6) static 초기화 실패 → 이후 NoClassDefFoundError

예:

 
public class Foo { static { // 여기서 예외 터지면 클래스 로딩 실패 int x = 1 / 0; } }

처음 로딩이 실패하면, 이후 참조 시점에 NoClassDefFoundError로 보일 수 있습니다.

✅ 해결: 최초 원인 로그(맨 처음 터진 스택트레이스)부터 확인


6. 해결 체크리스트 (바로 적용)

✅ 1) 로그에서 “진짜 최초 원인” 찾기

  • NoClassDefFoundError는 뒤에 따라오는 2차 증상인 경우가 많음

✅ 2) 빌드 산출물에 jar 포함 확인

  • JAR: BOOT-INF/lib
  • WAR: WEB-INF/lib

✅ 3) dependency tree로 버전 충돌 확인

  • 중복 라이브러리 제거 / 버전 고정

✅ 4) 톰캣 공용 lib vs 앱 lib 충돌 확인

  • 서버 lib에 넣은 jar가 우선 로딩될 수 있음

✅ 5) Clean build / 캐시 삭제 후 재배포

  • “어제 되던게 오늘 안됨”이면 효과 큼

7. 톰캣 배포에서 자주 터지는 케이스 (실무 팁)

  • 운영서버 lib에 오래된 jar가 남아있어 충돌
  • 여러 WAR들이 같은 라이브러리를 서로 다른 버전으로 사용
  • 클래스패스가 꼬여서 어떤 서버에서는 되고 어떤 서버에서는 안됨

✅ 이런 경우 해결은 “정리”가 답:

  • 공용 lib 최소화
  • 애플리케이션별 WEB-INF/lib로 통일
  • 버전 고정(BOM/의존성 관리)

결론

  • ClassNotFoundException: 클래스패스에 아예 없음 → jar 누락/경로/오타 점검
  • NoClassDefFoundError: 로딩/정의 사용 실패 → 의존성 충돌/초기화 실패/배포환경 점검
728x90
반응형