Ubuntu 환경에서 Spring Boot 프로젝트 jar 파일 빌드하기 Caused by: java.lang.ClassNotFoundException: main class 에러

루리·2023년 7월 26일
1

SpringBoot

목록 보기
1/2
post-thumbnail

Ubuntu 환경에서 Spring Boot 프로젝트를 빌드하는 것은 매우 간단하다.

나는 wsl을 사용해서 로컬에 있는 프로젝트를 간단하게 사용할 수 있었다.
예를 들어, D:Drive에 있는 test-project라는 이름으로 이동하고 싶다면

cd /mnt/d/test_project

매우 간단하다.

IntelliJ에서 jar 파일 빌드하기
IntelliJ에서 간단한 Java 프로젝트를 빌드해서 jar 파일로 wsl에서 실행 시켜 보았다.

Spring Boot 프로젝트를 만들고,
wsl에서 같은 방식으로 빌드해보았다.

빌드하기

일단 처음에는 권한이 없기 때문에 슈퍼 권한을 주고

chmod 777 gradlew

프로젝트를 빌드하고

./gradlew clean build

실행!

java -jar 프로젝트명-0.0.1-SNAPSHOT.jar

근데 안 된다.
(IntelliJ에서는 당연히 됨)

Caused by: java.lang.ClassNotFoundException: main class

어라..?

java -cp 프로젝트명-0.0.1-SNAPSHOT.jar com.패키지.패키지.이름Application

Caused by: java.lang.ClassNotFoundException: main class

엥?

Ubuntu와 IntelliJ의 jdk 버전을 맞춰주었다.

Caused by: java.lang.ClassNotFoundException: main class

클래스 이름 대소문자도 확인하고,
각 클래스들 패키지 이름도 확인하고
Application class에 annotation이 붙어있나도 확인했다.

Caused by: java.lang.ClassNotFoundException: main class

ㅎㅎ...

// build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.2'
    id 'io.spring.dependency-management' version '1.1.2'
}

스프링 부트를 최신 버전으로 바꾸고,

// gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip

gradle 버전은 다운그레이드로 변경해줬다.

Caused by: java.lang.ClassNotFoundException: main class

jar 파일을 뜯어서 MainClass가 잘 있는지도 확인해줬다.

Caused by: java.lang.ClassNotFoundException: main class

친구의 도움으로 문자열 인코딩 설정도 다시 줘봤다.

java -jar -Dfile.encoding=UTF-8 프로젝트명-0.0.1-SNAPSHOT.jar
java -jar -Dfile.encoding=EUC_KR 프로젝트명-0.0.1-SNAPSHOT.jar

Caused by: java.lang.ClassNotFoundException: main class

여기까지 한 일주일 걸렸다...

개발자가 된 나에게 기다리는 것은 무수한 악수 요청 대신 무수한 검색 기록 뿐...

당연한 절차로 검색해서 나오는 건 다 해봤다.

프로젝트 오픈은 해야 되니까 파트장님께서 주말 사이에 프로젝트를 다시 만들고, 모든 코드를 복붙하셨다.
근데 된다구요..?ㅠ...

원인 발견

그래서 두개의 jar 파일을 뜯어봤다.
근데 기존 프로젝트에서는 없었던 org 폴더가 있었다.

↓ 기존 프로젝트 ↓

// META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.패키지명.패키지명.프로젝트명Application
Start-Class: com.패키지명.패키지명.프로젝트명Application
Spring-Boot-Version: 3.1.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Build-Jdk-Spec: 17
Implementation-Title: 프로젝트명
Implementation-Version: 0.0.1-SNAPSHOT

↓ 새로 만든 프로젝트 ↓

// META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.패키지명.패키지명.프로젝트명Application
Spring-Boot-Version: 3.1.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Build-Jdk-Spec: 17
Implementation-Title: 프로젝트명
Implementation-Version: 0.0.1-SNAPSHOT

나는 Main-Class가 진짜 스타트 클래스로 잘 되어 있길래 문제가 없는 줄 알았는데,
새로 만들어진 프로젝트에는 org.springframework ~ 가 있었다.
이것이 원인이었구나...! 했지만 난 org 폴더가 없어서 바꿔도 의미가 없었다.

그렇다면 org 폴더는 왜 안 만들어졌을까?

두 프로젝트의 폴더 구조에는 딱 하나의 차이가 있었다.
main과 test의 resources 폴더에 META-INF가 또 있었다.
그리고 MANIFEST도 있었다.

아마 지금까지 프로젝트가 메인 클래스를 찾지 못했던 원인이 이것인 것 같다.
메니페스트가 너무 많아서 이 친구가 혼란에 빠진 것이다.
그 외에도 기타 뭐가 많았는데 다 처음 보는 파일들이라 resources 폴더에서 application.properties 빼고는 다 날려주었다.

너무 오랜만에 봐서 눈물이 날 지경

그럼 MENIFEST가 왜 생겼을까?

아마도... 내가 IntelliJ를 처음 써봐서 초반에
일반 Java 프로젝트를 빌드하는 것을 보면서 시작해서 (복선 회수)
프로젝트를 빌드를 여러가지 방식으로 진행하다보니 시행 착오가 많았고
아마 아티팩트 설정 등을 잘못하고 빌드를 해서 생긴 것 같다.

그리고, CTO님께서도 도움을 주셨는데
IntelliJ 안에서 gradle을 더블 클릭해서 build 하는 방식은
jar 파일 안에 PATH가 다수 꼬여있던 것을 발견하여
해당 방식은 지양하고 직접 cmd 창에서 build하는 방식을 추천해주셨다.

아무튼 오늘도 해결 완료!

profile
안녕하세요

1개의 댓글

comment-user-thumbnail
2023년 7월 27일

정리가 잘 된 글이네요. 도움이 됐습니다.

답글 달기