오류 현상

Gradle을 사용하여 프로젝트를 빌드할 때 다음과 같은 오류가 발생하는 경우가 있습니다.

> Task :compileJava FAILED

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

이 오류는 Gradle과 Java 버전의 불일치 또는 Lombok과 같은 플러그인의 호환성 문제로 인해 발생할 가능성이 큽니다.

 


원인 분석

이 오류는 주로 다음과 같은 원인으로 인해 발생합니다:

  1. Gradle 8.x와 JDK 21의 호환성 문제( Gradle과 Java 버전 불일치)
    • JDK 21에서 javac 내부 API가 변경되었고, Gradle 및 일부 플러그인이 이를 참조하려다 충돌 발생
  2. Lombok과 같은 Annotation Processor 문제
    • Lombok이 JDK 21의 내부 API를 잘못 참조하는 경우

이 문제를 해결하려면 JDK 버전을 확인하고, Gradle이 올바른 JDK를 사용하도록 설정한 후, 필요한 경우 Lombok 등의 플러그인 업데이트를 진행해야 합니다.


✅ 해결 방법

1️⃣ 현재 JDK 버전 확인

java -version

출력 결과 예시:

openjdk version "21.0.1" 2024-01-01

만약 JDK 21이 설치되어 있다면, JDK 17로 변경하는 것이 가장 확실한 해결 방법입니다.

2️⃣ JDK 버전 변경 (JDK 17 권장)

📌 SDKMAN을 사용하는 경우

sdk install java 17.0.9-tem
sdk use java 17.0.9-tem

📌 직접 설치하는 경우

  1. OpenJDK 17 다운로드 후 설치
  2. JAVA_HOME 환경 변수 변경
  3. expo🧐 원인 분석 이 오류는 주로 다음과 같은 원인으로 인해 발생합니다: Gradle 8.x와 JDK 21의 호환성 문제 JDK 21에서 javac 내부 API가 변경되었고, Gradle 및 일부 플러그인이 이를 참조하려다 충돌 발생 Lombok과 같은 Annotation Processor 문제 Lombok이 JDK 21의 내부 API를 잘못 참조하는 경우 Gradle과 Java 버전 불일치 Gradle이 예상하는 JDK 버전과 시스템에서 실행 중인 JDK 버전이 다를 경우 이 문제를 해결하려면 JDK 버전을 확인하고, Gradle이 올바른 JDK를 사용하도록 설정한 후, 필요한 경우 Lombok 등의 플러그인 업데이트를 진행해야 합니다. rt JAVA_HOME=/path/to/jdk-17

3️⃣ Gradle이 올바른 JDK를 사용하도록 설정

gradle.properties 파일에 다음을 추가:

org.gradle.java.home=/path/to/jdk-17

또는 실행 시:

export JAVA_HOME=/path/to/jdk-17
./gradlew build --warning-mode all

4️⃣ Lombok 문제 해결 (사용 중인 경우)

만약 Lombok을 사용하고 있다면, build.gradle에서 최신 버전인지 확인하고, annotationProcessor 설정을 점검합니다.

dependencies {
    annotationProcessor 'org.projectlombok:lombok:1.18.30' // 최신 버전 확인
    compileOnly 'org.projectlombok:lombok:1.18.30'
}

또한, lombok.config 파일에서 javac 관련 설정을 추가할 수도 있습니다.

config.stopBubbling = true

5️⃣ Gradle Wrapper 버전 확인 및 변경

gradle/wrapper/gradle-wrapper.properties 파일에서 Gradle 버전이 8.8 이상인지 확인하고, 필요하면 8.5~8.8로 변경합니다.

distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip

Gradle 9.0은 아직 미리보기 버전이므로 사용하지 않는 것이 좋습니다.

6️⃣ Gradle 클린 후 재빌드

./gradlew clean
./gradlew build --warning-mode all

lombok버전을 1.18로 설정하니 잘되었다.

프로젝트를 처음 시작할 때, 저는 두 가지 선택지 사이에서 고민을 했습니다.

  1. Spring Initializr를 통해 기본적인 Spring Boot 프로젝트 구조를 바로 생성하는 방법
  2. gradle init을 통해 생성된 템플릿을 바탕으로 직접 build.gradle 파일을 작성하고, 디렉터리 및 파일 구조를 커스터마이징하는 방법

결국, 저는 직접 build.gradle을 작성해보며, 프로젝트의 이름 변경, 파일 이름 수정(예: app.java → Application.java) 등 세세한 부분까지 컨트롤하는 방식으로 진행하기로 했습니다.

 


 

프로젝트 폴더 및 파일 커스터마이징

디렉터리 구조 재구성

gradle init으로 생성된 기본 템플릿은 보통 아래와 같은 구조를 가지고 있었습니다:

my-project-001/
 ├── app/                  ← 기본 템플릿의 서브 디렉터리
 ├── build.gradle
 └── settings.gradle
 

하지만 Spring Boot 표준 구조는 다음과 같아야 합니다:

 

my-project-001/
 ├── src/
 │    ├── main/
 │    │    ├── java/       ← 실제 소스 코드 (패키지 구조: io/github/devkb)
 │    │    └── resources/  ← 설정 파일 (application.properties 등)
 │    └── test/
 │         └── java/       ← 테스트 코드
 ├── build.gradle
 └── settings.gradle

기존의 app 디렉터리는 삭제(또는 백업)하고, 위와 같은 디렉터리 구조로 직접 생성 및 재구성했습니다.

build.gradle 파일 직접 작성 및 의존성 추가

저는 기존 템플릿에서 제공되는 내용을 참고하여, 필요한 의존성을 추가하고, 플러그인 버전도 업데이트하는 방식으로 build.gradle 파일을 직접 작성했습니다. 예를 들어:

plugins {
    id 'org.springframework.boot' version '2.7.10'   // Spring Boot 버전을 최신 안정 버전으로 업그레이드
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'io.github.devkb'
version = '0.0.1'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-mustache'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    implementation('com.h2database:h2:1.4.196')
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'

    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation "io.springfox:springfox-boot-starter:3.0.0"
    implementation "io.springfox:springfox-swagger-ui:3.0.0"

}

test {
    useJUnitPlatform()
}

파일 및 패키지명 수정

  • 프로젝트 이름 변경:
    settings.gradle 파일에서 rootProject.name = 'first-prj'와 같이 지정했던 것을 확인하고, 실제 폴더명과 일치하도록 변경했습니다.
  • 파일명 수정:
    기본 템플릿에서 생성된 app.java 파일의 이름을 오타 없이 Application.java로 변경하여, Spring Boot 애플리케이션의 진입점이 올바르게 작동하도록 했습니다.

3. 빌드 및 오류 대응

커스터마이징 과정 중 여러 오류가 발생했습니다.
예를 들어,

  • 버전 카탈로그 관련 오류:
    libs 프로퍼티가 정의되지 않아 생기는 문제는 직접 의존성을 명시하는 방식으로 해결했습니다.
  • 플러그인 호환성 문제:
    Gradle 8.12.1 환경에서 발생한 내부 API 오류는 Spring Boot 플러그인을 최신 안정 버전으로 올림으로써 해결했습니다.

  • 프로젝트 디렉터리 불일치 문제:
    settings.gradle 파일과 실제 소스 위치가 다를 때 발생하는 오류는, 디렉터리 구조를 재정리하여 모두 같은 루트 디렉터리 내에 위치하도록 수정했습니다.

 


4. 최종 정리 및 연동

모든 수정 작업 후, 다음과 같은 절차로 프로젝트를 정리했습니다.

 

./gradlew clean build
./gradlew bootRun

이번 포스트에서는 Gradle 설치 후 gradle -v 명령어로 버전을 확인하고, gradle init 명령어를 사용하여 프로젝트를 초기화한 경험을 공유하려고 합니다.
예전에는 build.gradle 파일부터 직접 작성하여 프로젝트를 구성했는데, 기본 템플릿 방식인 gradle init으로 생성된 프로젝트 구조와 패키지 명이 제 기대와는 달라 고민했던 사례를 중심으로 이야기를 진행합니다.

2. Gradle 설치 및 환경 변수 설정

먼저, Windows 환경에서 Gradle을 설치하고 환경 변수를 설정했습니다.

  • 설치 확인: 터미널에서 gradle -v를 실행하여 정상 동작하는지 확인
  • VS Code 적용: VS Code 터미널에서도 환경 변수가 반영되도록 재시작 및 설정 확인

https://bong-day.tistory.com/17

3. gradle init을 통한 프로젝트 초기화

프로젝트 초기화를 위해 터미널에서 다음 명령어를 실행했습니다.

gradle init

 

그리고 여러 옵션들을 선택했습니다:

  • 빌드 스크립트 DSL: Kotlin DSL
  •  
Groovy DSL : Gradle의 전통적인 기본 DSL입니다.
많은 예제와 자료들이 Groovy DSL 기반으로 작성되어 있어 참고하기 편리합니다.
자바 프로젝트에서는 널리 사용되는 선택입니다.

Kotlin DSL : 
최근에 인기를 끌고 있으며, 정적 타입 체크와 향상된 IDE 지원을 제공합니다.
Kotlin에 익숙하다면 더욱 편리하게 느낄 수 있습니다.
다만, 문법이나 예제가 Groovy DSL보다 적을 수 있습니다.

 

  • 테스트 프레임워크: JUnit Jupiter (JUnit 5)
JUnit 4: 오랫동안 사용되어 온 전통적인 테스트 프레임워크입니다. 기존 프로젝트나 호환성이 필요한 경우 선택할 수 있습니다.
TestNG: JUnit과 유사하지만, 더 유연한 어노테이션과 기능을 제공하여 복잡한 테스트 시나리오에 적합합니다.
Spock: Groovy 기반의 BDD 스타일 테스트 프레임워크로, 자바와도 사용할 수 있으나 주로 Groovy 프로젝트에서 인기가 높습니다.
JUnit Jupiter (JUnit 5): 최신 JUnit 버전으로, 모듈화, 확장성, 개선된 기능 및 깔끔한 문법을 제공합니다.
  • 프로젝트 이름: "first-prj" 입력
  • 애플리케이션 구조: Single application project 선택

 

하지만 실제 생성된 결과는,

  • 애플리케이션 소스: 실제 코드는 app이라는 서브 디렉터리 안에 생성됨

이러한 기본 템플릿은 빠른 스캐폴딩에는 유용하지만, 원하는 디렉토리 구조나 패키지 명을 얻기에는 한계가 있었습니다.

4. 기본 템플릿의 한계와 대안

기본 템플릿(gradle init) 방식은 A의 경우, 즉 간단한 테스트나 학습용 프로젝트에는 적절할 수 있습니다.
그러나 실제 업무 프로젝트나 디렉토리, 패키지 명을 세밀하게 관리해야 하는 경우에는 다음과 같은 대안이 필요합니다.

  • Spring Initializr 사용: Spring Boot 프로젝트의 경우, Spring Initializr를 이용하면 보다 세밀하게 원하는 설정을 적용할 수 있습니다.
  • 직접 build.gradle 파일 작성: 예전처럼 build.gradle부터 직접 작성하여 프로젝트 구조를 원하는 대로 구성하는 방법도 고려해볼 수 있습니다.
  • IDE 리팩토링 활용: VS Code나 IntelliJ IDEA의 리팩토링 기능을 사용해 프로젝트 생성 후 구조를 수정하는 방법도 있습니다.

결국, 각 프로젝트의 요구사항에 따라 도구와 방법을 유연하게 선택하는 것이 중요하네요.

5. 결론

gradle init 명령어는 빠른 초기 스캐폴딩 도구로는 유용하지만, 제가 원하는 세밀한 디렉토리 구조나 패키지 명을 얻기에는 한계가 있음을 경험했습니다.
조금 더 확정성을 고려한 프로젝트 구조를 구성할 계획입니다.

이번 글에서는 Windows 환경에서 Gradle을 설치하고 설정하는 방법에 대해 처음부터 차근차근 설명해드리겠습니다. Gradle은 Java 기반 프로젝트(특히 Spring Boot)에서 자주 사용하는 빌드 도구로, 올바르게 설치하고 환경 변수를 설정하면 VS Code나 다른 IDE에서 손쉽게 사용할 수 있습니다.

 


1. Gradle 설치 확인

먼저, 터미널(CMD 또는 PowerShell)에서 Gradle이 이미 설치되어 있는지 확인합니다.

gradle -v
  • 정상 출력: Gradle 버전 정보가 표시된다면 설치된 것입니다.
  • 오류 발생: “gradle을(를) 실행할 수 없습니다” 또는 “command not found”와 같은 메시지가 나온다면 설치가 필요합니다.

2. Gradle 설치 (패키지 매니저 사용)

Windows에서는 Scoop 또는 Chocolatey 같은 패키지 매니저를 사용하면 터미널 명령어로 쉽게 설치할 수 있습니다.

Scoop으로 설치하기

Scoop이 설치되어 있지 않다면, 아래 명령어로 설치합니다.터미널을 재시작하세요.

 
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser irm get.scoop.sh | iex
  1. Scoop을 사용해 Gradle을 설치합니다.
scoop install gradle

Chocolatey로 설치하기

  • Chocolatey가 설치되어 있지 않다면, 아래 명령어로 설치합니다.터미널을 재시작하세요.
 
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
  • Chocolatey를 사용해 Gradle을 설치합니다.
choco install gradle -y

3. 환경 변수 설정

Gradle을 압축 파일로 직접 다운로드하여 설치하는 경우, 환경 변수를 설정해야 합니다.

 

 

  • 다운로드한 .zip 파일의 압축을 원하는 폴더에 해제합니다.
    • 예시 경로: C:\dev\gradle\[gradle-version-bin]\bin
  • 환경 변수 설정
    • 내 PC → 속성 → 고급 시스템 설정 → 환경 변수로 이동
    • 시스템 변수에 GRADLE_HOME을 추가하고 값에 경로를 입력합니다.
    • Path 변수에 %GRADLE_HOME%\bin을 추가합니다.

4. VS Code에서 Gradle 사용하기

CMD나 PowerShell에서는 gradle -v로 확인이 되지만, VS Code 터미널에서는 반영되지 않을 수 있습니다. 이 경우:

  1. VS Code 재시작
    환경 변수 변경 사항이 반영되도록 VS Code를 완전히 종료한 후 다시 실행합니다.
  2. 기본 터미널 변경
    VS Code에서 Ctrl + Shift + P를 눌러 Select Default Profile을 선택하고, CMD (또는 PowerShell)로 변경한 후 확인합니다.

직접 환경 변수 추가 (필요시)
settings.json 파일에 다음과 같이 추가하여 VS Code 터미널에 환경 변수를 설정할 수 있습니다.

"terminal.integrated.env.windows": { "Path": "C:\\Gradle\\gradle-8.5\\bin;${env:Path}" }

작업결과

 

5. 프로젝트 초기화: Gradle Init

 

https://bong-day.tistory.com/18

 

 

 

 

 

 

+ Recent posts