공공부하자개발 · 영어 학습 노트
협업·배포
CI/CD빌드·테스트·배포 자동화0/7 완료
  • 01CI/CD 개념과 파이프라인
  • 02GitHub Actions 기초
  • 03자동 테스트와 품질 게이트
  • 04빌드 산출물과 버전
  • 05배포 자동화
  • 06릴리스 자동화
  • 07파이프라인 운영과 문제 해결
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › CI/CD › 05 / 7

배포 자동화

섹션 7진행 0 / 7
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

2. 핵심 원리

2.1 배포 방식의 발전 단계

배포는 보통 세 단계로 발전합니다.

단계 특징 위험
수동 배포 담당자가 직접 접속해 파일 복사 사람 실수·재현 어려움
스크립트 배포 배포 절차를 스크립트 1개로 고정 서버 차이 반영 필요
파이프라인 배포 CI/CD 가 빌드부터 배포까지 자동 실행 승인 단계 설계 필요

2.2 환경 분리: dev·stage·prod

같은 코드를 여러 환경에 배포하되 설정만 다르게 적용합니다.

환경 목적 특징
dev 개발자 테스트 자주 배포, 데이터 휘발
stage 운영 전 최종 검증 prod 와 같은 구성
prod 실제 사용자 서비스 배포 신중, 승인 필요

2.3 설정 분리: application-.properties 와 환경변수

환경별 값은 코드가 아니라 파일로 분리합니다.

properties
# application-dev.properties
app.port=8080
db.url=jdbc:h2:mem:devdb
log.level=DEBUG

배포 시 APP_ENV=prod 같은 환경변수로 어떤 파일을 쓸지 고르고, 필요하면 환경변수가 파일 값을 덮어씁니다. 비밀번호 같은 민감한 값은 파일이 아니라 환경변수나 시크릿 저장소에 둡니다.

2.4 릴리스 폴더 구조: releases/N + current

배포마다 새 폴더를 만들고, 활성 릴리스만 current 가 가리킵니다.

text
/opt/app/
├── releases/
│   ├── 1/
│   ├── 2/
│   └── 3/
└── current            (활성 릴리스 번호를 적은 파일 또는 심볼릭 링크)

Git Bash 에서는 심볼릭 링크 권한 문제가 있어 이 레슨의 스크립트는 current 를 릴리스 번호를 적은 텍스트 파일로 대신합니다. 리눅스 서버에서는 ln -sfn releases/3 current 로 실제 심볼릭 링크를 씁니다.

2.5 배포 스크립트 4단계

배포 스크립트는 언제나 같은 순서를 따릅니다.

순서 단계 내용
1 복사 새 릴리스 폴더에 산출물·설정 복사
2 전환 current 가 가리키는 대상을 새 릴리스로 변경
3 재시작 서비스 재시작으로 새 코드 적용
4 헬스체크 재시작 후 정상 응답인지 확인

2.6 헬스체크 설계

헬스체크는 서버를 띄운 채 오래 기다리지 않고, 짧게 실행해 종료 코드로 판단합니다.

bash
java -jar app.jar --health status.flag
echo "종료 코드: $?"   # 0=정상, 1=비정상

실제 서비스에서는 /health 같은 HTTP 엔드포인트를 두지만, 이 레슨은 --health 인자로 즉시 종료하는 방식으로 같은 판단 구조를 재현합니다.

2.7 실패 시 롤백

헬스체크가 실패하면 두 가지 상황이 있습니다.

  • 전환 전 실패: current 를 아예 바꾸지 않아 롤백이 필요 없습니다.
  • 전환 후 문제 발견: current 를 이전 릴리스 번호로 다시 쓰고 재시작합니다.

두 경우 모두 releases 폴더 자체는 지우지 않아 원인 분석에 남겨 둡니다.

2.8 릴리스 보관과 정리

releases 폴더가 계속 쌓이면 디스크가 찹니다. 보통 최근 5~10개만 남기고 오래된 폴더를 지우되, 지우기 전에는 그 릴리스가 current 가 아닌지 확인해야 합니다. 실수로 활성 릴리스를 지우면 다음 재시작이 실패합니다.

2.9 scp·ssh 원격 배포 명령

원격 서버가 있다면 산출물을 scp 로 올리고 ssh 로 배포 명령을 실행합니다.

bash
scp dist/app.jar deploy@prod-1:/opt/app/releases/12/app.jar
ssh deploy@prod-1 "echo 12 > /opt/app/current && \
  sudo systemctl restart app.service"

이 레슨은 인터넷·원격 서버 접근이 없는 환경이라 이 명령은 텍스트로만 보여주고, 실제 헬스체크와 전환은 로컬 스크립트로 재현합니다.

2.10 systemd 로 서비스 재시작

리눅스 서버는 보통 systemd 서비스로 앱을 관리합니다.

ini
[Service]
Type=simple
ExecStart=/usr/bin/java -jar /opt/app/current/app.jar
Restart=on-failure

sudo systemctl restart app.service 로 재시작하고, Restart=on-failure 를 두면 비정상 종료 시 자동으로 다시 뜹니다. 이 레슨은 문법만 확인하고 실행하지 않습니다.

2.11 GitHub Actions environments 와 승인 단계

GitHub Actions 는 environment 키로 배포 대상을 지정하고, 그 environment 에 필수 리뷰어를 걸어 두면 승인 전까지 잡이 멈춥니다.

yaml
jobs:
  deploy-prod:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.example.com
    steps:
      - run: echo "prod 배포 실행"

prod environment 에만 승인을 걸고 dev·stage 는 자동 배포하는 구성이 흔하며, 인터넷 접근이 없는 이 레슨에서는 워크플로 화면 대신 텍스트로만 구조를 보여줍니다.

2.12 컨테이너 배포와 다음 단계

여기서 다룬 릴리스 폴더 방식은 jar 를 직접 서버에 올리는 전통적인 배포입니다. 컨테이너 이미지로 배포하는 방식은 리눅스 운영 13(Docker) 레슨을 참고하세요. 두 방식 모두 환경 분리, 헬스체크, 롤백이라는 원리는 같고 산출물이 jar 냐 이미지냐만 다릅니다.

핵심 원리
  • 2.1 배포 방식의 발전 단계
  • 2.2 환경 분리: dev·stage·prod
  • 2.3 설정 분리: application-<env>.properties 와 환경변수
  • 2.4 릴리스 폴더 구조: releases/N + current
  • 2.5 배포 스크립트 4단계
  • 2.6 헬스체크 설계
  • 2.7 실패 시 롤백
  • 2.8 릴리스 보관과 정리
  • 2.9 scp·ssh 원격 배포 명령
  • 2.10 systemd 로 서비스 재시작
  • 2.11 GitHub Actions environments 와 승인 단계
  • 2.12 컨테이너 배포와 다음 단계
이전 섹션1 왜 배우는가2 / 7다음 섹션3 코드 예제