배경 : 나는 현재 jdk8 을 쓰고 있음. 현재 기준으로 버전업을 한번은 해야하는데 혼자하면 힘들 것 같아서 AI의 도움을 받아 해볼까 생각중 (인텔리제이 의 AI Assistant 를 실수로 30일 체험을 눌러서 유료일때 뭔가 같이 해서 해보려고한다)
내용 : 가이드 준 내용 1차 아래 작성 // 이후 내 소스에서 실제 적용한 버전 하나하나 남기면서 이력화 해보려고 함.
나
현재 이 프로젝트는 JDK 8와 SPRING BOOT 1.5.X 버전을 사용하고 있어, 최종 JDK 21 17까지 스프링 부트는 3.3.X 까지 업그레이드 하고 싶은데 너가 한번 전체 소스 점검해서 어디를 수정하고 어떤 순서로 수정을 진행해야하는지 자세하게 설명 부탁해
AI Assistant
스프링 부트 1.5.x(JDK 8)에서 스프링 부트 3.3.x(JDK 21 17)로의 업그레이드는 단순 버전 변경이 아닌 “대규모 마이그레이션” 작업입니다.
이 과정에서 Spring Boot, Spring Framework, Java 자체 API, 써드파티 라이브러리 등 다양한 호환성 이슈가 발생하므로 반드시 체계적으로 접근해야 합니다.
1. 전반적 주요 변화 요약
- Spring Boot 2.x~3.x:
- Spring Framework 6.x, Java 17 이상 필수 (3.3.x는 JDK 21도 지원)
- Jakarta EE 네임스페이스 변경(javax.* → jakarta.*)
- Legacy API/의존성(예: Spring Data, Security 등) 대폭 변경/제거
- Deprecated 코드 다수 제거
- XML 설정 최소화, Java Config 사용 권장
- JDK 8 →
2117:- 새로운 문법/기능 추가, Deprecated/제거 API 존재
- 써드파티 라이브러리 최신 버전 필요
- 빌드/런타임 호환성 유의
2. 대표 변경점/작업 항목 리스트
(1) 필수 선결작업
JDK 21JDK17 설치 및 전환 (JAVA_HOME 등 프로젝트 세팅)- Gradle/Maven 빌드 툴 최신화 (권장)
- 모든 서드파티 라이브러리 최신 버전 확인
(2) 단계별 업그레이드
- 권장 로드맵
- Spring Boot 2.7.x + JDK 17까지 올림
(바로 3.x로 점프하지 말고, 변화가 적은 중간단계를 거치면 오류 추적과 변경관리 용이) Spring Boot 3.x + JDK 21으로 올림Spring Boot 3.3.x (현재 최신 릴리즈는 10 이므로 10 으로 진행해볼 예정)
- Spring Boot 2.7.x + JDK 17까지 올림
(3) 코드 및 설정 점검
- javax.* → jakarta.* 네임스페이스 전환(예: servlet, validation, persistence, etc.)
- Spring, Hibernate, Security 등 사용 API 마이그레이션 가이드 참고
- , 등 Deprecated 클래스 제거 WebMvcConfigurerAdapterHandlerInterceptorAdapter
- XML 기반 설정 → Java Config 전환 권장
- actuator, security, data 등 적용 방식 변경 체크
- 테스트 코드/환경 점검 및 JUnit 5 전환 반영
(4) 상황별 구체 조치
- 코드 내 직접적으로 Model, HttpServletRequest 등 커스텀 래퍼 써있는 경우 호환성 확인
- Lombok, MapStruct, QueryDSL 등 컴파일 타임 의존 라이브러리 호환성 확인 및 업그레이드
- ExceptionHandler, ControllerAdvice, 글로벌 핸들러 등 신규방식 전환
- Entity, DTO 등 애노테이션/속성 확인
(5) CI/CD, 운영환경
- Docker, Jenkins 등 서버 JDK 버전, 빌드/배포 스크립트 체크
- 스프링 프로필별(yml) 설정 검토
3. 예상 주요 이슈 및 구체 점검 포인트
항목 버전업 전 버전업 후 (조치사항)
| 네임스페이스 | javax | jakarta (일괄변경) |
| 의존성 | spring-boot-starter-xyz | groupId/artifactId, scope 변경 |
| Filter/Interceptor | ~Adapter 클래스 | 직접 인터페이스 구현 |
| Security | WebSecurityConfigurerAdapter | SecurityFilterChain Bean 등록 방식 |
| Validation | javax.validation | jakarta.validation |
| JPA | javax.persistence | jakarta.persistence |
| 테스트 | JUnit 4 | JUnit 5, assertJ 최신화 |
| yml/properties | 일부 옵션 삭제 | 공식 문서 참고하여 대체 옵션 적용 |
4. 업그레이드 단계별 상세 순서와 전략
1단계: 준비 및 진단
- 빌드/테스트 자동화 먼저 구현/정비
- 모든 의존성 버전 테이블 작성(현재/변경 후)
- 커뮤니티 마이그레이션 가이드, 공식 Upgrading Guide 숙지
2단계: JDK 17/21 및 빌드툴 버전 업그레이드
- JDK 17로 빌드·테스트 →
정상 확인 후 JDK 21로 추가 업그레이드 (21은 안가기로 함. 한개의 시스템은 zcp 라는 것을 쓰는데 현재 jdk 17만 허용함) - 빌드툴(Gradle/Maven) 플러그인 최신화
3단계: Spring Boot 2.7.x로 업그레이드
- 최소 컴파일/런타임 오류 수정(주로 의존성 버전, Deprecated API)
- 부트 애노테이션, 설정 방식 변경 적용
- 테스트 전수 돌려보고 오류 대응
4단계: Spring Boot 3.3.x로 업그레이드
- javax.* → jakarta.* 코드/설정/의존성 일괄 변경
- Spring Security, Data 등 종속 모듈 업그레이드 및 신규 설정 적용
- 예외처리, 핸들러, 필터 등 신규방식 전환
- 프로젝트 전체 빌드 및 테스트
5단계: 부가 기능 및 서드파티 추가 점검
- actuator, swagger, openapi, kafka 등 연계 라이브러리 모두 최신화
6단계: 인프라, 프로파일, 배포환경 점검
- 운영/개발 서버 JDK 교체, 배포 스크립트 점검
7단계: 문서화 및 개발팀 코드리뷰
- 주요 마이그레이션 포인트와 발생한 문제/해결방안 위키 등으로 기록
5. 실제 수정 예시
(1) → jakarta 예시 javax
- import javax.servlet.http.HttpServletRequest;
+ import jakarta.servlet.http.HttpServletRequest;
(2) Filter, Adapter 코드 변경 예시
// Before (1.5.x)
public class MyInterceptor extends HandlerInterceptorAdapter { ... }
// After (3.x)
public class MyInterceptor implements HandlerInterceptor { ... }
(3) Security 설정 변경 예시
// Before
@Override
protected void configure(HttpSecurity http) throws Exception { ... }
// After
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { ... }
6. 정리/권고
- 소스가 많고 오래된 경우, “마이그레이션 브랜치”를 새로 파서 단계별로 올리고, 각 단계별 Commit을 남기는 방식 강력 권장
- 반드시 “전체 테스트 코드/통합테스트” 정비 및 주기적 실행
- 필수 신규 문법이 어려운 경우 공식 Upgrading 가이드/커뮤니티 QnA 활용
📋 결론: 실무 자동 업그레이드 로드맵
- 전체 의존성/코드 목록 파악
JDK 17 → 21 순 업그레이드- Spring Boot 2.7.x → 3.3.x 순차 업그레이드 ·단계별 Commit 남기기·
- 의존성 ·네임스페이스· ·Deprecated· 코드 전체 교체
- 전수 테스트 및 인프라 최적화
좋은 질문 감사합니다!
아래는 귀하의 코드 현황을 참고해, "Spring Boot 1.5.x(JDK 8) → Spring Boot 3.3.x(JDK 21)"로 업그레이드시 실제 소스 단위에서 반드시 점검 및 수정해야 하는 주요 포인트와 구체적인 제안을 정리한 것입니다.
1. 패키지(import) 네임스페이스 변경
Spring Boot 3.x에서 가장 큰 변화는 javax.* → jakarta.*입니다.
특히 다음과 같은 부분이 직접적으로 영향받습니다.
- Controller, Service, VO에 import하고 있는
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
⇒
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
- validation, jpa, persistence, annotation, filter 등에서 동일하게 적용
2. Spring 의존성/애노테이션 변경 및 추가 작업
2-1. Controller에서 Spring Mapping, DI 관련 변화는 큰 변화 없음
다만, 아래 사항을 점검/적용:
- @Autowired 대신 생성자 주입 권장(final, @RequiredArgsConstructor 활용 가능)
- @Controller, @RequestMapping 등은 동일, 그냥 유지해도 무방합니다.
- @Value 애노테이션 방식 동일
// (변경 필요 X)
@Value("${service.env}")
String serviceEnv;
// 변경 권장: 생성자 주입 적용
private final AdmTaskService admTaskService;
@Autowired
public AdmReportDownController(AdmTaskService admTaskService) {
this.admTaskService = admTaskService;
}
TIP: Lombok @RequiredArgsConstructor 사용 권장
2-2. AdmTaskVo.java 등 VO/DTO 관련
- 특별한 JPA, Validation, Serialization 관련 어노테이션이 붙어 있는 경우만 javax. → jakarta.로 바꿔야 합니다.
- 현재 소스상엔 그런 부분 없음
- 만약 전역적으로 javax.validation.constraints.*, javax.persistence.* 등 존재한다면 모두 jakarta.*로 변경 필요
2-3. MultipartFile 등 파일업로드
- 기존 org.springframework.web.multipart.MultipartFile은 변함없으나,
Spring Boot 3 환경에서 동작하려면 multipart 관련 프로퍼티 및 의존성 재점검 필요
3. 기본 코드 호환성 점검 및 권장 리팩토링
3-1. Exception Catch 재점검
- 기존 Exception 타입이 바뀌거나, 일부 Exception이 Deprecated 되었는지 확인 필요
(예: Spring Security, Data, Web MVC 등)
3-2. Service, DAO 클래스 내외의 트랜잭션 처리
- 기존의 @Transactional (javax) → jakarta.transaction.Transactional 바뀔 수 있으니 import 네임스페이스 점검 필요
- usersDelete처럼 Exception 전파하고 있는 경우, custom Exception이나 RuntimeException 활용 권장
4. 빌드/의존성(yml, properties 포함) 변경
- Spring Boot 3.x로 올리면 application.properties(application.yml) 내 몇몇 속성명이 변경/삭제되었으니 반드시 점검
5. 마이그레이션 주요 순서 요약 (실제 소스 대응 관점)
- JDK 21로 빌드/런확환경 변경
- 전체 코드 내 javax. → jakarta. 일괄 검색 및 변경
- 특히 servlet, validation, persistence 등
- 모든 의존성(pom.xml/build.gradle)을 Spring Boot 3.3.x로 맞추고, 필요한 경우 써드파티(예: Lombok, Mapstruct 등)도 업그레이드
- 빌드 후 컴파일 에러, Deprecated 경고를 전부 확인하고
- Adapter 기반 클래스, 일부 테스트 코드 인터페이스 확장, 시큐리티 설정 변경 필요 여부 점검
- 최소수정 빌드 완료 후, 테스트 코드/통합테스트로 기능 정상동작 확인
- 리팩토링 및 불필요한 코드, Deprecated API 제거
6. 예시: 여러분 프로젝트 소스의 실제 변경 포인트
(1) admReportDownController.java : import 변경
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
+ import jakarta.servlet.http.HttpServletRequest;
+ import jakarta.servlet.http.HttpServletResponse;
그리고 필요시 생성자 주입 리팩토링 적용
(2) 전역적으로 모든 javax. → jakarta. 네임스페이스 변경
- 특히 DTO/VO, Service, Filter, Exception 관련 코드에서 반복 확인
(3) build.gradle/pom.xml에서 Spring Boot/관련 의존성 최신화
- Lombok 최신화 및 Enable Annotation Processing 설정
7. 권장 순차적 작업 체크리스트
- 전체 소스에서 javax 사용되는 부분 grep
- 각종 Adapter, Deprecated API 검색 및 교체
- 전체 의존성 최신화 (스프링/롬복 등)
- 서버 구동 및 컴파일 확인
- 테스트 코드 수정·최신화
- 배포 및 운영환경 스크립트 수정(JAVA_HOME 등)
더 구체적인 예시, 파일별 예상 변경내역이 필요하면
build.gradle (혹은 pom.xml) 파일과
Filter, Validation, JPA(Entity), Security, ExceptionHandler 등의 샘플 코드를 올려주시면
각각의 구체적인 신규 코드 샘플/대응 가이드도 추가로 안내드릴 수 있습니다!
추가 궁금한 점 알려주세요. 😊
나
jdk21은 안하고 jdk17로 변경할꺼야 다시 설명해줘
AI Assistant
네, JDK 21이 아닌 JDK 17을 기준으로 Spring Boot 3.3.x 업그레이드를 진행하는 경우에 맞추어
귀하의 소스를 어떻게 변경·점검해야 할지 실제 적용 위주로 단계를 정리해서 안내드리겠습니다.
1. JDK 17로 변경 시 주요 참고점
- Spring Boot 3.x는 최소 JDK 17을 요구합니다.
- JDK 17은 LTS(장기지원) 버전이며, 대부분의 최신 라이브러리가 공식 지원합니다.
- Java 언어 및 일부 표준 API 변화(JDK 8 → 17) 반영 주의(예: some deprecated, stream api, files api 등)
2. 프로젝트 구조별 주요 변경사항
2-1. javax.* → jakarta.* 네임스페이스 변경
(이건 Spring Boot 3.x로 올릴 때 무조건 필요합니다.
JDK 17을 쓰더라도, Spring 3.x + Jakarta EE 9+는 jakarta.* 네임스페이스만 사용됩니다.)
예시:
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
+ import jakarta.servlet.http.HttpServletRequest;
+ import jakarta.servlet.http.HttpServletResponse;
2-2. 서비스, VO, 기타 코드
- validation, persistence 등 JPA, 유효성검사 관련 코드에도 javax.에서 jakarta.로 반드시 바꿔야 합니다.
- 만약 javax.validation.constraints.NotNull 등의 annotation을 쓰고 있으면 jakarta.validation.constraints.NotNull로 변경
2-3. Spring Security, Web MVC 관련 변경
- WebSecurityConfigurerAdapter 등 Deprecated이므로, 새 Bean 등록 방식으로 변경 필요
- HandlerInterceptorAdapter 등의 Adapter 클래스 → 인터페이스 구현으로 변경
2-4. Lombok, Mapstruct 등 컴파일 타임 의존성 최신화
- 반드시 최신 버전 사용 (JDK 17 지원 여부 확인)
2-5. 빌드 도구 및 yml/properties 변경
- Gradle/Maven plugin 최신화
- application.properties(yml)에서 일부 옵션명 변동되는 것 점검
3. 업그레이드 단계 요약 (실제 프로젝트 작업 순)
1단계. JDK 17로 전환 (프로젝트, CI, IDE 모두 설정)
- JAVA_HOME 등 전역 환경변수 변경
- 인텔리J, 이클립스, 젯브레인 등 빌드툴 JDK 버전 설정 변경
2단계. 의존성 최신화
- build.gradle or pom.xml에서
- spring-boot-starter-parent(Maven), spring-boot-dependencies(Gradle) → 3.3.x
- Lombok, 기타 주요 라이브러리 버전업
3단계. 코드 전역의 네임스페이스 변경
- javax. → jakarta.
- servlet, validation, persistence, annotation 등 모두!
- grep(Find in Path/grep 등 도구)로 전체 소스에서 javax. 찾고, 일괄변경
4단계. Spring Security, WebMvc, Filter 등 Spring API 변경사항 반영
- (해당 코드가 있는 경우)
- Adapter 기반 클래스 → 인터페이스 직접구현
- Security → SecurityFilterChain 방식
- 예:
// Before
public class MyInterceptor extends HandlerInterceptorAdapter { ... }
// After
public class MyInterceptor implements HandlerInterceptor { ... }
5단계. application.yml(properties) 설정명 변경점 확인
- 공식 가이드 참고, 사용중인 key에 deprecated된 것이 없는지 점검
6단계. 전체 빌드/테스트
- 컴파일/런타임 에러, Deprecated 경고 모두 수정
- 전수 기능 테스트 진행
7단계. 운영/배포 환경 JDK도 17로 반드시 맞춤
4. 실제 여러분 소스에 필요한 변경점 요약
- 컨트롤러/서비스/VO에서
- import javax.servlet... → import jakarta.servlet...
- 기타 javax.validation, javax.persistence 등도 마찬가지 (전체검색으로 확인)
- (Lombok 등) 의존 파일, annotation processor 최신화
- Spring Security/WebMvc 관련 코드는 공식 가이드 보고 패턴변경 필요
- application.properties(yml)의 옵션명/값 최신 가이드 적용
5. 꼭 확인할 특별 주의사항
- JDK 17부터는 더 이상 일부 오래된 옵션, 라이브러리, API가 작동하지 않을 수 있습니다.
- 일부 3rd-party(오래된 Oracle, MySQL, LDAP, Kafka 등 드라이버)도 JDK 17+에서 지원버전 확인 필요!
- 이전 버전에서 돌아가던 reflection, dynamic proxy 방식 API는 반드시 기능 전수 테스트 필요
6. 결론(순서 정리)
- JDK 17 적용(전체 환경)
- Spring Boot 3.3.x, 기타 의존성 최신화
- 소스 코드의 javax.* → jakarta.* 전체 일괄변경
- Spring API 패턴 변경(특히 Security, WebMvc, Filter)
- 의존 라이브러리/플러그인(Lombok 등) 최신화
- 전체 테스트 수행 및 남은 호환성 이슈 수정
💡 추가로 궁금한 점(예: 특정 Adapter 코드, 빌드/설정파일, Security 설정 등)이 있으시면
소스 일부나 build.gradle/pom.xml 등 파일을 첨부해 주시면,
정확하게 어떤 부분을, 어떻게 고쳐야 하는지 코드 예시와 함께 안내 드릴 수 있습니다!
언제든 질문 주세요. 😊
1. JDK 버전 8 > 11 테스트
인텔리제이에서 현재 조회되고 있는 프로젝트 내 jdk 버전을 바꾸려면 어떻게 해
인텔리제이(IntelliJ)에서 현재 프로젝트의 JDK(Java Development Kit) 버전을 변경하려면 아래와 같은 절차를 따르면 됩니다.
프로젝트 내 JDK 버전 변경 방법
1. Project Structure 창 열기
- 메뉴에서 File → Project Structure를 선택하거나 단축키 Ctrl + Alt + Shift + S(Windows), Command + ;(Mac)를 사용합니다245.
2. Project SDK 변경
- 좌측에서 Project 탭을 선택합니다.
- Project SDK 드롭다운에서 원하는 JDK 버전을 선택합니다.
3. Project Language Level 변경
4. Module 별 JDK 및 Language Level 변경
- 좌측에서 Modules 탭을 선택합니다.
- 각 모듈의 Dependencies 탭에서 Module SDK를 원하는 JDK로 변경합니다.
- Sources 탭에서 Language level도 맞춰줍니다211.
5. Gradle/Maven 빌드 도구 JDK 변경
- File → Settings(Windows: Ctrl + Alt + S, Mac: Command + ,)로 이동합니다.
- Build, Execution, Deployment → Build Tools → Gradle에서 Gradle JVM을 원하는 JDK로 변경합니다.
- Maven을 사용하는 경우, Build Tools → Maven의 Runner 설정에서 JDK를 맞춰줍니다12414.
6. Java Compiler(바이트코드 버전) 변경
- 같은 Settings에서 Build, Execution, Deployment → Compiler → Java Compiler로 이동합니다.
- Project bytecode version을 원하는 JDK 버전에 맞게 설정합니다1214.
7. (필요 시) 실행/디버그 설정의 JDK 확인
참고 사항
- JDK를 아직 설치하지 않았다면, Project Structure 창의 SDKs에서 + 또는 Download JDK를 통해 바로 다운로드 및 추가할 수 있습니다91416.
- 빌드 도구(Gradle, Maven) 설정 파일(build.gradle, pom.xml)의 Java 버전도 일치하는지 확인해야 합니다2611.
- 변경 후 프로젝트를 Rebuild하거나 Invalidate Caches / Restart를 해주면 적용이 확실합니다.
요약
- Project Structure에서 SDK, Language Level, Module SDK를 변경
- Settings에서 Gradle JVM, Java Compiler 버전 변경
- 필요시 실행 설정 및 빌드 도구 설정 파일까지 모두 확인 및 수정
250428 스프링부트 버전업 시작
(이력관리)
1. JDK 버전 8 -> 11
바꾼뒤 devtools 에러 나옴
Exception in thread "main" java.lang.ClassCastException: class jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to class java.net.URLClassLoader (jdk.internal.loader.ClassLoaders$AppClassLoader and java.net.URLClassLoader are in module java.base of loader 'bootstrap')
첫 작업은 프로젝트 제일 상위 build.gradle 내 아래 소스 추가
//250428,ksko jdk 11 업그레이드 작업
//sourceCompatibility = 1.8
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
그 뒤 build.gradle 내 (web) 프로젝트
compile "org.springframework.boot:spring-boot-devtools"
주석처리 (혹시몰라, 아래 추가)
//250428,ksko jdk 버전업에 따른 devtools 의존성 제거 (jdk8 까지는 정상동작 jdk9 이후 부터 모듈시스템 도입과 함께 내부 로더 구현 변경)
//- Java 9 이상(Java 11 환경)에서 기본 애플리케이션 클래스로더는 더 이상 를 상속하지 않으므로, 이러한 캐스팅은 실패하게 됩니다. `URLClassLoader`
//- 따라서 **DevTools**를 사용할 때 버전 호환성 문제가 주요 원인입니다.
//compile "org.springframework.boot:spring-boot-devtools"
//개발서버만 사용하도록 수정
developmentOnly("org.springframework.boot:spring-boot-devtools")
수정을 해도 계속 동일 오류남. 인텔리제이 ai assistant 말로는
장기적이고 권장되는 해결 방법
- Spring Boot DevTools 제거
- DevTools는 개발 편의성을 위한 hot reload를 제공하지만, 실제로 대부분의 배포 환경에서는 필요하지 않습니다.
- 개발환경에서도 문제가 계속된다면 임시로 DevTools를 의존성에서 제거하는 것이 가장 확실한 해결책입니다.
- 최신 Spring Boot로 업그레이드
- 최신 버전의 Spring Boot에서는 이 문제들이 해결되었습니다. 가능하다면 Spring Boot 2.4 이상(특히 DevTools 부분)을 사용하는 것이 좋습니다.
- DevTools를 ‘optional’ 혹은 개발 프로필에서만 사용
- DevTools는 production이나 test 환경에서 동작하지 않게 관리하세요.
- 개발 환경에서만 필요하다면, 다음과 같이 의존성을 구성할 수 있습니다 (주로 pom.xml 또는 에서 처리): build.gradle
요약
- Java 9 이상에서 DevTools의 URLClassLoader 캐스팅은 동작하지 않습니다.
- 해결법: 의존성에서 devtools를 제거하거나 최신 Spring Boot로 업그레이드 하세요.
- 장기적 해결: DevTools는 개발 환경에서만 사용, 운영(build) 환경에는 포함시키지 마세요.
위처럼 이야기를 해줘서,
일단 위 2가지 수정후 스프링부트 버전을 올려보려한다.
intellij ai assistant 에게 문의를 했다.
1. 백업 및 브랜치 분리
- 코드, 빌드파일, 설정파일을 모두 백업하세요.
- Git 브랜치를 새로 생성하는 걸 추천합니다.
(ex. springboot2-migration)
==> 프로젝트를 분리했음. ***-evaluation-vup
==> 브랜치는 dev_jdk_springboot_upgrade 에서 작업 진행함.
2. 개발 툴 업그레이드
- Gradle 버전을 Spring Boot의 권장 버전에 맞게 올려야 합니다.
- 예를 들어 Spring Boot 2.5.x 부터는 Gradle 6.x 이상이 권장됩니다.
- 에서 distributionUrl을 올려주세요. (예: https://services.gradle.org/distributions/gradle-6.9.4-bin.zip) gradle-wrapper.properties
==> 수정완료 (gradle-wrapper.properties)
#springboot 1.5.x --> 2.7.18
#distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip
distributionUrl=https:\://services.gradle.org/distributions/gradle-6.9.4-bin.zip
3. 스프링부트 의존성 버전 변경
- 에서 build.gradle
ext {
springBootVersion = '1.5.22.RELEASE'
}
→ 원하는 새 버전(ex. '2.7.18')으로 변경
==> 수정완료 (build.gradle - 최상위 플젝)
ext {
//250428,ksko springboot version uprage (1.5.22 --> 2.7.18)
//springBootVersion = '1.5.22.RELEASE'
springBootVersion = '2.7.18.RELEASE'
}
4. 의존성 라이브러리 함께 올리기
- spring-boot-starter-* 등 부트starter 라이브러리는 자동 맞춤이므로 그대로 두세요.
- 직접 명시한 라이브러리(예: jackson, hibernate, tomcat, elaticsearch, poi 등)는
Spring Boot와 호환되는 버전으로 교체해주어야 합니다.- https://start.spring.io → Dependency 선택 후 버전을 참고하거나
- 공식 Spring Boot compatibility table 참고:
https://docs.spring.io/spring-boot/docs/current/reference/html/dependency-versions.html
https://docs.spring.io/spring-boot/redirect.html?page=dependency-versions
docs.spring.io
==> 뭘 어딜 바꾸라는거야 ;;
5. 관련 변경사항 적용 build.gradle
- Gradle 5.x 이상에서 compile -> implementation/api로 변경 필요
- 예: compile → implementation
- testCompile → testImplementation
- plugin 적용 방식도 변화가 있으니, 권장 방식으로 변경
==> 각 플젝별 build.gradle 내 위 처럼 변경
[ implentation과 api의 차이 ]
api는 전이 의존성을 허용한다. 예를 들어 Project A가 있고, Project B에서는 api를 사용하여 Project A에 의존한다고 하자.

Project C에서는 Project B에 implementation를 통해 의존하기 때문에, Project B에 있는 컴파일 경로, 런타임 경로들이 노출된다. 그리고 Project B는 api를 통해 Project A에 의존하고 있으므로, Project C에서도 Project A가 사용 가능하다.
하지만 implementation으로 선언된 전이 의존성은 사용이 불가능하다. 아래의 경우에는 Project B에서 implementation를 사용하여 Project A에 의존하고 있으므로, Project C에서는 Project A의 코드에 접근이 불가능하다. 만약 Project A의 코드에 접근하려고 하면 컴파일 에러가 발생한다.

api와 implementation의 차이에 대해 정확히 이해하기 위해 몇 가지 사례를 더 추가하였다. 직접 확인해보도록 하자.

==> 우리 프로젝트는 c 영역이 admin, mobile, web, B , A 영역이 core, common 영역이므로 core, common 은 api로 C 영역은 implement 로 적용 (ens gradle 버전업 버전 참고)
==> 맨 앞에 있는 최상단 프로젝트 내 build.gradle 에도 api를 적용한다.
[ implentation과 api의 사용 ]
이러한 implementation은 api에 비해 몇 가지 장점이 있다.
- 의존성이 해당 모듈을 사용하는 컴파일 클래스 경로에 노출되지 않으므로, 실수로 전이 종속성에 빠지지 않음
- 줄어든 클래스 패스 덕분에 컴파일이 빨라짐
- implementation하는 의존성들이 변경되었을 때, 재컴파일을 하지 않아도 되므로 재컴파일 횟수가 줄어듬
- 새로운 maven-publish 플러그인을 함께 사용하면, java 라이브버리는 컴파일하는데 필요한 것과 런타임에 사용하는데 필요한 것을 정확히 구분하는 POM 파일을 생성하여 더욱 깔끔하게 publish 할 수 있음
따라서 가능하다면 api 보다는 implementation을 우선시하는 것이 좋다. 이렇게 하면 모듈을 사용하는 곳의 컴파일 클래스 경로에서 종속성을 유지할 수 있다. 또한 implemeantion으로 선언된 라이브러리가 사용되려고 하면 컴파일 에러가 발생하며 실패하게 된다.
api는 애플리케이션 바이너리 인터페이스(ABI, Application Binary Interface)로 아래와 같은 경우에 사용하면 좋다.
- 부모 클래스 또는 인터페이에 사용되는 타입
- 제너릭 타입을 포함하여 public 메소드 파라미터로 사용하는 타입
- 퍼블릭 필드에 사용되는 타입
출처: https://mangkyu.tistory.com/296 [MangKyu's Diary:티스토리]
==> 일단 다 바꿧음.
6. 소스 코드 및 설정 업데이트
- 패키지 변경, 삭제, Deprecated/Removed 기능 수정(특히 JPA, Embedded Tomcat, Servlet API 관련)
- application.properties / application.yml 등 설정 양식과 키 변경점 반영
(기존 server.context-path → server.servlet.context-path 등)
==> 검색은 안됨
7. 빌드 및 실행
- ./gradlew clean build로 빌드와 테스트 확인
- 오류 로그를 꼼꼼히 보고 대응
==> 안되서 일단 gradle 빌드 버전 수정 했다.
오류 났다.
A problem occurred configuring root project '***-evaluation'.
> Could not resolve all artifacts for configuration ':classpath'.
> Could not find org.springframework.boot:spring-boot-gradle-plugin:2.7.18.RELEASE.
Searched in the following locations:
- https://jcenter.bintray.com/org/springframework/boot/spring-boot-gradle-plugin/2.7.18.RELEASE/spring-boot-gradle-plugin-2.7.18.RELEASE.pom
- https://jcenter.bintray.com/org/springframework/boot/spring-boot-gradle-plugin/2.7.18.RELEASE/spring-boot-gradle-plugin-2.7.18.RELEASE.jar
Required by:
project :
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
==> 오류 원인 퍼플렉시티에게 물어보니,
버전 올리렌다..
올렸는데 안되서 아래 처럼 오류난다.
=====================
호환되지 않는 Gradle JVM
빌드가 현재 호환되지 않는 Java 17.0.13 및 Gradle 4.10을(를) 사용하도록 구성되었습니다. 프로젝트를 동기화할 수 없습니다.
Gradle 8.12 버전으로 업그레이드하는 것이 좋습니다.
호환되는 최소 Gradle 버전은 7.2입니다.
호환되는 최대 Gradle JVM 버전은 10입니다.
가능한 솔루션:
- Gradle 8.12(으)로 업그레이드하고 다시 동기화
- Gradle 7.2(으)로 업그레이드하고 다시 동기화
- Java 10을(를) Gradle JVM으로 사용: Gradle 설정 열기
==========================
일단..
common, core 프로젝트 + 맨 상위 프로젝트 내 내 gradle-wrapper.properties 내 gradle 버전 변경한다. (위 내용땜에 gradle 버전을 6.9 --> 7.2로 변경)
#springboot 1.5.x --> 2.7.18 (gradle 6.9 -> 7.2 fixed)
#distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip
distributionUrl=https:\://services.gradle.org/distributions/gradle-7.2-bin.zip
그리고 다시 그레이들 빌드 돌려본다.
역시 오류난다.
Cannot invoke "String.lastIndexOf(String)" because "path" is null
gradle 8.6 으로 다운로드 후 다시 비륻함.
또 오류남.
Build file 'D:\ksko\workspace\***-evaluation-vup\build.gradle' line: 8
A problem occurred evaluating root project '***-evaluation'.
> Could not find method plugins() for arguments [build_33um34161c0qs8syj89bn5180$_run_closure1$_closure2@3ba2dc9e] on object of type org.gradle.api.internal.initialization.DefaultScriptHandler_Decorated.
//250428,ksko plugin 블록은 build.gradle 파일의 최상단에 어떠한 다른 븡록보다 먼저 위치해야 함
//그래서 build.script 안애 plugin 블록 넣어서 오류남.
plugins {
id 'org.springframework.boot' version '2.7.18'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
}
buildscript {
//250428,ksko plugin DSL 방식 권장에 따른 ext 영역 주석처리
//ext {
//250428,ksko springboot version uprage (1.5.22 --> 2.7.18)
//springBootVersion = '1.5.22.RELEASE'
//springBootVersion = '2.7.18.RELEASE'
//}
repositories {
//250428,ksko 부트 상위버전은 jcenter 제거, mavenCentral로 권장함.
//jcenter()
mavenCentral()
//maven {
// url ****
//}
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "io.spring.gradle:dependency-management-plugin:1.0.9.RELEASE"
}
}
위 글 처럼 기존에 ext 영역에 plugins 를 넣었더니 오류 낫음..
위 처럼 빼고 다시 실행해보자.
뭐냐 ㅠㅠ
buildscript가 최상단이 되어야한다고 하네;;
buildscript {
repositories {
mavenCentral()
// 필요시 google() 등 추가
}
dependencies {
// 필요한 classpath 추가
}
}
plugins {
id 'org.springframework.boot' version '2.7.18'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
}
// 그 외 설정(repositories, dependencies 등)
돌다가 또 오류남...
하 ㅠㅠ
Build file 'D:\ksko\workspace\***-evaluation-vup\build.gradle' line: 71
A problem occurred evaluating root project '***-evaluation'.
> Could not find method api() for arguments [org.slf4j:slf4j-api:1.7.30] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
의 원인은 api() 메서드는 java-library 플러그인이 적용된 경우에만 사용할 수 있는데, 현재 프로젝트에 java-library 플러그인이 적용되어 있지 않기 때문입니다
원인
api는 Gradle의 java-library 플러그인을 사용할 때만 지원되는 의존성 선언 메서드입니다.
만약 plugins { id 'java' } 또는 apply plugin: 'java'만 사용하고 있다면, api 메서드는 사용할 수 없습니다.
이 경우에는 implementation만 사용할 수 있습니다.
해결 방법
1. java-library 플러그인 적용
build.gradle의 plugins 블록을 아래처럼 수정하세요.
plugins {
id 'java-library'
id 'org.springframework.boot' version '2.7.18'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
바꾸고 빌드해도 오류난다. 하 ㅠㅠ
jdk 버전 17로 바꿨다..
sourceCompatibility = '17'
targetCompatibility = '17'
그래도 오류난다.
Build file 'D:\ksko\workspace\***-evaluation-vup\build.gradle' line: 83
A problem occurred evaluating root project '***-evaluation'.
> Could not find method testCompile() for arguments [org.springframework.boot:spring-boot-starter-test] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
오류난 이유는
이 오류의 원인은 Gradle 7.0 이상에서 testCompile이 삭제되었기 때문입니다.
testCompile은 예전 Gradle에서 테스트 의존성을 추가할 때 사용하던 방식이지만,
Gradle 4.10 이후로 deprecated(사용 중단) 되었고, Gradle 7.0부터는 완전히 제거되었습니다
dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
testCompile --> testImplementation 로 수정
맨 최상위 프로젝트는 잘 넘어갔는데
이건 뭐야 admin은 왜 읽는거냐;;
Build file 'D:\ksko\workspace\*** - evaluation-vup\***-evaluation-admin\build.gradle' line: 4
A problem occurred evaluating project ':***-evaluation-admin'.
> Could not set unknown property 'archiveName' for task ':***-evaluation-admin:war' of type org.gradle.api.tasks.bundling.War.
하 ㅠㅠ
admin gradle 버전 4.10 --> 8.x 바꿔주고
이 오류의 원인은 Gradle 7.0 이상에서 더 이상 archiveName 속성을 지원하지 않기 때문입니다.
archiveName은 Gradle 6.x까지는 사용 가능했으나, Gradle 7.0부터는 완전히 제거되었고,
대신 archiveFileName, archiveBaseName 등의 속성을 사용해야 합니다
archiveFileName 으로 바꿔서 다시 빌드했다.
어드민의 build.gradle 내 있는 compile 들도 모두 implementaion 으로 바꿔주엇다.
어드민은 끝났다.
common 으로 바꼇다.
Build file 'D:\ksko\workspace\***-evaluation-vup\***-evaluation-common\build.gradle' line: 1
A problem occurred evaluating project ':***-evaluation-common'.
> Could not find method bootRepackage() for arguments [build_eclxaikzugpsqujl8xg0mmwj0$_run_closure1@2c935393] on project ':***-evaluation-common' of type org.gradle.api.Project.
이 오류의 원인은 Spring Boot 2.0 이상부터 Gradle 플러그인에서 bootRepackage 태스크가 제거되었기 때문입니다.
bootRepackage는 Spring Boot 1.x에서 실행 가능한 JAR/WAR를 만들 때 사용했던 태스크지만,
Spring Boot 2.0부터는 bootJar(JAR)와 bootWar(WAR)로 대체되었습니다
1. JAR 프로젝트라면
bootRepackage { ... } → bootJar { ... }로 변경하세요.
bootJar {
// 기존 bootRepackage에서 하던 설정을 여기에 옮깁니다
}
2. WAR 프로젝트라면
bootRepackage { ... } → bootWar { ... }로 변경하세요.
bootWar {
// 기존 bootRepackage에서 하던 설정을 여기에 옮깁니다
}
3. 만약 실행 가능한 JAR/WAR 생성을 끄고 싶었다면
예전:
bootRepackage { enabled = false }
변경:
JAR의 경우
bootJar { enabled = false }
WAR의 경우
bootWar { enabled = false }
4. 만약 Spring Boot 플러그인을 적용할 필요가 없다면
해당 모듈에서 apply plugin: 'org.springframework.boot'를 제거하고,
필요한 경우 apply plugin: 'io.spring.dependency-management'만 남겨두세요
==> 우리 프로젝트에서는 3번에 bootWar { enabled = false } 로 수정했다.
근데 또 오류 났따.
Build file 'D:\ksko\workspace\***-evaluation-vup\***-evaluation-common\build.gradle' line: 3
A problem occurred evaluating project ':***-evaluation-common'.
> Could not find method bootWar() for arguments [build_eclxaikzugpsqujl8xg0mmwj0$_run_closure1@ac2bc60] on project ':***-evaluation-common' of type org.gradle.api.Project.
이 오류의 원인은 Spring Boot Gradle 플러그인이 적용되지 않은 상태에서 bootWar { ... } 블록을 사용했기 때문입니다.
bootWar는 Spring Boot 플러그인을 적용해야만 사용할 수 있는 태스크이며, 플러그인이 없으면 Gradle은 bootWar 메서드를 인식하지 못해
Could not find method bootWar() for arguments [...]
오류가 발생합니다
1. Spring Boot 플러그인 적용
해당 모듈(예: ***-evaluation-common)이 Spring Boot 웹 애플리케이션(WAR)로 패키징되어야 한다면,
build.gradle 최상단에 아래를 추가하세요:
plugins {
id 'org.springframework.boot' version '2.7.18'
// ... 기타 플러그인
}
또는 구버전 방식이라면:
apply plugin: 'org.springframework.boot'
2. Spring Boot 플러그인 적용이 불필요한 경우
만약 해당 모듈이 공통 라이브러리 등이고, Spring Boot 애플리케이션이 아니라면
bootWar { ... } 블록을 제거해야 합니다.
대신, 일반적으로는 jar { ... } 또는 war { ... } 태스크만 사용하면 됩니다.
3. 멀티 모듈 프로젝트라면
보통 :common 같은 공통 모듈에는 Spring Boot 플러그인을 적용하지 않고,
최상위 실행 모듈(웹/서비스 모듈)에만 적용합니다.
공통 모듈에서는 bootWar, bootJar 대신 표준 jar, war 태스크를 사용하세요.
==> 여기서는 3번과 같은 사유 였음. war Task 로 변경
다시 빌드.
war 안먹네 ㅋㅋ;;
Build file 'D:\ksko\workspace\***-evaluation-vup\***-evaluation-common\build.gradle' line: 7
A problem occurred evaluating project ':***-evaluation-common'.
> Could not find method war() for arguments [build_eclxaikzugpsqujl8xg0mmwj0$_run_closure1@430abf25] on project ':***-evaluation-common' of type org.gradle.api.Project.
... (설명 생략)
만약 공통 모듈(:***-evaluation-common)이 WAR 패키징이 필요 없는 라이브러리라면, war 플러그인과 관련 블록을 제거하는 것이 맞습니다.
--> WAR 영역 빌드 하는거 아니다 명령 모두 주석처리
core 프로젝트로 넘어감.
Build file 'D:\ksko\workspace\***-evaluation-vup\***-evaluation-core\build.gradle' line: 1
A problem occurred evaluating project ':***-evaluation-core'.
> Could not find method bootRepackage() for arguments [build_6fh1pkfq6w0nup4kw2csryqzd$_run_closure1@49374e56] on project ':***-evaluation-core' of type org.gradle.api.Project.
똑같이 bootRepackage 영역이므로 common 과 동일하게 셋팅 (해당 블록 주석처리)
빌드 안하고 일단 종료
250428 19:26 분 .. 일단 여기까지 하자.. ㅋㅋ;;
Build file 'D:\ksko\workspace\***-evaluation-vup\***-evaluation-web\build.gradle' line: 4
A problem occurred evaluating project ':***-evaluation-web'.
> Could not set unknown property 'archiveName' for task ':***-evaluation-web:war' of type org.gradle.api.tasks.bundling.War.
오.... 스프링부트 2.7 다운로드 막 받음 우어어 ㅠㅠ
Download https://jcenter.bintray.com/net/bytebuddy/byte-buddy-agent/1.12.23/byte-buddy-agent-1.12.23.jar, took 336 ms
Download https://jcenter.bintray.com/net/minidev/accessors-smart/2.4.11/accessors-smart-2.4.11.jar, took 321 ms
Download https://jcenter.bintray.com/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar, took 322 ms
Download https://jcenter.bintray.com/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar, took 315 ms
Download https://jcenter.bintray.com/org/ow2/asm/asm/9.3/asm-9.3.jar, took 326 ms
Download https://jcenter.bintray.com/org/junit/jupiter/junit-jupiter-engine/5.8.2/junit-jupiter-engine-5.8.2.jar, took 1 s 713 ms
Download https://jcenter.bintray.com/org/junit/platform/junit-platform-engine/1.8.2/junit-platform-engine-1.8.2.jar, took 500 ms
Download https://jcenter.bintray.com/org/objenesis/objenesis/3.2/objenesis-3.2.jar, took 759 ms
어우 됬다 ㅠㅠ
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.6/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 6m 53s
빌드는 됫는데, 이제 실행하면 오류 터진다 하 ㅋㅋ;
Cause: class lombok.javac.apt.LombokProcessor (in unnamed module @0x3ed4bfca) cannot access class cohttp://m.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export cohttp://m.sun.tools.javac.processing to unnamed module @0x3ed4bfca
오류 원인
이 오류는 Java의 모듈 시스템(JPMS) 도입 이후, JDK 내부 API에 대한 접근 제한이 강화되면서 발생합니다.
lombok.javac.apt.LombokProcessor가 cohttp://m.sun.tools.javac.processing.JavacProcessingEnvironment 클래스를 접근하려고 시도하지만,
JDK 9 이상부터는 jdk.compiler 모듈이 해당 패키지를 외부(unnamed module)로 export하지 않기 때문에 불가능합니다.
특히 JDK 16 이상에서는 이 제한이 더욱 엄격해져, Lombok의 일부 버전이 정상적으로 동작하지 않습니다
주요 원인 정리
JDK 버전이 16 이상: JDK 16부터 내부 API 접근이 막혀서 Lombok이 정상 동작하지 않음.
Lombok 버전이 JDK와 호환되지 않음: 구버전 Lombok은 최신 JDK에서 동작하지 않음
해결 방법
1. JDK 버전 낮추기 (권장)
JDK 8 또는 JDK 11로 프로젝트의 JDK 버전을 낮추면 대부분의 Lombok 관련 오류가 해결됩니다.
IntelliJ 기준: File > Project Structure > SDK에서 JDK 8 또는 11로 변경.
2. Lombok 최신 버전 사용
사용하는 Lombok 버전을 최신(예: 1.18.20 이상)으로 올리면 JDK 16 일부 버전까지는 해결되는 경우가 있습니다.
build.gradle 예시:
groovy
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
}
3. JDK 16 이상을 꼭 써야 한다면 (비추천)
빌드 도구에 추가 JVM 옵션을 넣어 내부 패키지 접근을 허용할 수 있지만, 이는 임시방편이며, 모든 환경에서 완벽히 동작하지 않을 수 있습니다.
예시 (Maven):
xml
<compilerArgs>
<arg>--add-exports=jdk.compiler/cohttp://m.sun.tools.javac.processing=ALL-UNNAMED</arg>
</compilerArgs>
Gradle의 경우에도 비슷하게 compileJava 태스크에 JVM 옵션을 추가할 수 있습니다.
그러나 이 방법은 IDE(예: IntelliJ)에서는 적용이 어려우며, 공식적으로 권장되지 않습니다.
결론
가장 확실한 해결책: JDK를 8 또는 11로 낮추고, Lombok을 1.18.20 이상으로 사용하세요.
JDK 16 이상을 꼭 써야 한다면, Lombok의 공식 지원 여부를 확인하거나, JVM 옵션을 추가해 일시적으로 우회할 수 있지만, 이는 근본적인 해결책이 아닙니다
==> 나는 롬복 최신버전을 선택한다. java 17 로 가니까 1.18.22 로 가보자
https://jinseobbae.github.io/java/2023/02/27/lombok-version-compatibility.html
[JAVA] Lombok 호환 버전 정리
현재 업무에서 4가지의 자바 버전을 사용하고 있어 그에 따른 Lombok 버전을 정리한다.
jinseobbae.github.io
현재 업무에서 4가지의 자바 버전을 사용하고 있어 그에 따른 Lombok 버전을 정리한다.
(2024. 12. 05 현황)
Java 버전Lombok 버전
| 23 | 1.18.36 |
| 22 | 1.18.32 |
| 21 | 1.18.30 |
| 20 | 1.18.28 |
| 19 | 1.18.26 |
| 18 | 1.18.24 |
| 17 | 1.18.22 |
| 16 | 1.18.20 |
| 15 | 1.18.16 |
| 14 | 1.18.12 |
| 13 | 1.18.12 |
| 12 | 1.18.10 |
| 11 | 1.18.4 |
| 10 | 1.18.4 |
| 9 | 1.16.20 |
| 8 | 1.16.0 |
여기서 일이 치고들어와서 일단 스톱 .... 저장하고 다시
lombok 버전을 1.8.12 --> 1.18.22 로 변경
compileOnly "org.projectlombok:lombok:1.18.22" //250429,ksko jdk 17 - 1.18.12 --> 1.18.22 로 변경
annotationProcessor "org.projectlombok:lombok:1.18.22" //250429,ksko jdk 17 - 1.18.12 --> 1.18.22 로 변경
오류 났음.
Execution failed for task ':***-evaluation-common:processResources'.
> Entry jks/datalent_dev.jks is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/8.6/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
250507 다시 시작하자.
오류...
Execution failed for task ':***-evaluation-common:processResources'.
> Entry jks/datalent_dev.jks is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/8.6/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
원인
오류 원인:
Gradle 빌드 중 :***-evaluation-common:processResources 태스크에서 같은 이름의 파일(jks/datalent_dev.jks)이 여러 번 복사되려고 해서 "duplicate but no duplicate handling strategy has been set" 오류가 발생한 것입니다. 즉, 리소스 파일이 중복되어 빌드 시스템이 어떻게 처리할지 몰라 에러가 납니다.
==> 실제로 확인해보니, ADMIN, COMMON 프로젝트에 src/resources/jks 폴더 내 datalent_dev.jks 파일이 모두 들어가 있었음. 빌드하다가 오류 난듯 보임.
==> ***-evaluation-common 내 resource/jks/ 폴더 에 있는 datalent_dev, datalent_opr 파일 제거 (나중에 오류 발생시 admin 에 있는 것 넣어서 진행)
==> 위 처럼 삭제 할 필요가 없음
해결 방법:
COMMON 프로젝트 내 아래 영역 추가.
build.gradle 파일의 해당 task(예: processResources)에 duplicatesStrategy 옵션을 추가해 중복 파일 처리 방식을 명시하면 됩니다.
tasks.named('processResources') {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE // 또는 DuplicatesStrategy.INCLUDE
}
INCLUDE: 중복 파일을 모두 포함
EXCLUDE: 중복 파일을 제외(보통 추천)
설정 후 Gradle 프로젝트를 리프레시하면 오류가 해결됩니다
위 영역은 넘어갔는데.. 음
Execution failed for task ':***-evaluation-core:processResources'.
> Entry mybatis/codeMapper.xml is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/8.6/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
오류 원인
Gradle 빌드 중 :***-evaluation-core:processResources 태스크에서 mybatis/codeMapper.xml 파일이 여러 소스에서 중복되어 복사되려고 할 때, 중복 처리 방식(duplicatesStrategy)이 지정되지 않아 발생하는 오류입니다. Gradle 7.x 이상에서는 중복 파일이 있을 때 명시적으로 처리 방식을 지정해야 합니다.
해결 방법
build.gradle 파일에 아래와 같이 processResources 태스크에 duplicatesStrategy 옵션을 추가하세요.
tasks.named('processResources') {
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE // 또는 EXCLUDE
}
==> core 프로젝트 내 위 추가 (common 처럼)
넘어갔는데 음... 허 뭐여 ㅠㅠ
D:\ksko\workspace\***-evaluation-vup\***-evaluation-web\src\main\java\com\***\evaluation\Application.java:16: error: package org.springframework.boot.context.embedded does not exist
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
오류 원인
org.springframework.boot.context.embedded 패키지는 Spring Boot 1.x에서 사용되던 것으로, Spring Boot 2.x부터는 삭제되고 대체 API가 도입되었습니다. 따라서 Spring Boot 2.x 이상 버전에서는 해당 패키지와 관련 클래스(ConfigurableEmbeddedServletContainer 등)를 더 이상 사용할 수 없어 발생하는 오류입니다.
해결 방법
1. ConfigurableEmbeddedServletContainer → ConfigurableServletWebServerFactory로 변경
2. EmbeddedServletContainerCustomizer → WebServerFactoryCustomizer로 변경
3. 관련 import도 모두 org.springframework.boot.web.server 등 새로운 패키지로 수정
import org.springframework.boot.web.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
두개 바꾸고 gradle 빌드 후 실행했더니 오류 또 나왓다.
D:\ksko\workspace\***-evaluation-vup\***-evaluation-web\src\main\java\com\***\evaluation\Application.java:18: error: package org.springframework.boot.context.embedded.tomcat does not exist
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer;
오류 원인
org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer 패키지와 클래스는 Spring Boot 1.x 버전에서 사용되던 것으로, Spring Boot 2.x 이상부터는 해당 패키지가 삭제되고 완전히 다른 패키지와 클래스로 대체되었습니다. 따라서 Spring Boot 2 이상 환경에서 기존 1.x용 클래스를 import 하면 "package ... does not exist" 오류가 발생합니다.
해결 방법
TomcatEmbeddedServletContainer 대신 org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory 클래스를 사용해야 합니다.
import 문을 다음과 같이 변경하세요:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
기존에 EmbeddedServletContainerCustomizer를 사용했다면, Spring Boot 2.x부터는 WebServerFactoryCustomizer<TomcatServletWebServerFactory>를 사용하여 커스터마이징합니다.
예시 코드:
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class CustomTomcatConfig implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setPort(9090);
factory.addAdditionalTomcatConnectors(connector);
}
}
build.gradle 또는 pom.xml에 spring-boot-starter-web과 spring-boot-starter-tomcat 의존성이 포함되어 있는지 확인하세요.
요약
| org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer | org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory |
| EmbeddedServletContainerCustomizer | WebServerFactoryCustomizer<TomcatServletWebServerFactory> |
이렇게 변경하면 해당 import 오류가 해결되고 Spring Boot 2.x 이상 환경에 맞게 톰캣 내장 서버를 설정할 수 있습니다
근데 잘 안되서..
ai assistant 로 돌려서 이 버전으로 적용함.
/*@Profile("local")
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
log.debug("LOCAL======================================");
return new TomcatEmbeddedServletContainerFactory() {
@Override
//protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
protected TomcatServletWebServerFactory getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context){
ContextResource resource = null;
try {
resource = new ContextResource();
resource.setName("jdbc/evl");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", dbDriverClassName);
resource.setProperty("url", dbJdbcUrl);
resource.setProperty("username", dbUserName);
resource.setProperty("password", aes256.AES_Decode(dbPassword));
} catch (Exception e) {
e.printStackTrace();
}
context.getNamingResources().addResource(resource);
}
};
}*/
@Profile("local")
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
log.debug("LOCAL======================================");
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
try {
resource.setName("jdbc/evl");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", dbDriverClassName);
resource.setProperty("url", dbJdbcUrl);
resource.setProperty("username", dbUserName);
resource.setProperty("password", aes256.AES_Decode(dbPassword));
} catch (Exception e) {
e.printStackTrace();
}
context.getNamingResources().addResource(resource);
}
};
factory.addContextCustomizers(context -> {
// 톰캣 JNDI 활성화 및 추가 설정 필요시 여기에 추가
});
return factory;
}
빌드 후 다시 돌려본다.
계속 오류 나서 아래 소스 부분 변경했음.
//250507,ksko boot 1.5.x -> 2.x 변경에 따른 적용
/*@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/WEB-INF/views/error/error.jsp"));
container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/WEB-INF/views/error/error.jsp"));
container.addErrorPages(new ErrorPage("/WEB-INF/views/error/error.jsp"));
}
};
}*/
//250507,ksko ErrorPage import 경로 변경
//`org.springframework.boot.context.embedded.ErrorPage` -> `org.springframework.boot.web.server.ErrorPage`
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
return factory -> {
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/WEB-INF/views/error/error.jsp"));
factory.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/WEB-INF/views/error/error.jsp"));
factory.addErrorPages(new ErrorPage("/WEB-INF/views/error/error.jsp"));
};
}
public class Application extends SpringBootServletInitializer {
부분에서 오류가 난다 ai assistant 통해 해결한다.

1. 패키지 변경 확인
SpringBootServletInitializer의 import 경로가 다음과 같이 변경되었습니다.
- 1.5.x:
org.springframework.boot.web.support.SpringBootServletInitializer - 2.x:
org.springframework.boot.web.servlet.support.SpringBootServletInitializer
수정하고 다시 돌렸다.
Execution failed for task ':***-evaluation-web:processResources'.
> Entry static/css/calendar-ui.css is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/8.6/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
오류 원인
Gradle 빌드 과정에서 static/css/calendar-ui.css 파일이 여러 소스에서 중복되어 복사되려고 할 때, 중복 파일 처리 방식(duplicatesStrategy)이 지정되지 않아 발생하는 오류입니다. Gradle 7.x 이상에서는 중복 파일이 있을 경우 명시적으로 처리 전략을 지정해야 합니다.
해결 방법
build.gradle 파일에 아래와 같이 processResources 태스크에 duplicatesStrategy 옵션을 추가하세요.
tasks.named('processResources') {
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE // 또는 EXCLUDE
}
==> web 프로젝트 내 위 옵션 추가한다. 실행했다... 빨간색은 안나는데 아래와같이 오류가 난다.
21:50:40 WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'characterEncodingFilter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration; factoryMethodName=characterEncodingFilter; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class]] for bean 'characterEncodingFilter': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=application; factoryMethodName=characterEncodingFilter; initMethodName=null; destroyMethodName=(inferred); defined in com.***.evaluation.Application] bound.
21:50:40 INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
21:50:40 ERROR o.s.b.d.LoggingFailureAnalysisReporter
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'characterEncodingFilter', defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class], could not be registered. A bean with that name has already been defined in com.***.evaluation.Application and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
종료 코드 0(으)로 완료된 프로세스
오류 원인
이 에러는 characterEncodingFilter라는 이름의 Bean이 두 번 등록되어 발생합니다. 하나는 Spring Boot의 자동 설정(HttpEncodingAutoConfiguration)에서, 다른 하나는 직접 만든 코드(com.***.evaluation.Application)에서 등록되고 있습니다.
Spring Boot 2.1 이상에서는 Bean 이름이 중복될 경우 기본적으로 덮어쓰기가 금지되어 있어, 이럴 때 BeanDefinitionOverrideException이 발생합니다.
해결 방법
1. Bean 이름 중복 제거
- 직접 등록한 characterEncodingFilter Bean을 삭제하거나 이름을 변경하세요.
- 대부분의 경우 Spring Boot의 자동 설정만으로도 인코딩 필터가 잘 동작하므로, 직접 등록이 불필요하다면 삭제하는 것이 좋습니다.
2. Bean 덮어쓰기 허용 설정
- 정말 직접 등록이 필요한 경우, application.properties에 아래 설정을 추가하면 덮어쓰기가 허용되어 오류가 사라집니다:
spring.main.allow-bean-definition-overriding=true
단, 이 방법은 권장되는 방식은 아니며, 중복 Bean 등록의 원인을 먼저 확인하는 것이 좋습니다
ai assistant 로 보니
원인 설명:
Spring Boot 2.x부터는 같은 이름의 Bean이 중복될 경우, Bean Overriding이 기본적으로 금지되어 있습니다.
그런데 characterEncodingFilter라는 Bean이
- SpringBoot의 기본 자동설정(HttpEncodingAutoConfiguration)
- Application.java의 커스텀 Bean
에서 각각 중복 정의되어 충돌이 발생한 것입니다.
해결 방법
1. Application.java에서 중복 Bean 제거
characterEncodingFilter Bean은 자동으로 등록되므로, Application.java에서 직접 Bean을 만들 필요가 없습니다.
아래 부분을 주석처리(또는 삭제)하세요.
// 삭제 또는 주석 처리하세요!
@Bean
public Filter characterEncodingFilter() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
Spring Boot 기본 설정으로 충분합니다.
필요하다면 application.properties에서 다음과 같이 설정(NOT 필수, 참고용):
spring.web.encoding.charset=UTF-8
spring.web.encoding.enabled=true
spring.web.encoding.force=true
2. bean 이름 변경(비추천, 권장X)
만약 커스텀 설정이 꼭 필요하다면, Bean 이름을 변경해서 자동등록 bean과 충돌을 피할 수 있습니다.
@Bean(name = "myCharacterEncodingFilter")
public Filter myCharacterEncodingFilter() {
...
}
하지만 가장 좋은 방법은 1번 방식(불필요한 중복 제거)입니다.
정리
- SpringBoot가 자동으로 등록하는 characterEncodingFilter Bean이 이미 있습니다.
- Application.java에서 중복 정의한 Bean을 삭제(또는 주석)하세요.
- 별도 custom이 필요하다면 이름을 바꿔 등록하세요(일반적으로 필요 없음).
이렇게 수정하면 오류가 해결될 것입니다.
추가 도움이 필요하시면 언제든 말씀해 주세요!
==> 해당부분 주석처리 하자.
참고
Spring Boot 2.x의 기본 CharacterEncodingFilter 설정
- Encoding 기본값: UTF-8
- 강제 적용 여부(forceEncoding): 기본값은 true
- Bean 활성화: 기본적으로 활성화(별도 비활성 설정 없으면 등록됨)
근거 코드(공식 문서 및 소스)
spring-boot-autoconfigure의 HttpEncodingProperties에서 default 값:
private Charset charset = StandardCharsets.UTF_8;
private boolean force = true;
즉, 에 아무 설정도 하지 않더라도
UTF-8로 force 옵션이 켜져서 무조건 UTF-8로 요청/응답이 인코딩됩니다. application.properties
요약
- Spring Boot 2.x부터 기본 인코딩은 UTF-8이며, 강제 적용됩니다.
- 별도로 spring.web.encoding.charset 또는 관련 설정을 바꾸지 않으면
항상 UTF-8로 동작합니다.
===============
다시 실행해 보았다. 역시 오류났다.
Description:
The dependencies of some of the beans in the application context form a cycle:
evaluationInterceptor (field cohttp://m.***.evaluation.service.task.TaskService cohttp://m.***.evaluation.config.EvaluationInterceptor.taskService)
┌─────┐
| taskService (field cohttp://m.***.evaluation.service.peerFb.TaskPeerFbPopService cohttp://m.***.evaluation.service.task.TaskService.taskPeerFbPopService)
↑ ↓
| taskPeerFbPopService (field cohttp://m.***.evaluation.service.task.TaskService cohttp://m.***.evaluation.service.peerFb.TaskPeerFbPopService.taskService)
└─────┘
🔎 오류 원인:
오류 메시지는 순환 의존성(circular dependency) 문제를 설명합니다.
- evaluationInterceptor → taskService → taskPeerFbPopService → 다시 taskService
즉,
- evaluationInterceptor가 taskService를 주입받음
- taskService가 taskPeerFbPopService를 주입받음
- 그런데 taskPeerFbPopService도 다시 taskService를 주입받음
이렇게 되면 스프링이 객체 생성 시 서로를 계속 참조하게 되어
Bean 생성이 끝나지 않는 순환(cycle)이 발생하게 됩니다.
💡 해결 방법
1. 설계 개선(순환 의존 제거) — 가장 근본적인 방법
- 서비스 설계가 순환참조 없이 분리되게 리팩토링하는 것이 가장 바람직합니다.
- 에서 꼭 를 직접 주입받아야 하는지,
반대로 에서 꼭 를 주입받아야 하는지
비즈니스 필요성을 검토해보세요. TaskServiceTaskPeerFbPopServiceTaskPeerFbPopServiceTaskService
- 에서 꼭 를 직접 주입받아야 하는지,
- 예를 들어, 한 쪽만 인터페이스를 사용하고 콜백이나 이벤트, Setter 주입 등으로 바꿀 수도 있습니다.
2. @Lazy 사용
- 부득이하게 순환 의존이 반드시 필요하다면, 한쪽 의존성에 @Lazy를 붙이는 방법도 있습니다.
- 예시:
// TaskService 안에서
@Autowired
@Lazy
private TaskPeerFbPopService taskPeerFbPopService;
또는
// TaskPeerFbPopService 안에서
@Autowired
@Lazy
private TaskService taskService;
- 이렇게 하면, 해당 Bean은 실제 사용될 때까지 초기화를 미룹니다.
- 하지만 구조적 해결이 아니므로 되도록 설계 개선을 권장합니다.
3. Setter/필드 주입 대신 생성자 주입 사용
- 일반적으로 생성자 주입을 사용하면, 스프링이 순환 의존을 더 일찍 감지하며
setter나 필드 주입보다 문제 파악이 쉽습니다. - 그러나 생성자 주입만으로 순환 문제는 해결되지 않고, 구조 개선이 필요합니다.
🚦 정리
- 제일 좋은 방법: 설계를 재검토해서 순환 의존 관계를 없애세요.
- 부득이할 경우: 한 쪽 필드에 @Lazy 추가.
- 실제 코드 사례를 보여주면 더 구체적으로 개선 방법을 안내해 드릴 수 있습니다!
네, spring.main.allow-circular-references=true 설정을 통해
Spring Boot 2.6 이상에서는 순환 의존성 오류를 일시적으로 우회할 수 있습니다.
📍 spring.main.allow-circular-references=true 설명
- 이 프로퍼티를 application.properties나 환경변수에 추가하면,
- 스프링이 순환 참조(circular dependency) 상황에서도 예외를 발생시키지 않고
강제로 Bean을 생성합니다. - 즉, "순환 의존성"이 있어도 애플리케이션이 실행됩니다.
spring.main.allow-circular-references=true
⚠️ 주의사항 및 권장사항
- 비추천!
이 옵션은 임시 방편입니다.
구조적으로 순환 의존성이 있으면(특히 서비스 → 서비스 간),
유지보수와 확장에 매우 불리하고,
나중에 예기치 않은 버그 또는 테스트 어려움이 생길 수 있습니다. - 권장방식:
가능한 한- 서비스의 순환 의존관계 자체를 설계 수정(분리/리팩토링/콜백 혹은 이벤트 등)
- 위에서 안내한 @Lazy, setter 주입 등으로 부분 우회
- Spring Boot 2.6부터 기본 false(이전에는 true였음 → 최근 spring에서는 더 엄격하게 관리)
결론
- 급하게 돌아가야 한다면
- spring.main.allow-circular-references=true 하면 동작은 합니다.
- 장기적으로는
- 순환 의존 구조를 반드시 없애야 합니다.
⚠️ 실제로 서비스 운영/배포 전에는 설계 개선이 우선임을 꼭 명심하세요!
web, admin 프로젝트 내 application.properties 내 아래와 같이 추가함
#250507,ksko springboot 1.5.x > 2.x bean circular dependency passing setting (Not recommended)
spring.main.allow-circular-references=true
다시 돌려보자... 오류는 안나는데.. 이거 뭐냐 ㅋㅋ;; 집가자 ㅋㅋ;;


gradle 빌드 하고 다시 실행해보고 안되면 찐 집간다.
web 프로젝트는 오류는 안났는데 실행이 안되고,
어드민은
D:\ksko\workspace\***-evaluation-vup\***-evaluation-admin\src\main\java\com\***\evaluation\Application.java:16: error: package org.springframework.boot.context.embedded does not exist
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
하 ㅋㅋㅋ 맨처음부터 다시해야하나 ㅋㅋ;;
일단 오늘은 여기까지..
250508 저녁이다 다시 시작이다.
이거.. 실행했는데 오류는 안되는거다...
우선 뭐땜에 안되는지 발견이 안되서,
AI 가 알려주는 것들 1.5.x -> 2.x 변경 필요한 것 부분부분 수정한다.
application.properties
1.5.x → 2.x 업그레이드시 필요한 점
1. 코드 구조(주요변경 없음)
위 코드(뷰리졸버 설정)는 1.5.x와 거의 동일하게 2.x에서도 동작합니다. Spring MVC의 기본 인터페이스, 클래스가 바뀌지 않았기 때문이에요.
→ 따라서 "네가 선택한 소스대로" 사용해도 API 변경이 없어 문제는 없습니다.
2. 주의할 점 & 자동설정
- Spring Boot 2.x에서는 JSP 지원이 기본적으로 비추천(deprecated 아님)됩니다.
- spring-boot-starter-web과 tomcat-embed-jasper 설정은 문제없으나, 배포 방식/구성이 맞는지 확인 필요.
3. properties 변경점
- spring.http.multipart.* → deprecated
Spring Boot 2.x부터는 다음과 같이 변경해야 합니다.
spring.servlet.multipart.max-file-size
spring.servlet.multipart.max-request-size
- application.properties의 나머지는 그대로 사용 가능하지만, 일부 옵션(예: error 관련) 등에서 namespace가 바뀌거나 제거된 항목이 있으니 Release Note를 보고 확인하면 좋아요!
==> 수정함.
4. Gradle Plugin 변경
- gradle 7.x부터 → archiveFileName으로 변경archiveName
이미 네 코드에서 이 부분은 변경해서 적용되어있으니 문제 없음.
==> 수정함.
5. circular dependency(순환 참조)
- spring.main.allow-circular-references=true
Spring 2.6.x 이후에는 디폴트가 false됩니다. 순환참조가 없도록 구조개선 권장되지만, 일시적으론 설정으로 허용할 수 있습니다.
==> 수정함.
6. Dependencies/호환성
- mybatis-spring-boot-starter, jackson 등의 라이브러리 각 버전이 Spring Boot 2.x 호환 버전인지 체크 필요
→ 마이그레이션 가이드/공식 호환표 참고!
이 뭐야 진짜 ㅠㅠ
찾다가
//250508,ksko compileOnly 대신 implementation 로 변경
//compileOnly "org.apache.tomcat.embed:tomcat-embed-jasper"
//`api` 또는 `implementation`으로 변경하면 내장 Tomcat 실행 시에도 JSP 컴파일러를 사용할 수 있게 됩니다.
//만약 WAR 파일로 패키징하여 외부 Tomcat에 주로 배포한다면, 빌드 프로파일을 분리하거나 최종 배포 환경에 맞춰 이 설정을 조정할 수 있습니다.
implementation "org.apache.tomcat.embed:tomcat-embed-jasper"
위처럼 되어있어서 compileOnly -> implementation 으로 수정하고 gradle 빌드 + 실행 해보자.
역시 안됨 ㅋㅋ 하 ㅋㅋ;;;
하나 더 수정했음
//250508,ksko compileOnly 대신 implementation 로 변경
//compileOnly "org.apache.tomcat.embed:tomcat-embed-jasper"
//`api` 또는 `implementation`으로 변경하면 내장 Tomcat 실행 시에도 JSP 컴파일러를 사용할 수 있게 됩니다.
//만약 WAR 파일로 패키징하여 외부 Tomcat에 주로 배포한다면, 빌드 프로파일을 분리하거나 최종 배포 환경에 맞춰 이 설정을 조정할 수 있습니다.
implementation "org.apache.tomcat.embed:tomcat-embed-jasper"
그래도 안된다...
그래서 일단 logback.xml 내 로컬 로그를 INFO -> DEBUG로 바꿔서 실행했다.
안된다 안돼 아 빡쳐 ㅠ
일단 종료
250529
28일날 한게 다 날라감.
29일 다시 시도
AI Assistant
CSS/JS 경로를 서버 실행 시 인식하지 못하는 문제와 해결 방법
원인 분석
코드를 확인한 결과, 주요 원인은 다음과 같습니다:
- @EnableWebMvc 애노테이션 사용: 주석처리 된 @EnableWebMvc 애노테이션이 이전에 사용되었던 것으로 보입니다. 이 애노테이션은 Spring Boot의 기본 정적 리소스 자동 설정을 완전히 비활성화합니다. [1]
- Spring Boot 버전 업그레이드: 코드 주석을 보면 Spring Boot 1.5에서 2.7로 업그레이드한 것으로 보입니다. 이 과정에서 정적 리소스 처리 방식이 변경되었습니다.
- 리소스 경로 구성: 현재 코드에서는 여러 리소스 경로를 설정했지만, 실제 파일 경로와 매핑이 올바르지 않을 수 있습니다.
해결 방법
1. 정적 리소스 위치 확인
Spring Boot 2.7에서는 기본적으로 다음 경로에서 정적 리소스를 찾습니다:
- classpath:/static/
- classpath:/public/
- classpath:/resources/
- classpath:/META-INF/resources/
먼저 CSS/JS 파일이 정확히 어디에 위치해 있는지 확인하세요.
2. WebMvcConfig 수정
현재 설정을 다음과 같이 수정해보세요:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 기본 정적 리소스 경로 매핑
registry.addResourceHandler("/**")
.addResourceLocations(
"classpath:/static/",
"classpath:/public/",
"classpath:/resources/",
"classpath:/META-INF/resources/"
)
.setCachePeriod(3600)
.resourceChain(true);
// 명시적인 CSS/JS 매핑 (필요한 경우)
registry.addResourceHandler("/css/**")
.addResourceLocations("classpath:/static/css/")
.setCachePeriod(3600);
registry.addResourceHandler("/js/**")
.addResourceLocations("classpath:/static/js/")
.setCachePeriod(3600);
}
3. application.properties/yml 설정 추가
application.properties 또는 application.yml 파일에 다음 설정을 추가하세요:
# 정적 리소스 경로 설정
spring.mvc.static-path-pattern=/**
spring.web.resources.static-locations=classpath:/static/,classpath:/public/,classpath:/resources/,classpath:/META-INF/resources/
4. @EnableWebMvc 주석 유지
현재 코드에서 @EnableWebMvc가 주석 처리된 것은 정확한 조치입니다. 이 애노테이션은 계속 주석 처리된 상태로 유지하세요. [2]
5. 파일 구조 확인
프로젝트의 파일 구조가 다음과 같은지 확인하세요:
src/
main/
resources/
static/
css/
your-css-files.css
js/
your-js-files.js
...
추가 확인 사항
- 디버깅 방법: 브라우저 개발자 도구에서 네트워크 탭을 열고 CSS/JS 파일이 어떤 URL로 요청되는지 확인하세요.
- 경로 이름 대소문자: URL 경로와 실제 디렉토리 이름의 대소문자가 일치하는지 확인하세요.
- 컨텐츠 타입 확인: 서버가 CSS/JS 파일을 올바른 MIME 타입으로 전송하는지 확인하세요.
- 캐시 비우기: 브라우저 캐시를 비워보세요.
이러한 변경 사항을 적용하면 정적 리소스 문제가 해결될 가능성이 높습니다. 추가적인 도움이 필요하시면 더 자세한 정보를 제공해 주세요.
나
지금 아직도 CSS JS 를 못읽어.. 혹시. 아래 addInterceptors 메서드 내 경로를 /resources/static/** 를 추가해줘야 되는거야?
AI Assistant
CSS/JS 파일 인식 문제 해결 방법
예, 인터셉터 설정에서 정적 리소스 경로를 제외해야 합니다. 인터셉터가 CSS/JS 요청을 가로채서 처리하는 것이 문제일 수 있습니다.
해결 방법: 인터셉터에서 정적 리소스 경로 제외하기
addInterceptors 메서드를 다음과 같이 수정하세요:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(certificationInterceptor)
.excludePathPatterns("/sso/**")
.excludePathPatterns("/healthCheck/**")
.excludePathPatterns("/css/**")
.excludePathPatterns("/js/**")
.excludePathPatterns("/images/**")
.excludePathPatterns("/static/**")
.excludePathPatterns("/resources/**");
registry.addInterceptor(evaluationInterceptor)
.addPathPatterns("/main/**")
.addPathPatterns("/myTask/**")
.addPathPatterns("/watching/**")
.addPathPatterns("/approvalTask/**")
.addPathPatterns("/boardMemberTask/**")
.addPathPatterns("/teamMemberTask/**")
.addPathPatterns("/taskPeerFeedback/**")
.addPathPatterns("/writePeerFb/**")
.addPathPatterns("/myPeerFb/**")
.addPathPatterns("/statistics/**")
.addPathPatterns("/userTssn/**")
.addPathPatterns("/leaderTssn/**")
.addPathPatterns("/officerTssn/**")
.addPathPatterns("/officerTssnFb/**")
.addPathPatterns("/resultTssn/**")
.addPathPatterns("/reward/**")
.addPathPatterns("/reviewResult/**")
.addPathPatterns("/bridge/**")
.addPathPatterns("/techTaskSkillReview/**")
.addPathPatterns("/kpi/**")
.addPathPatterns("/workspace/**")
.addPathPatterns("/peerFb/**")
.addPathPatterns("/review/**")
.addPathPatterns("/tssn/**")
.excludePathPatterns("/healthCheck/**")
.excludePathPatterns("/css/**")
.excludePathPatterns("/js/**")
.excludePathPatterns("/images/**")
.excludePathPatterns("/static/**")
.excludePathPatterns("/resources/**");
}
왜 이것이 문제인가요?
- 인터셉터와 정적 리소스 충돌: Spring MVC 인터셉터는 모든 요청을 가로채는데, 특별히 제외하지 않으면 정적 리소스 요청도 가로챕니다. [1]
- 인증 관련 문제: 특히 certificationInterceptor와 같은 인증 관련 인터셉터는 인증되지 않은 사용자의 정적 리소스 접근을 차단할 수 있습니다. [2]
- 경로 패턴 충돌: 인터셉터의 경로 패턴이 정적 리소스 URL과 충돌할 수 있습니다. [3]
추가 확인 사항
- 파일 위치 확인: CSS/JS 파일이 src/main/resources/static/css 및 src/main/resources/static/js 디렉토리에 정확히 위치해 있는지 확인하세요.
- 브라우저 개발자 도구 확인: 브라우저의 개발자 도구에서 네트워크 탭을 열고, CSS/JS 파일 요청 시 어떤 HTTP 상태 코드가 반환되는지 확인하세요:
- 404: 파일을 찾을 수 없음
- 403: 접근이 금지됨 (인터셉터 문제일 가능성 높음)
- 500: 서버 오류
- application.properties/yml 설정 확인: 다음 설정을 추가했는지 확인하세요:
spring.mvc.static-path-pattern=/**
spring.web.resources.static-locations=classpath:/static/,classpath:/public/,classpath:/resources/,classpath:/META-INF/resources/
이 변경사항들을 적용한 후 서버를 재시작하면 CSS/JS 파일이 제대로 인식될 것입니다. 인터셉터에서 정적 리소스 경로를 제외하는 것이 가장 중요한 해결책입니다.
추가 했더니. 됨.
하 ㅠ
이게 맞나?
실했엤는데 DB xml 파일 못읽음 에러 확인하자
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or in an application resource file: java.naming.factory.initial
이 오류는 MyBatis가 JNDI를 통해 데이터베이스 연결을 시도했으나, JNDI 설정이 올바르게 되어 있지 않아 발생한 것입니다.
원인 분석
- JNDI 설정 문제: 코드에서 이라는 JNDI 데이터소스를 사용하도록 설정되어 있지만, 실제 JNDI 컨텍스트가 올바르게 초기화되지 않았습니다. jdbc/evl
- Spring Boot 버전 업그레이드: 코드 주석을 보면 Spring Boot 1.5에서 2.7로 업그레이드한 것으로 보입니다. 이 과정에서 JNDI 설정 방식이 변경되었습니다.
- Tomcat 설정 문제: 임베디드 Tomcat에서 JNDI를 사용하기 위한 설정이 올바르게 되어 있지 않습니다.
해결 방법
1. Tomcat JNDI 설정 수정
메서드를 다음과 같이 수정해 보세요: tomcatFactory()
@Profile("local")
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
log.debug("LOCAL======================================");
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
try {
resource.setName("jdbc/evl");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", dbDriverClassName);
resource.setProperty("url", dbJdbcUrl);
resource.setProperty("username", dbUserName);
resource.setProperty("password", aes256.AES_Decode(dbPassword));
// 추가 필요한 속성
resource.setProperty("factory", "org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory");
resource.setProperty("initialSize", "5");
resource.setProperty("maxTotal", "20");
resource.setProperty("maxIdle", "10");
resource.setProperty("minIdle", "5");
} catch (Exception e) {
e.printStackTrace();
}
context.getNamingResources().addResource(resource);
}
};
// JNDI 활성화
factory.addContextCustomizers(context -> {
context.addParameter("java.naming.factory.initial", "org.apache.naming.java.javaURLContextFactory");
context.addParameter("java.naming.factory.url.pkgs", "org.apache.naming");
});
return factory;
}
다시 실행.
안됨
3. JNDI를 꼭 사용해야 하는 경우 (수정된 코드)
만약 JNDI 사용이 필요하다면, 다음과 같이 수정하세요:
@Profile("local")
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
log.debug("LOCAL======================================");
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
tomcat.enableNaming(); // JNDI 네이밍 활성화
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
// 데이터소스 리소스 설정
ContextResource resource = new ContextResource();
try {
resource.setName("jdbc/evl");
resource.setType(DataSource.class.getName());
resource.setProperty("factory", "org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory");
resource.setProperty("driverClassName", dbDriverClassName);
resource.setProperty("url", dbJdbcUrl);
resource.setProperty("username", dbUserName);
resource.setProperty("password", aes256.AES_Decode(dbPassword));
resource.setProperty("initialSize", "5");
resource.setProperty("maxTotal", "20");
resource.setProperty("maxIdle", "10");
resource.setProperty("minIdle", "5");
resource.setProperty("validationQuery", "SELECT 1");
resource.setProperty("testOnBorrow", "true");
} catch (Exception e) {
log.error("JNDI 리소스 설정 오류", e);
}
context.getNamingResources().addResource(resource);
}
};
}
위껄로 바꾸고 해도 안됨
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NamingException: Unexpected exception resolving reference [Root exception is java.sql.SQLException: Cannot create PoolableConnectionFactory (error parsing url : Optional parameter allowMultiQueries must be boolean (true/false or 0/1) was 'true?characterEncoding=UTF-8')]
### The error may exist in file [D:\ksko\workspace\***-evaluation-vup\***-evaluation-core\build\resources\main\mybatis\userMapper.xml]
### The error may involve userMapper.getLoginPassword
MariaDB JDBC URL 파라미터 오류 해결
오류 원인 분석
오류 메시지를 분석하면:
java.sql.SQLException: Cannot create PoolableConnectionFactory (error parsing url : Optional parameter allowMultiQueries must be boolean (true/false or 0/1) was 'true?characterEncoding=UTF-8')
문제점: 의 에서 URL 파라미터가 잘못 구성되어 있습니다. application.propertiesdb.jdbcUrl
현재 URL:
jdbc:log4jdbc:mariadb://111.11.111.111:3316/_prev?allowMultiQueries=true?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
문제: allowMultiQueries=true 뒤에 ?를 사용했는데, 이미 첫 번째 파라미터이므로 추가 파라미터는 &로 연결해야 합니다.
해결 방법
1. application.properties 수정
############ log4jdbc ################
db.driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
#mns - dev - URL 파라미터 구분자 수정
db.jdbcUrl=jdbc:log4jdbc:mariadb://111.111.111.111:3316/***_prev?allowMultiQueries=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
db.username=1111
db.password=1111
변경사항: ?characterEncoding=UTF-8를 &characterEncoding=UTF-8로 수정
다시 돌림 될거같음.
된다.. 스프링 부트 2.7 업그레이드 완료 ㅠㅠ




