WildFly·JBoss WAR 배포 시 WFLYSRV0153 PARSE 오류 원인과 해결 방법

반응형

WildFly·JBoss WAR 배포 시 WFLYSRV0153 PARSE 오류 원인과 해결 방법

WildFly 또는 JBoss EAP에 WAR 파일을 배포할 때 다음과 같은 오류가 발생할 수 있습니다.

ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4)
MSC000001: Failed to start service
jboss.deployment.unit."test.war".PARSE:

org.jboss.msc.service.StartException:
WFLYSRV0153: Failed to process phase PARSE
of deployment "test.war"
핵심 판단:

배포 디렉터리에 WAR 파일이 2개 있었고, 하나를 삭제한 뒤 정상 배포되었다면 두 애플리케이션 사이의 배포 이름, 컨텍스트 경로, 모듈 또는 서버 자원 충돌 가능성이 높습니다.

다만 WFLYSRV0153 자체는 최종 원인을 나타내는 오류가 아닙니다. 정확한 원인은 로그 아래쪽에 있는 마지막 Caused by: 메시지에서 확인해야 합니다.

1. 오류 메시지가 의미하는 것

WildFly의 배포 과정은 여러 단계로 진행됩니다. 대표적으로 다음과 같은 단계가 있습니다.

STRUCTURE
PARSE
DEPENDENCIES
CONFIGURE_MODULE
POST_MODULE
INSTALL

이번 오류의 PARSE는 서버가 WAR 내부의 배포 기술자와 메타데이터를 분석하는 단계입니다.

이 단계에서는 다음 파일과 구성요소가 처리될 수 있습니다.

  • WEB-INF/web.xml
  • WEB-INF/jboss-web.xml
  • WEB-INF/jboss-deployment-structure.xml
  • META-INF/MANIFEST.MF
  • Servlet, CDI, JPA, EJB 관련 XML 및 애노테이션 정보
  • WAR 내부에 포함된 JAR의 메타데이터

WFLYSRV0153은 해당 단계에서 예외가 발생했다는 상위 메시지입니다. 따라서 아래 한 줄만으로는 XML 오류인지, 중복 배포인지, 라이브러리 문제인지 확정할 수 없습니다.

2. WAR 파일 하나를 삭제하자 배포된 이유

관찰된 현상을 기준으로 보면 WAR 파일 자체가 무조건 손상된 것보다는, 두 WAR가 동시에 배포될 때 충돌하는 구조였을 가능성이 큽니다.

WAR 파일이 2개일 때 발생할 수 있는 주요 충돌
원인 설명 확인할 로그
같은 배포 이름 동일하거나 유사한 이름으로 서버에 중복 등록된 경우입니다. DuplicateServiceException, already registered
같은 Context Root 두 WAR가 동일한 URL 경로를 사용하려고 한 경우입니다. WFLYUT0105, DuplicateServiceException, Undertow 관련 오류
동일 애플리케이션의 구버전과 신버전 test.wartest-1.0.war처럼 같은 애플리케이션을 두 번 배포한 경우입니다. JNDI, EJB, persistence unit 또는 서비스 중복 등록 메시지
배포 마커 파일 불일치 삭제된 WAR의 .deployed, .failed, .dodeploy 파일이 남아 있는 경우입니다. Deployment Scanner 관련 메시지
WAR 내부 설정 중복 두 애플리케이션이 같은 EJB 이름, JNDI 이름, 데이터소스 또는 영속성 단위를 등록하는 경우입니다. already registered, duplicate, WFLYNAM

WildFly는 상위 배포 모듈에 배포 파일명을 기반으로 한 이름을 사용합니다. 또한 배포 스캐너는 .deployed, .failed, .dodeploy와 같은 마커 파일로 배포 상태를 관리합니다.

3. 가장 가능성이 높은 원인

3.1 같은 애플리케이션의 WAR가 두 개 있었던 경우

예를 들어 배포 디렉터리가 다음과 같았다면 충돌 가능성이 있습니다.

$JBOSS_HOME/standalone/deployments/
├── test.war
├── test-1.0.0.war
├── test.war.deployed
└── test-1.0.0.war.failed

파일 이름은 다르더라도 두 WAR 내부의 설정이 같을 수 있습니다.

  • jboss-web.xmlcontext-root가 동일함
  • web.xml의 애플리케이션 이름이 동일함
  • 같은 EJB 또는 JNDI 이름을 사용함
  • persistence.xml의 persistence unit 이름이 동일함
  • 같은 서버 자원을 중복 등록함

실제 WildFly 배포 오류에서도 동일한 서비스가 이미 등록되어 있을 때 DuplicateServiceExceptionalready registered가 하위 원인으로 기록될 수 있습니다.

3.2 두 WAR의 Context Root가 같았던 경우

다음처럼 두 애플리케이션이 같은 경로를 사용하면 충돌할 수 있습니다.

<!-- 첫 번째 WAR의 WEB-INF/jboss-web.xml -->
<jboss-web>
    <context-root>/test</context-root>
</jboss-web>
<!-- 두 번째 WAR의 WEB-INF/jboss-web.xml -->
<jboss-web>
    <context-root>/test</context-root>
</jboss-web>

두 애플리케이션을 모두 배포해야 한다면 서로 다른 경로로 변경해야 합니다.

<!-- 첫 번째 WAR -->
<jboss-web>
    <context-root>/test</context-root>
</jboss-web>

<!-- 두 번째 WAR -->
<jboss-web>
    <context-root>/test-admin</context-root>
</jboss-web>

3.3 파일명 또는 확장자가 잘못된 경우

제시된 로그에는 다음과 비슷한 표현이 포함되어 있습니다.

jboss.deployment.unit."test,war".PARSE

실제 로그에도 test,war처럼 쉼표가 들어가 있었다면 파일명이 잘못되었는지 확인해야 합니다.

잘못된 예
test,war

정상 예
test.war
주의:

질문을 작성하면서 마침표가 쉼표로 입력된 것이라면 이 항목은 무시해도 됩니다. 실제 서버 파일명과 server.log 원문을 기준으로 판단해야 합니다.

3.4 남아 있는 배포 마커 파일 문제

WildFly의 파일 시스템 배포 스캐너는 WAR 옆에 상태 파일을 생성합니다.

test.war.deployed
test.war.failed
test.war.dodeploy
test.war.isdeploying
test.war.pending
test.war.undeployed

.failed 파일에는 배포 실패 원인 일부가 기록될 수 있습니다. 또한 이전 WAR를 삭제한 뒤 마커 파일만 남아 있으면 배포 상태가 혼란스러워질 수 있습니다. WildFly 공식 관리 문서에서도 이러한 마커 파일이 배포 스캐너의 상태 관리에 사용된다고 설명합니다.

4. 권장 조치 방법

조치 1. 배포 디렉터리 정리

WildFly를 정상 종료한 다음 배포 디렉터리를 확인합니다.

cd "$JBOSS_HOME/standalone/deployments"
ls -al

배포할 WAR 하나만 남기고, 해당 애플리케이션과 관련된 오래된 마커 파일을 정리합니다.

rm -f test.war.failed
rm -f test.war.deployed
rm -f test.war.dodeploy
rm -f test.war.isdeploying
rm -f test.war.pending
rm -f test.war.undeployed

운영 서버에서는 파일을 삭제하기 전에 현재 배포 대상과 롤백 파일을 별도 경로에 백업하는 것이 안전합니다.

조치 2. 두 WAR의 내부 설정 비교

WAR 파일은 ZIP 형식이므로 압축을 풀지 않고 목록을 확인할 수 있습니다.

jar tf test.war
jar tf test-old.war

임시 디렉터리에 각각 압축을 해제합니다.

mkdir -p /tmp/war-check/test
mkdir -p /tmp/war-check/test-old

cd /tmp/war-check/test
jar xf /deploy/test.war

cd /tmp/war-check/test-old
jar xf /deploy/test-old.war

다음 파일을 우선 비교합니다.

diff -u \
  /tmp/war-check/test/WEB-INF/jboss-web.xml \
  /tmp/war-check/test-old/WEB-INF/jboss-web.xml

diff -u \
  /tmp/war-check/test/WEB-INF/web.xml \
  /tmp/war-check/test-old/WEB-INF/web.xml

find /tmp/war-check -name "persistence.xml" -print
find /tmp/war-check -name "jboss-deployment-structure.xml" -print

조치 3. WildFly에 등록된 배포 목록 확인

파일을 삭제했더라도 관리 모델에 배포 정보가 남아 있는지 확인합니다.

$JBOSS_HOME/bin/jboss-cli.sh --connect \
  --command="/deployment=*:read-resource"

간단히 배포 이름만 확인하려면 다음 명령을 사용할 수 있습니다.

$JBOSS_HOME/bin/jboss-cli.sh --connect \
  --command="deployment-info"

불필요한 이전 배포가 등록되어 있다면 정상적인 undeploy 절차로 제거합니다.

$JBOSS_HOME/bin/jboss-cli.sh --connect \
  --command="undeploy test-old.war"

조치 4. 두 WAR를 모두 사용해야 한다면 이름과 경로 분리

두 WAR가 서로 다른 애플리케이션이라면 최소한 다음 항목을 분리해야 합니다.

두 WAR 동시 배포 시 확인 항목
항목 WAR 1 예시 WAR 2 예시
WAR 파일명 test.war test-admin.war
Context Root /test /test-admin
EJB 이름 TestService TestAdminService
Persistence Unit testPU testAdminPU
JNDI 이름 java:/jdbc/TestDS java:/jdbc/TestAdminDS

조치 5. 로그의 마지막 Caused by 확인

현재 제공된 스택 트레이스는 중간까지만 포함되어 있습니다. 다음과 같이 오류 발생 지점 전후를 확인해야 합니다.

grep -n -A 80 -B 20 \
  'WFLYSRV0153.*test.war' \
  "$JBOSS_HOME/standalone/log/server.log"

압축된 로그까지 함께 확인하려면 다음과 같이 검색할 수 있습니다.

zgrep -n -A 80 -B 20 \
  'WFLYSRV0153.*test.war' \
  "$JBOSS_HOME"/standalone/log/server.log*

특히 아래 키워드를 찾습니다.

Caused by:
DuplicateServiceException
already registered
Duplicate
context root
ParseError
XMLStreamException
SAXParseException
ZipException
ClassNotFoundException
DeploymentUnitProcessingException
진짜 원인 찾는 방법:

첫 번째 WFLYSRV0153가 아니라, 해당 스택 트레이스의 가장 아래쪽에 있는 마지막 Caused by:를 확인합니다. 예를 들어 SAXParseException이면 XML 문제이고, DuplicateServiceException이면 중복 등록 문제입니다.

5. 원인별 추가 조치

DuplicateServiceException이 표시되는 경우

서비스, EJB, JNDI 또는 웹 컨텍스트가 중복된 상태입니다.

  1. 두 WAR의 jboss-web.xml에서 Context Root를 비교합니다.
  2. EJB 클래스의 @Stateless(name = "...") 또는 @Singleton(name = "...") 값을 확인합니다.
  3. persistence.xml의 persistence unit 이름을 비교합니다.
  4. 동일 애플리케이션의 이전 버전을 undeploy합니다.

SAXParseException 또는 XMLStreamException이 표시되는 경우

web.xml이나 JBoss 전용 XML 설정의 문법 또는 네임스페이스를 확인합니다.

xmllint --noout WEB-INF/web.xml
xmllint --noout WEB-INF/jboss-web.xml
xmllint --noout WEB-INF/jboss-deployment-structure.xml

PARSE 단계는 XML 및 배포 메타데이터 분석 중에도 실패할 수 있으므로, 두 번째 WAR를 삭제한 것이 직접적인 해결이 아니라 재배포 과정에서 문제가 우연히 사라진 것인지도 확인해야 합니다.

ZipException이 표시되는 경우

WAR 파일이 손상되었거나 서버가 복사 중인 파일을 읽었을 가능성이 있습니다.

unzip -t test.war
jar tf test.war > /dev/null

운영 중인 배포 디렉터리에 WAR를 직접 천천히 복사하기보다는 임시 이름으로 복사한 후 원자적으로 이름을 변경하거나, 관리 CLI를 사용해 배포하는 방법이 더 안전합니다. 최신 WildFly 문서도 파일 시스템 스캐너보다 관리 API를 통한 설치를 권장합니다.

cp test.war /tmp/test.war
mv /tmp/test.war "$JBOSS_HOME/standalone/deployments/test.war"

6. 최종 결론

현재 정황에서는 다음 순서로 판단할 수 있습니다.

  1. WAR 파일이 2개일 때만 실패했다.
  2. 하나를 삭제한 후 정상 배포되었다.
  3. 따라서 동일 애플리케이션의 중복 배포 또는 Context Root·EJB·JNDI·Persistence Unit 같은 서버 자원 충돌 가능성이 가장 높습니다.
  4. 다만 WFLYSRV0153은 상위 오류이므로, 최종 확정은 server.log의 마지막 Caused by:를 기준으로 해야 합니다.
권장 처리 순서
  1. 배포 디렉터리에 실제 WAR가 몇 개 있는지 확인합니다.
  2. 이전 WAR와 관련된 마커 파일을 정리합니다.
  3. CLI의 deployment-info로 등록된 배포를 확인합니다.
  4. 두 WAR의 Context Root와 내부 설정을 비교합니다.
  5. 로그의 마지막 Caused by:를 확인합니다.
  6. 같은 애플리케이션의 구버전이라면 한 개만 배포합니다.

FAQ

WFLYSRV0153은 정확히 어떤 오류인가요?

WildFly의 특정 배포 처리 단계가 실패했다는 공통 오류입니다. 원인 자체는 아니며, 이어지는 Caused by: 메시지를 확인해야 합니다.

WAR 파일 이름만 다르면 동시에 배포해도 되나요?

항상 그런 것은 아닙니다. 파일명이 달라도 Context Root, EJB 이름, JNDI 이름, persistence unit 또는 기타 서버 자원이 동일하면 충돌할 수 있습니다.

하나를 삭제하니 배포되었다면 해결된 것인가요?

같은 애플리케이션의 이전 버전을 실수로 함께 배포한 상황이라면 해결된 것입니다. 그러나 두 WAR를 모두 운영해야 한다면 충돌 항목을 찾아 각각 고유한 이름과 경로로 분리해야 합니다.

.failed 파일은 삭제해도 되나요?

실패 원인을 먼저 확인한 후 삭제할 수 있습니다. 자동 배포 모드에서는 .failed 파일을 제거하면 다시 배포 대상이 될 수 있으므로, 원인 수정 없이 삭제만 반복해서는 안 됩니다.

반응형