LabHub

Tomcat & nginx 운영 · WAR 배포와 무중단 · 이론

WAR 배포의 실제와 병행 배포(Parallel Deployment)

LabHub 에서 이어서 보기

한 줄 요약

WAR 를 그냥 복사하는 배포에는 전개 중 404 라는 구멍이 있고, 톰캣은 이미 그 구멍을 메울 수단(##버전 병행 배포)을 갖고 있는데 대부분의 현장이 그것을 모른다.

왜 이게 문제인가

정지 배포는 안전하지만 그동안 서비스가 멈춘다. 무정지로 하려고 WAR 만 덮어쓰면 전개가 끝날 때까지 그 경로는 404 이고, 이 시간은 클래스가 많을수록 길어져 30 초를 넘기기도 한다. 짧다고 넘길 수 없는 이유는 그 30 초가 오픈 첫날 오전 아홉 시에 걸리기 때문이다.

게다가 실패가 조용하다. 복사 도중에 톰캣이 전개를 시작해 반쪽짜리 WAR 를 풀다 실패하면 로그에는 남지만 배포 스크립트의 종료 코드는 0 이다. 배포한 사람은 성공했다고 믿고 퇴근한다.

WAR 는 어떻게 배포되는가

webapps/order.war 를 복사하면 톰캣이 webapps/order/ 로 풀고 /order 경로로 서비스한다.
이게 autoDeploy="true" 의 동작이다. 편하지만 운영에서는 함정이 있다.

병행 배포 — 톰캣이 원래 갖고 있는 무중단 수단

톰캣에는 잘 안 알려진 기능이 있다. **파일명에 ##버전 을 붙이면
같은 컨텍스트 경로에 여러 버전을 동시에 올릴 수 있다.**

webapps/order##001.war   ← 기존 버전webapps/order##002.war   ← 새 버전

이 상태에서 톰캣은 이렇게 동작한다.

즉 세션을 끊지 않고 새 버전으로 넘어간다. L4 앞단에서 서버를 빼고 넣는
전통적인 무중단 배포가 불가능한 단일 WAS 환경에서 이건 꽤 쓸모 있는 카드다.

버전 문자열은 문자열 비교로 정렬되니 ##1, ##2, ##10 처럼 쓰면
##10##2 보다 앞으로 간다. ##001 처럼 0 을 채우거나
##2026-08-19_1430 같은 타임스탬프를 쓴다.

그래도 정지 배포를 하는 경우

병행 배포는 만능이 아니다. 아래 경우엔 못 쓴다.

그래서 실무 판단은 이렇다:
화면·로직만 바뀌면 병행 배포, 스키마·배치·전역 상태가 얽히면 정지 배포.

WAR 와 실행 가능 JAR 는 무엇이 다른가

요즘 신규 개발은 스프링부트 fat jar 로 하고, 기존 시스템은 WAR 다.
같은 조직 안에 둘이 공존하는 것이 흔한 상황이라 차이를 정리해 두면 좋다.

| 항목 | WAR + 외부 Tomcat | 실행 가능 JAR (내장 Tomcat) |
| --- | --- | --- |
| 배포 단위 | WAR 파일 | JAR 파일 |
| 톰캣 버전 | 서버 관리자가 관리 (여러 앱이 공유) | 앱이 들고 있음 (앱마다 다를 수 있음) |
| 포트 | server.xml | 실행 인자 / 프로퍼티 |
| 여러 앱 배치 | 한 WAS 에 여러 컨텍스트 | 프로세스를 여러 개 띄움 |
| 롤백 | 이전 WAR 로 교체 | 이전 JAR 로 프로세스 교체 |
| 무중단 | 병행 배포 또는 L4 | 프로세스 교체 + LB |
| 운영 표준 | WAS 기준 절차서 | 프로세스/컨테이너 기준 절차서 |

운영 조직의 표준 절차서가 어느 쪽으로 쓰여 있는가가 실제 선택을 좌우한다.
기술적으로 JAR 가 편해도, WAS 단위로 감시·기동·백업 절차가 표준화된 조직에서는
JAR 하나 때문에 절차를 새로 만들어야 한다. 그 비용이 기술 이점보다 클 수 있다.

배포 스크립트가 갖춰야 할 최소한

현장에서 쓸 만한 배포 스크립트는 이 정도는 한다.

1. 인자 검증 — WAR 파일이 실제로 존재하고 0바이트가 아닌지
2. 백업 — 현재 배포본을 타임스탬프 붙여 보관
3. 원자적 배치 — 임시 이름으로 복사 후 mv
4. 전개 대기 — 최대 N 초 동안 컨텍스트가 응답할 때까지 폴링
5. 검증 — 헬스체크 URL 이 200 이고 버전 문자열이 기대값인지
6. 실패 시 즉시 중단 — 5번이 실패하면 배포 성공으로 보고하지 않는다

4번의 "전개 대기"가 특히 중요하다. cp 직후에 curl 하면 아직 404 다.
그걸 실패로 판정해서 롤백하는 스크립트도 봤고, 반대로 대기 없이
"배포 완료"를 출력하고 끝나는 스크립트는 훨씬 더 많이 봤다.
후자는 실패한 배포를 성공으로 보고한다. 훨씬 나쁘다.

현장에서 만나는 모습

그래서 배포 스크립트가 갖춰야 할 최소한이 정해져 있다. 다른 이름으로 복사한 뒤 mv 로 원자적으로 이름을 바꾸고, 전개가 끝날 때까지 기다렸다가 실제 응답이 200 인지 확인하고 나서 종료 코드를 낸다. 복사 직후 바로 확인하면 아직 전개 중이라 실패하는데, 이걸 "배포 실패" 로 오해해 되돌리는 일도 흔하다.