외장 서버(WAR) 방식의 단점과 내장 서버(JAR)의 등장

전통적인 웹 애플리케이션 개발 방식은 톰캣 같은 WAS를 별도로 설치하고 WAR 파일을 배포하는 외장 서버 방식이었다. 이 방식은 복잡한 설치 및 배포 과정, 개발 환경 설정의 어려움, 버전 관리의 불편함 등 여러 단점을 가졌다. 이러한 불편함을 해결하기 위해 WAS를 애플리케이션 코드 내부에 라이브러리 형태로 포함하여 main() 메서드 실행만으로 웹 서버까지 함께 구동하는 내장 서버 (Embedded Server) 방식이 등장했으며, 이는 현대 스프링 부트 개발의 근간이 된다

전통적인 WAR 배포 방식의 단점 (외장 서버)

  • WAS 별도 설치 및 관리: 톰캣과 같은 웹 애플리케이션 서버(WAS)를 개발 서버 및 운영 서버에 각각 다운로드하여 설치해야 했다. 이는 초기 설정 및 유지보수 부담을 가중시켰다
    • 엄밀히 말해 톰캣은 서블릿 컨테이너이며, 전통적인 WAS(WebLogic, WebSphere, JBoss 등)는 서블릿 컨테이너 + EJB 컨테이너 + 기타 엔터프라이즈 기능을 포함하는 더 넓은 개념이다. 여기서는 일반적으로 통용되는 의미로 WAS 용어를 사용한다
  • 복잡한 개발 환경 설정: 단순한 자바 애플리케이션은 main() 메서드 실행만으로 구동되지만, 웹 애플리케이션은 WAS와 WAR 파일을 연동하기 위한 복잡한 IDE(IntelliJ, Eclipse 등)이 필수적이었다
  • 복잡한 배포 과정: 개발된 코드를 WAR 파일로 빌드한 후, 이 WAR 파일을 WAS에 수동으로 전달하여 배포해야 했다. 서버 재시작 등의 과정이 얽혀 배포 절차가 번거롭고 오류 발생 가능성이 높았다
  • WAS 버전 관리의 어려움: WAS의 버전을 변경해야 할 경우, 각 서버에 설치된 WAS를 개별적으로 업데이트해야 하는 번거로움이 있다

내장 서버 (Embedded Server) 개념의 등장 배경

  • 오랜 기간 이러한 외장 서버 방식의 불편함에 대한 고민이 지속되었다. 핵심적인 아이디어는 “자바의 main() 메서드만 실행하면 웹 서버까지 같이 구동될 수 없을까?”였다. 톰캣 역시 자바로 만들어진 애플리케이션이므로, 톰캣을 마치 일반 자바 라이브러리처럼 애플리케이션 코드 안에 포함하여 사용할 수 있지 않을까 하는 생각해서 출발했다.
    • 내장 서버 개념 자체는 Jetty, Undertow 등이 이전부터 지원해왔으나, 스프링 부트(2013년 출시)가 이를 대중화하고 표준화하여 자바 웹 애플리케이션 개발의 패러다임을 바꾸어 놓았다

내장 서버 방식의 특징 (JAR 배포)

  • WAS의 라이브러리화: 톰캣과 같은 WAS를 더 이상 별도의 설치형 서버가 아닌, 자바 애플리케이션이 의존하는 하나의 라이브러리로 포함한다
  • 단일 JAR 파일 배포: 애플리케이션 코드를 포함한 다양한 라이브러리(WAS 라이브러리 포함)가 하나의 실행 가능한 JAR 파일로 빌드된다
  • 스프링 부트의 실행 가능한 JAR는 특수한 중첩 구조(nested JAR)를 가진다
    • BOOT-INF/classes/: 애플리케이션 클래스
    • BOOT-INF/lib/: 의존 라이브러리들 (톰캣 포함)
    • META-INF/: 매니페스트 파일
      • 매니페스트 파일은 특정 소프트웨어 또는 파일 그룹에 대한 메타데이터(설명 정보)를 포함하는 파일이다
    • org/springframework/boot/loader/: 스프링 부트 로더 클래스
  • 일반 JAR와 달리 내부에 다른 JAR 파일들을 포함할 수 있는 구주로, 스프링 부트의 커스텀 클래스 로더가 이를 읽어 실행한다
  • 간단한 실행: java -jar xxxx-application.jar 명령어나 main() 메서드만 실행하면 WAS가 함께 시작된다. 예를 들어, 애플리케이션 시작 시 내장된 톰캣 라이브러리가 8080 포트를 열고 웹 서버 기능을 수행하게 된다
    • 포트는 application.properties 혹은 application.yml 등의 설정 파일을 통해 변경이 가능하다

외장 서버와 내장 서버의 근본적인 차이

  • 외장 서버 (WAR): “서버를 설치하고 그 위에 내 코드를 배포”하는 방식이다. WAS가 주체가 되어 애플리케이션을 호스팅 한다
  • 내장 서버 (JAR): “내 코드 안에 서버를 라이브러리로 포함하여 함께 실행”하는 방식이다. 애플리케이션 자체가 주체가 되어 필요할 때 WAS를 구동한다
  • 버전 일관성: WAS의 버전이 애플리케이션과 함께 패키징되어 “개발 환경 = 운영 환경”을 보장해준다
  • 클라우드 네이티브: 컨테이너(Docker, Kubernetes) 환경에 최적화되어 MSA에 적합하다
  • 빠른 스케일링: 인스턴스 추가 시 단순히 JAR를 실행하기만 하면 되므로 수평 확장이 용이하다

결론

내장 서버 방식은 기존 외장 서버 방식의 모든 단점을 해결하며 개발 및 배포 과정을 혁신적으로 단순화하였다. 스프링 부트는 이러한 내장 톰캣(또는 다른 내장 WAS) 기능을 적극적으로 활용해, 개발자가 복잡한 서버 인프라 설정 없이 애플리케이션 개발에만 집중할 수 있는 환경을 제공한다. 다음으로는 이 내장 톰캣이 구체적으로 어떤 원리로 동작하는지 더 깊이 이해하는 것이 중요하다

PS – WAR 방식의 현재 활용

내장 서버 방식이 표준이 되었지만, 상황에 따라 여전히 전통적인 WAR 배포 방식이 사용된다

  • 레거시 인프라: 이미 구축된 WAS 인프라를 계속 활용해야 하는 경우
    • 설명: 많은 기업들이 수십 년간 구축하고 운영해온 기존 WAS 인프라를 가지고 있다. 이런 환경은 안정성이 검증되었고, 관련 운영 및 모니터링 시스템이 이미 잘 갖추어져 있다
    • 활용 이유: 새로운 시스템을 개발하더라도 기존 인프라에 통합해야 하거나, 비용 및 시간 문제로 인프라 전체를 최신 방식으로 전환하기 어려운 경우 WAR 파일 형태로 배포하여 기존 WAS를 그대로 활용한다. 이는 전환 비용을 최소화하고 기존 운영 프로세스와 충돌을 방지하는 효과적인 방법이다
  • 엔터프라이즈 환경: 엄격한 WAS 표준화가 요구되는 대기업 환경
    • 설명: 대규모 엔터프라이즈 환경에서는 WAS의 운영, 보안, 로깅, 모니터링 등에 대한 엄격한 표준과 정책이 요구되는 경우가 많다. 특정 벤더의 WAS(Oracle, WebLogic, IBM WebSphere)가 이러한 표준을 충족하도록 커스터마이징되어 있거나 라이선스 정책상 필수적인 경우가 있다
    • 활용 이유: 기업 내에서 표준화된 WAS 환경을 유지해야 할 때, 애플리케이션 개발 방식과 무관하게 WAR 파일을 생성하여 표준화된 WAS에 배포하는 것이 일반적이다. 이는 일관된 운영 환경을 제공하고 보안 및 규제 준수 측면에서 유리하다
  • 멀티 애플리케이션: 하나의 WAS에서 여러 애플리케이션을 호스팅해야 하는 경우
    • 설명: 때로는 리소스 효율성이나 관리의 편의를 위해 하나의 WAS 인스턴스에 여러 개의 웹 애플리케이션을 배포하여 동시에 서비스해야 하는 경우가 있다
    • 활용 이유: WAR 파일은 WAS 내에서 독립적인 컨텍스트 경로(Context Path)를 가지고 배포될 수 있으므로, 하나의 WAS가 여러 개의 독립적인 웹 애플리케이션을 효율적으로 호스팅할 수 있습니다. 예를 들어, http://example.com/app1과 http://example.com/app2 처럼 하나의 WAS에서 다른 URL로 접근 가능한 여러 서비스를 제공할 때 유용하다. 내장 서버 방식은 각 애플리케이션이 자체 WAS를 가지므로, 이 경우 여러 개의 WAS 인스턴스가 실행되어 리소스 관리가 복잡해질 수 있다

비교표

항목외장 서버 (WAR)내장 서버 (JAR)
WAS 설치별도 설치 필요불필요 (라이브러리로 포함)
배포 단위WAR 필요실행 가능한 JAR 파일
실행 방법WAS에 WAR 배포 후 서버 시작java -jar 명령어 하나로 실행
버전 관리WAS와 애플리케이션 별도 관리애플리케이션과 WAS 버전 일체화
개발 환경IDE-WAS 연동 설정 필요main() 메서드 실행만으로 즉시 테스트
배포 복잡도높음 (WAS 관리, WAR 배포)낮음 (JAR 복사 및 실행)
클라우드 적합성낮음 (무거운 이미지)높음 (경량 컨테이너화)
멀티 테넌시하나의 WAS에 여러 앱 배포 가능각 앱이 독립적인 프로세스

출처 – 김영한 님의 강의 중 스프링 부트 – 핵심 원리와 활용