[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.sh나shutdown.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: 팀 규모가 크고, 자주 배포하며, 품질 관리가 중요한 프로젝트에 적합