온프레미스 개발환경

[6탄] WAR 배포 실패 2 - spring-web 누락 & tomcat-runtime

finvault 2026. 4. 1. 18:39

👈 이전 글: [5탄] WAR 배포 실패 1 - Logback 충돌


💡 트러블슈팅 랩: "사라진 spring-web을 찾아라"

5탄에서 로깅 충돌의 원인인 Logback을 도려내고 드디어 배포가 성공하는 줄 알았습니다.

하지만 JBoss 로그를 살펴보니, 분명 배포(Deploy)는 성공했다고 뜨는데 정작 스프링이 초기화되었다는 로그가 없습니다.

마치 껍데기만 배포되고 알맹이(Spring)는 쏙 빠진 상태입니다.

 

이번 6탄에서는 이 기이한 현상의 원인을 파헤치고, Spring Boot 4.0과 외장 WAS(JBoss) 간의 빌드 스펙 충돌을 완벽하게 교정해 보겠습니다.

 

01. 배포 실패 현상: 껍데기만 남은 WAR

로깅 문제를 해결한 후 배포를 진행하면 다음과 같은 로그가 뜹니다:

 

GRADLE TASK 시작1
GRADLE TASK 시작1

 

Gradle Tak 더블클릭
Gradle Tak 더블클릭

 

run
run

 

 

1.Add 버튼을 클릭 하여 그림 처럼 Clean ADD 버튼 bootWar 입력한다
2.Working Directory 부분은 Workspace 를 클릭 하여 항목을 선택한다
3.Run을 클릭 한다

 

 

빌드 성공 화면
빌드 성공 화면

 

 

INFO [io.undertow.servlet]
No Spring WebApplicationInitializer types detected on classpath
...
INFO [org.jboss.as.server]
Deployed "FinVault.war" (runtime-name: "FinVault.war")

 

"No Spring WebApplicationInitializer types detected on classpath" 스프링이 전혀 로드되지 않았다는 뜻입니다.

 

 

WAR 파일 직접 해부

의심스러운 마음에 빌드된 WAR 파일의 압축을 풀어 WEB-INF/lib 폴더를 확인합니다:

 

 

C:\projects\FinVault\workspace\FinVault\build\libs\FinVault-0.0.1-SNAPSHOT.war

확장자를 .zip으로 변경 후 압축 해제

WEB-INF\lib 폴더 진입

결과:
spring-web.jar ← 없음!
spring-context.jar ← 없음!
핵심 Spring 라이브러리 실종!

 

C:\projects\FinVault\workspace\FinVault\build\libs 폴더 내용
C:\projects\FinVault\workspace\FinVault\build\libs 폴더 내용

 

분명 build.gradle에는 spring-boot-starter-web이 선언되어 있는데, 왜 WAR 안에는 들어가지 않았을까요?

 

Project and External Dependencies
Project and External Dependencies

 

💡 STS Project and External Dependencies에서 보면 spring-web jar는 의존성으로 정상 등록되어 있습니다. 하지만 실제 빌드된 WAR 파일 안에는 포함되지 않는 상태! 즉, 의존성은 있는데 패키징에서 빠진 것입니다.

 

 

 

🧠 02.  원인 분석 (Why?)

원인은 두 가지가 복합적으로 작용했습니다.

 

원인 1. 광범위한 Exclude의 부작용

 

Plaintext
 
[5탄에서 적용한 설정]
configurations {
    all {
        exclude group: 'ch.qos.logback'
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}
↓
configurations.all → 모든 의존성 트리에 전역 적용!
↓
spring-boot-starter-web이 내부적으로 spring-web을 가져오는 과정에서
exclude 설정이 너무 광범위하게 작용
↓
Spring 핵심 라이브러리까지 제외 됨!

 

 

원인 2. Spring Boot 4.0 모듈화 구조 변경

Spring Boot를 외장 JBoss에 올릴 때, 기존에는 아래와 같이 설정했습니다:

// ❌ 기존 방식 (Spring Boot 3.x 이하)
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'

 

 

Spring Boot 4.0은 새로운 모듈식 설계를 도입했습니다. 기존의 큰 jar 대신 작고 집중된 모듈들로 분리되었으며, 이 방식이 spring-web 모듈의 스코프(Scope)까지 건드려 WAR 패키징 과정에서 누락되는 현상이 발생합니다.

 

 

충돌 요약

원인 내용 영향
configurations.all exclude 너무 광범위한 제외 설정 spring-web 등 핵심 라이브러리 누락
tomcat 의존성 방식 Spring Boot 4.0 모듈화 미반영 WAR 패키징 스코프 오류 발생

 

 

03. 해결 방안: build.gradle 의존성 재정렬

Step 1. 배포 찌꺼기 완전 초기화

설정이 꼬였을 때는 물리적인 삭제가 가장 확실합니다.

 

[빌드 결과물 삭제]

C:\projects\FinVault\workspace\FinVault\build\libs\ 하위 WAR 파일 모두 삭제

[deployments 폴더 초기화]

C:\projects\was\jboss-eap-8.1\standalone\deployments\

- FinVault.war 삭제 - FinVault.war.deployed 삭제 후 새로 빈 파일 생성

 

 

Step 2. build.gradle 최종 수정

 

Groovy
 
plugins {
    id 'java'
    id 'war'
    id 'org.springframework.boot' version '4.0.5'
    id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.finvault'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}

repositories {
    mavenCentral()
}

dependencies {
    // 1. Web 스타터 의존성 (Logback exclude를 전역이 아닌 이 블록 안으로 한정!)
    implementation('org.springframework.boot:spring-boot-starter-web') {
        exclude group: 'ch.qos.logback'
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
    implementation 'org.springframework.boot:spring-boot-starter-log4j2'
    
    // 2. 🔥 [핵심 변경] tomcat → tomcat-runtime
    // providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' ← ❌ 기존
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat-runtime' // ← ✅ 변경
    
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

 

 

핵심 변경사항 요약:

항목 변경 전 변경 후
exclude 범위 configurations.all (전역) starter-web 블록 안으로 한정
tomcat 의존성 spring-boot-starter-tomcat spring-boot-starter-tomcat-runtime
근거 - Spring Boot 4.0 Migration Guide

 

 

 

Spring Boot 4.0 Migration Guide의 핵심: WAR 배포 시 spring-boot-starter-tomcat-runtime을 사용해야 Spring Boot 4.0의 모듈화 구조에서 spring-web 등 핵심 라이브러리가 WAR에 올바르게 패키징됩니다.

 

 

Step 3. Gradle Refresh

 

FinVault 프로젝트 우클릭

Gradle → Refresh Gradle Project

하단 진행 표시줄 완료 확인

 

Refresh Gradle Project
Refresh Gradle Project

 

 

 

04. Gradle Task를 이용한 수동 배포 검증

STS의 자동 배포를 믿기 전에, 먼저 Gradle 명령어로 확실하게 빌드하여 WAR 파일 상태를 육안으로 검증합니다.

 

Step 1. Gradle Run Configuration 설정

 

프로젝트 루트(FinVault) 우클릭

Run As → Run Configurations

Gradle Task 더블클릭 (새 설정 생성)

Name: JBoss_Deploy (명확한 이름 설정)
Gradle Tasks: clean bootWar
Working Directory: Workspace 선택

Run 클릭

 

 

Run As
Run As

 

 

Gradle Task
Gradle Task

 

New Configuration 화면
New Configuration 화면

 

 

1.Add 버튼을 클릭 하여 그림 처럼 Clean ADD 버튼 bootWar 입력한다
2.Working Directory 부분은 Workspace 를 클릭 하여 항목을 선택한다
3.Run을 클릭 한다
 
 

Step 2. 빌드 성공 확인

 

 
 

Task :clean
Task :compileJava
Task :processResources
Task :classes
Task :resolveMainClassName
Task :bootWar

BUILD SUCCESSFUL in 1s
5 actionable tasks: 5 executed
Gradle Version: 9.4.1
Java Home: C:\projects\FinVault\bin\java\jdk21  ← 독립 JDK 21 확인!

 

빌드 성공 확인
빌드 성공 확인

 

Step 3. WAR 파일 내용 재검증

 

build\libs\FinVault-0.0.1-SNAPSHOT.war

.zip 확장자로 변경 후 압축 해제

WEB-INF\lib 폴더 확인

spring-web.jar ✅ 정상 포함 확인!
spring-context.jar ✅ 정상 포함 확인!

 

spring 정상 패킹
spring 정상 패킹

 

 

Step 4. JBoss 수동 배포 (dodeploy)

 

생성된 FinVault-0.0.1-SNAPSHOT.war 복사

C:\projects\was\jboss-eap-8.1\standalone\deployments\ 이동

파일명 변경: FinVault-0.0.1-SNAPSHOT.war → FinVault.war

빈 파일 생성: FinVault.war.dodeploy

 

FinVault-0.0.1-SNAPSHOT.war
FinVault-0.0.1-SNAPSHOT.war

 

빈 파일 생성: FinVault.war.dodeploy
빈 파일 생성: FinVault.war.dodeploy
FinVault.war 로 변경
FinVault.war 로 변경

 

 

💡 JBoss 배포 메커니즘: JBoss는 .dodeploy 파일이 감지되는 순간 Hot Deploy를 시작하고, 배포가 성공하면 이 파일을 .deployed로 자동 변경합니다. 배포가 실패하면 .failed로 변경되어 즉시 확인 가능합니다.

 

 

05. 이번 탄 트러블슈팅 전체 흐름

시도 변경 내용 결과
5탄 configurations.all exclude 적용 spring-web 누락 발생
1차 수정 exclude 범위를 starter-web에 한정 여전히 실패
2차 수정 tomcat → tomcat-runtime 변경 WAR에 spring-web 정상 포함 성공!

 

 

 

06. 이번 탄 완료 체크리스트

  • [ ] server.log에서 "No Spring WebApplicationInitializer" 확인
  • [ ] WAR 파일 압축 해제 → spring-web 누락 확인
  • [ ] 원인 분석 (configurations.all + tomcat 의존성)
  • [ ] build.gradle exclude 범위 starter-web으로 한정
  • [ ] tomcat → tomcat-runtime 변경 (Spring Boot 4.0 가이드)
  • [ ] 빌드 찌꺼기 완전 초기화
  • [ ] Gradle Refresh 후 clean bootWar 재빌드
  • [ ] WAR 파일 재검증 → spring-web 정상 포함 확인
  • [ ] JBoss deployments 수동 배포
  • [ ] .dodeploy 빈 파일 생성

 

07. 다음 편 예고

드디어 spring-web 누락 이슈까지 완벽하게 잡아내고 WAR 파일이 100% 정상적으로 빌드되었습니다.

하지만 매번 배포할 때마다 [WAR 파일 복사] → [이름 변경] → [JBoss 폴더 이동] → [.dodeploy 파일 생성] 이라는 노가다를 반복할 수는 없습니다. 엔터프라이즈 환경에서 수동 배포는 인적 오류(Human Error)의 지름길입니다.

이어지는 [7탄] Gradle 기반 JBoss 자동 배포 스크립트 완성에서는, 방금 우리가 수동으로 했던 모든 삽질을 클릭 한 번에 자동으로 처리해 주는 엔터프라이즈급 커스텀 빌드 스크립트를 완성합니다. 사전 조건 체크, 백업, 배포 성공 여부 확인까지 모든 과정을 자동화하여 CI/CD의 첫 단추를 꿰어 보겠습니다.

👉 [7탄] Gradle 기반 JBoss 자동 배포 스크립트 완성 보러가기