CI/CD로 자동화된 배포 구축하기 - Docker, GitHub Actions 실전
“이제 코드를 Push 하면, 자동으로 서비스가 배포됩니다.”
이제는 배포도 코드처럼 다뤄야 하는 시대. 우리는 이번 편에서 CI/CD 파이프라인을 직접 구성하며, 진짜 개발자다운 자동화 흐름을 만들어 봅니다.
🛠️ 본격 실습 전, 준비할 것들
자동화 배포를 시작하기 전에 다음 준비 작업이 필요합니다:
- EC2 인스턴스 생성 및 접속 준비
- Ubuntu 또는 Amazon Linux 2 인스턴스 실행
- SSH 접속 가능 여부 확인 (chmod 400 키. pem, ssh -i 키. pem ec2-user@IP)
- 보안 그룹 설정: 포트 22 (SSH), 80/443 (HTTP), 3000 (Node.js 앱)
- GitHub Repository 준비
- main 브랜치 설정 및 기본 프로젝트 업로드
- .gitignore, README.md, Dockerfile 포함 확인
- GitHub Secrets 설정
- EC2_HOST: EC2 퍼블릭 IP
- EC2_KEY:. pem 키 내용 전체 복붙 (비밀값)
- EC2_USER: 일반적으로 ec2-user 또는 ubuntu
- Docker 설치 (EC2 내부)
- 이후 exit 후 다시 접속하여 docker 명령어 사용 가능 확인
- sudo apt update sudo apt install docker.io -y sudo systemctl start docker sudo systemctl enable docker sudo usermod -aG docker $USER
- Node.js 및 프로젝트 디렉터리 구성
- 프로젝트 폴더 /home/ec2-user/app에 clone 및 실행 권장
이 모든 준비가 끝났다면, 이제 자동화 배포의 여정을 본격 시작할 수 있습니다.
🧭 왜 자동화 배포가 필요할까?
지난 편에서는 AWS EC2에 수동으로 접속해 서버를 설정하고 배포를 진행했습니다. 하지만, 이런 방식은 다음과 같은 단점이 있습니다:
- 수정사항이 생길 때마다 SSH 접속 → pull → restart 반복
- 사람마다 설정이 달라 재현성 부족
- 실수로 서버 설정 망가질 수 있음
그래서 등장한 것이 CI/CD입니다.
- CI(지속적 통합): 코드를 자주 병합하고 자동 테스트/빌드를 수행
- CD(지속적 배포): 코드를 병합하면 자동으로 배포까지 이어짐
이제 우리는 GitHub에 Push만 해도 배포가 완료되는 자동화 흐름을 만들어봅니다.
🐳 Docker란? 왜 써야 할까?
Docker는 앱과 그 실행 환경을 하나의 컨테이너로 묶어주는 도구입니다.
- 가상머신: OS까지 통째로 복제 → 무거움
- 도커 컨테이너: 앱과 라이브러리만 격리 → 가벼움
장점:
- 어디서든 동일한 실행 환경 보장
- 배포가 일관되고 빠름
- 서버 설정 문제 발생률 감소
⚙️ Dockerize 실습: 내 Node.js 앱을 컨테이너에 담기
1. Dockerfile 작성
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
2. 도커 빌드 & 실행
docker build -t my-node-app .
docker run -d -p 3000:3000 my-node-app
이제 브라우저에서 http://localhost:3000에 접속해 앱을 확인해 보세요.
⚡ GitHub Actions로 자동화 시작하기
.github/workflows/deploy.yml 생성:
name: Deploy to EC2
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: SSH into EC2 & deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_KEY }}
script: |
cd /home/ec2-user/app
git pull origin main
docker build -t my-node-app .
docker stop app || true && docker rm app || true
docker run -d --name app -p 3000:3000 my-node-app
주의:
- EC2_HOST, EC2_KEY 등은 GitHub Secrets에 등록해야 보안 유지
- SSH 연결을 위해 EC2에 .pem 기반 SSH 접근 설정 필요
🧪 실전 트러블슈팅
문제 원인 해결 방법
SSH 연결 실패 | 키 문제 or IP 허용 안 됨 | EC2 보안 그룹 22포트 확인 |
Docker pull 오류 | Dockerfile 위치 이상 | .dockerignore 체크 및 경로 확인 |
Workflow 작동 안 함 | YAML 문법 오류 | GitHub Actions 로그 확인 |
📌 실습 정리 & 배포 체크리스트
- Node.js 앱에 Dockerfile 추가
- GitHub Actions 설정 완료
- Push 시 자동 배포 확인
- EC2 로그 확인 (docker logs)
- 실패 시 롤백 계획 세움
🧭 회고: 자동화, 진짜 개발자처럼
우리는 지금, 코드를 Push 하고 자동으로 서비스가 갱신되는 구조를 만들었습니다.
단순히 편리함을 넘어서, 이건 팀 개발과 실무의 기반이 되는 핵심 역량입니다.
자동화는 단순한 기술이 아니라 협업, 효율, 안정성을 위한 인프라입니다.
🔮 다음 예고: 도커 컴포즈와 멀티서비스
이제는 하나의 앱이 아니라, DB + API + 프론트 + Nginx를 함께 다루는 멀티 서비스 환경으로 나아갑니다.
이를 위해 우리는 Docker Compose를 배우게 됩니다.
⚙️ 배포는 끝이 아닌, 시작입니다.
다음은 복잡한 서비스를 통합적으로 다루는 도전이 기다립니다.