[Deploy] 웹 애플리케이션 배포 방식 3가지 비교

웹 애플리케이션을 서버에 배포하는 방식은 여러 가지가 있다. Jenkins가 프로젝트를 관리하는 상황이라면 UI에서 모든 일이 가능하기 때문에 배포가 무척 쉽지만 상황에 따라 CI/CD 구축이 되어있지 않은 프로젝트도 많기 때문에 이 글에서는 실무에서 자주 사용되는 세 가지 배포 방식(수동 배포, Docker 배포, Jenkins CI/CD 배포)에 대해 알아보고 각각의 특징을 비교해보려고 한다.

1. 수동 배포

  • 가장 전통적인 방식으로, 개발자가 직접 명령어를 입력하여 애플리케이션을 서버에 배포하는 방식이다. MobaXterm(윈도우), iTerm2(MacOS) 등의 툴을 이용하면 편리한 배포가 가능하다. SSH 기능이 있는 VS Code나 intellij 등에서도 배포할 수 있다.

과정

# 1. WAR 파일 백업
cp ROOT.war ROOT.war.백업일자

# 2. Tomcat 서버 종료
cd /home/사용자의 경로.../sw/tomcat/bin
./shutdown.sh

# 종료 로그 확인
tail -f ../logs/catalina.out

# 3. 새 WAR 파일 배포
# FTP 클라이언트를 사용해 /home/사용자의 경로.../sw/tomcat/webapps/ 경로로 전송

# 4. Tomcat 서버 시작
./startup.sh

# 시작 로그 확인
tail -f ../logs/catalina.out

# 5. 프로세스 확인
ps -ef | grep tomcat

특징

  • 장점
    • 간단하고 직관적이라 복잡한 도구 없이 바로 시작 가능
    • 배포 과정을 직접 제어할 수 있음
  • 단점
    • 수동 작업으로 인한 인적 오류 발생 가능성 높음
    • 배포 시간이 길고 반복 작업이 많음
    • 배포 히스토리 관리가 어려움
    • 규모가 큰 프로젝트에서는 비효율적

주의사항

  • 배포 전 반드시 백업 확인 → 실패나 오류 상황을 대비해 미리 ROOT.WAR 파일의 복사본을 만들어놓는 게 좋다.
  • 서버 종료 전 현재 접속자 수 확인
  • WAR 파일 크기에 따라 압축 해제 시간 다름. 파일 크기를 잘 확인하자.
  • 문제 발생 시 백업한 WAR 파일로 롤백 준비

2. docker 배포

  • Docker는 애플리케이션과 그 환경을 컨테이너로 패키징하여 일관된 환경에서 실행할 수 있게 해주는 기술이다.
  • 수동배포와 달리 startup.shshutdown.sh 파일이 보이지 않는 이유는 이미 Docker 이미지 내부에 Tomcat이 설정되어 있기 때문이다. 그래서 docker restart 명령어로 컨테이너를 재시작하면 내부의 Tomcat도 함께 재시작됩니다.
  • Docker 컨테이너는 독립적이고 일관된 환경을 제공하므로 <작동하는 환경="" 그대로=""> 배포할 수 있다.
  • 애플리케이션 코드, 서버, 종속성, 설정 등이 모두 하나의 단위로 관리된다.

과정

# 도커로 배포(컨테이너 재시작) & 로그도 함께 확인하는 명령어
경로:~/docker/사용자의 경로/sw/tomcat/bin$ docker restart 컨테이너 이름 && docker logs --tail 10 -f gen-station
# 뒤의 && 부분을 제외하면 로그 확인 없이 배포된다.

# Docker 컨테이너의 상세 정보를 확인하는 명령어
docker inspect 컨테이너 이름

특징

  • 장점
    • 애플리케이션, 서버, 종속성, 설정 등을 모두 하나의 단위로 관리
    • 환경 간(개발, 테스트, 운영) 일관성 유지
    • 배포 과정과 롤백(이전 이미지로 컨테이너 교체)이 모두 단순화되고 빨라짐
    • 마이크로서비스 아키텍처(MSA)에 적합
  • 단점
    • Docker 학습 곡선이 있음 (기술 장벽)
    • 기존 시스템에 도입하려면 추가 작업 필요
    • 컨테이너 이미지 크기가 클 수 있음
    • 컨테이너 관리 및 오케스트레이션 추가 도구 필요

Docker inspect 명령어로 알 수 있는 정보

  • 컨테이너 기본 정보: ID, 생성 시간, 경로, 이름 등
  • 상태 정보: 실행 중인지 여부, 시작 시간, 종료 코드 등
  • 네트워크 설정: IP 주소, 포트 매핑, 네트워크 모드 등
  • 볼륨 마운트 정보: 컨테이너에 연결된 볼륨과 마운트 포인트
  • 환경 변수: 컨테이너 내부에 설정된 환경 변수
  • 실행 중인 명령어: 컨테이너가 시작될 때 실행되는 명령어
  • 리소스 제한: 메모리, CPU 제한 설정

3. Jenkins 배포 (CI/CD)

  • Jenkins는 지속적 통합/지속적 배포(CI/CD) 도구로 코드 변경부터 배포까지의 과정을 자동화한다.

과정

  • 개발자가 코드를 Git 저장소에 푸시
  • Jenkins가 변경 사항을 감지하고 자동으로 빌드 시작
  • 코드 테스트 및 정적 분석 실행
  • WAR/JAR 파일 또는 Docker 이미지 생성
  • 테스트 환경에 자동 배포 및 테스트
  • 승인 과정 후 운영 환경에 자동 배포
  • 배포 결과 알림 전송(로그 확인 가능)

특징

  • 장점
    • 배포 과정 완전 자동화
    • 휴먼 에러 감소
    • 일관된 빌드 및 배포 과정 보장
    • 도커, 쿠버네티스, AWS, SonarQube 등 다양한 플러그인으로 확장성 높음
    • 배포 히스토리 및 로그 관리 용이
    • 롤백 프로세스 자동화 가능
    • 품질 게이트를 통한 코드 품질 향상
  • 단점
    • 초기 설정이 복잡하고 시간 소요
    • 추가 서버 자원 필요
    • 파이프라인 유지 관리 필요
    • 복잡한 환경에서는 구성이 어려울 수 있음

Jenkins 파이프라인 예시

pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }

        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }

        stage('Deploy to Staging') {
            steps {
                // Docker 이미지 빌드 및 배포
                sh 'docker build -t myapp:latest .'
                sh 'docker stop myapp-staging || true'
                sh 'docker rm myapp-staging || true'
                sh 'docker run -d --name myapp-staging -p 8080:8080 myapp:latest'
            }
        }

        stage('Deploy to Production') {
            steps {
                // 승인 과정
                input 'Deploy to production?'

                // 운영 환경 배포
                sh 'docker stop myapp-production || true'
                sh 'docker rm myapp-production || true'
                sh 'docker run -d --name myapp-production -p 80:8080 myapp:latest'
            }
        }
    }

    post {
        success {
            echo 'Deployment successful!'
            // 성공 알림 전송
        }
        failure {
            echo 'Deployment failed!'
            // 실패 알림 전송
        }
    }
}

세 가지 배포 방식 비교

특성 수동 배포 Docker 배포 Jenkins CI/CD
속도 느림 빠름 매우 빠름
일관성 낮음 높음 매우 높음
자동화 수준 없음 부분적 완전함
설정 복잡성 낮음 중간 높음
롤백 용이성 어려움 쉬움 매우 쉬움
학습 곡선 낮음 중간 높음
확장성 낮음 높음 매우 높음
적합한 환경 소규모 프로젝트 중간 규모 프로젝트 대규모 프로젝트

결론

각 배포 방식은 프로젝트의 규모, 팀의 역량, 자동화 수준 등에 따라 선택할 수 있다:

  • 수동 배포: 작은 프로젝트나 개발 초기 단계에서 간단하게 사용 가능
  • Docker 배포: 환경 일관성이 중요하거나 마이크로서비스 아키텍처를 사용하는 경우 적합
  • Jenkins CI/CD: 팀 규모가 크고, 자주 배포하며, 품질 관리가 중요한 프로젝트에 적합