TIL - 20260607

juni·2026년 6월 6일

TIL

목록 보기
372/471

0607 풀스택 실무 기초 (10/N): 배포와 CI/CD 기본 흐름


✅ 1. 배포란 무엇인가?

  • 배포(Deployment)란 개발한 소스코드를 실제 사용자가 접근할 수 있는 서버 또는 서비스 환경에 반영하는 작업입니다.
  • 로컬 PC에서 잘 동작하는 코드를 운영 서버에 올리고, 빌드하고, 실행하고, 도메인과 연결해서 사용자가 이용할 수 있게 만드는 과정입니다.
  • 풀스택 개발자는 단순히 코드를 작성하는 것에서 끝나지 않고, 코드가 실제 서비스 환경에서 안정적으로 동작하도록 배포하는 흐름을 이해해야 합니다.

➕ 1-1. 배포가 중요한 이유

  • 개발 결과물이 실제 사용자에게 전달되는 단계

    • 아무리 기능을 잘 만들어도 배포가 안 되면 사용자는 이용할 수 없습니다.
  • 장애와 직접 연결

    • 배포 과정에서 빌드 실패, 환경변수 누락, DB 마이그레이션 오류, 서버 재시작 실패가 발생할 수 있습니다.
  • 운영 안정성에 영향

    • 배포 절차가 정리되어 있지 않으면 매번 수동 작업 실수가 발생할 수 있습니다.
  • 개발자의 실무 역량 증명

    • 프론트엔드, 백엔드, DB, 서버, 도메인, SSL, 로그까지 연결해서 운영할 수 있으면 실무 가치가 크게 올라갑니다.

✅ 2. 로컬 환경과 운영 환경의 차이

  • 로컬에서 정상 동작한다고 해서 운영에서도 무조건 정상 동작하는 것은 아닙니다.
  • 운영 환경은 도메인, HTTPS, 서버 리소스, 환경변수, DB, 외부 API 설정이 다를 수 있습니다.

➕ 2-1. 로컬 환경

프론트엔드: http://localhost:5173
백엔드: http://localhost:3000
DB: localhost:5432
  • 개발자가 직접 실행합니다.
  • 오류가 나면 바로 콘솔을 볼 수 있습니다.
  • 테스트 데이터를 사용합니다.
  • 보안 설정이 느슨할 수 있습니다.

➕ 2-2. 운영 환경

프론트엔드: https://www.example.com
백엔드: https://api.example.com
DB: RDS 또는 운영 DB
  • 실제 사용자가 접속합니다.
  • 장애가 매출과 신뢰도에 영향을 줍니다.
  • 운영 DB에는 실제 데이터가 들어 있습니다.
  • HTTPS, CORS, 보안 그룹, 방화벽, SSL 인증서 설정이 필요합니다.

✅ 3. 배포의 기본 구성 요소

➕ 3-1. 프론트엔드 배포

  • React/Vite 프로젝트는 보통 빌드 후 정적 파일로 배포됩니다.
npm run build
  • 빌드 결과물은 보통 dist 또는 build 폴더에 생성됩니다.
dist/
  index.html
  assets/
    main.a1b2c3.js
    style.x9y8z7.css
  • 이 정적 파일을 Nginx, S3, CloudFront, Vercel, Netlify 같은 환경에서 제공합니다.

➕ 3-2. 백엔드 배포

  • NestJS 백엔드는 TypeScript 코드를 JavaScript로 빌드한 뒤 서버에서 실행합니다.
npm run build
npm run start:prod
  • 운영 서버에서는 보통 PM2, Docker, systemd 등을 사용해 백엔드 프로세스를 관리합니다.
pm2 start dist/main.js --name api

➕ 3-3. 데이터베이스 배포

  • DB는 단순히 서버를 켜는 것만으로 끝나지 않습니다.
  • 테이블 구조 변경이 필요한 경우 마이그레이션을 적용해야 합니다.
npx prisma migrate deploy
  • 운영 DB 마이그레이션은 매우 조심해야 합니다.
  • 배포 전 백업 여부와 변경 내용을 반드시 확인해야 합니다.

➕ 3-4. 환경변수 반영

  • 운영 환경에서는 .env.production 또는 서버 환경변수에 실제 운영 설정이 들어가야 합니다.
NODE_ENV=production
DATABASE_URL=postgresql://USER:PASSWORD@DB_HOST:5432/DB_NAME
JWT_SECRET=production-secret
CORS_ORIGIN=https://www.example.com
  • 환경변수가 하나라도 빠지면 서버가 실행되지 않거나 특정 기능이 실패할 수 있습니다.

✅ 4. 수동 배포 흐름

  • 가장 기본적인 배포 방식은 서버에 직접 접속해서 명령어를 실행하는 수동 배포입니다.
  • 작은 프로젝트나 초기 서비스에서는 수동 배포로 시작할 수 있습니다.

➕ 4-1. 백엔드 수동 배포 예시

# 1. 서버 접속
ssh ubuntu@server-ip

# 2. 프로젝트 폴더 이동
cd /home/ubuntu/app

# 3. 최신 코드 가져오기
git pull origin main

# 4. 의존성 설치
npm install

# 5. 빌드
npm run build

# 6. Prisma 마이그레이션
npx prisma migrate deploy

# 7. 서버 재시작
pm2 reload api

# 8. 상태 확인
pm2 status
pm2 logs api

➕ 4-2. 프론트엔드 수동 배포 예시

# 1. 로컬 또는 서버에서 빌드
npm run build

# 2. 빌드 결과물 업로드
scp -r dist/* ubuntu@server-ip:/var/www/frontend

# 3. Nginx 설정 확인
sudo nginx -t

# 4. Nginx 재시작
sudo systemctl reload nginx
  • 수동 배포는 이해하기 쉽지만, 사람이 직접 하다 보니 실수 가능성이 높습니다.
  • 그래서 반복되는 배포는 자동화하는 것이 좋습니다.

✅ 5. CI/CD란 무엇인가?

  • CI/CD는 코드 변경부터 테스트, 빌드, 배포까지의 과정을 자동화하는 방식입니다.

➕ 5-1. CI

  • CI(Continuous Integration)는 지속적 통합을 의미합니다.
  • 개발자가 코드를 push하거나 Pull Request를 만들 때 자동으로 테스트, 린트, 빌드를 실행하는 과정입니다.
코드 push
  ↓
자동 테스트
  ↓
자동 빌드
  ↓
문제 있으면 병합 차단
  • CI를 적용하면 main 브랜치에 깨진 코드가 들어가는 것을 줄일 수 있습니다.

➕ 5-2. CD

  • CD(Continuous Delivery / Continuous Deployment)는 지속적 배포를 의미합니다.
  • CI를 통과한 코드를 자동으로 서버에 배포하거나, 승인 후 배포할 수 있게 만드는 과정입니다.
main 브랜치 병합
  ↓
자동 빌드
  ↓
서버 배포
  ↓
서비스 재시작
  ↓
헬스체크
  • 실무에서는 main 브랜치에 push되면 자동으로 운영 서버에 배포되도록 구성하는 경우가 많습니다.
  • 다만 운영 배포는 위험하므로 승인 단계나 staging 배포를 먼저 두기도 합니다.

✅ 6. GitHub Actions 기본 구조

  • GitHub Actions는 GitHub에서 제공하는 CI/CD 자동화 도구입니다.
  • .github/workflows 폴더 안에 YAML 파일을 만들어 자동화 작업을 정의합니다.

➕ 6-1. 기본 파일 위치

.github/
  workflows/
    deploy.yml

➕ 6-2. GitHub Actions 기본 예시

name: CI

on:
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build
  • 위 설정은 main 브랜치로 PR이 생성되었을 때 자동으로 의존성 설치와 빌드를 실행합니다.

✅ 7. GitHub Actions로 서버 배포하기

  • GitHub Actions에서 SSH로 운영 서버에 접속해 배포 명령어를 실행할 수 있습니다.

➕ 7-1. 배포 흐름 예시

1. main 브랜치에 push
2. GitHub Actions 실행
3. 서버에 SSH 접속
4. git pull
5. npm install
6. npm run build
7. prisma migrate deploy
8. pm2 reload
9. health check

➕ 7-2. 간단한 deploy.yml 예시

name: Deploy Backend

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Deploy to server
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /home/ubuntu/app
            git pull origin main
            npm install
            npm run build
            npx prisma migrate deploy
            pm2 reload api
  • 실제 운영에서는 이보다 더 세밀한 실패 처리, 로그 확인, 헬스체크, 롤백 전략이 필요합니다.
  • SSH 정보와 비밀키는 반드시 GitHub Secrets에 저장해야 합니다.

✅ 8. PM2를 이용한 Node.js 운영

  • PM2는 Node.js 애플리케이션을 운영 환경에서 안정적으로 실행하기 위한 프로세스 매니저입니다.
  • 서버가 꺼지거나 앱이 죽었을 때 재시작하고, 로그를 확인하고, 여러 프로세스를 관리할 수 있습니다.

➕ 8-1. PM2 기본 명령어

# 앱 실행
pm2 start dist/main.js --name api

# 앱 목록 확인
pm2 list

# 로그 확인
pm2 logs api

# 재시작
pm2 restart api

# 무중단 reload
pm2 reload api

# 앱 중지
pm2 stop api

# 앱 삭제
pm2 delete api

➕ 8-2. 서버 재부팅 후 자동 실행

pm2 startup
pm2 save
  • 서버가 재부팅되어도 PM2가 기존 프로세스를 자동으로 다시 실행하도록 설정할 수 있습니다.

✅ 9. Nginx와 Reverse Proxy

  • 운영 서버에서는 보통 Nginx를 앞단에 두고, 백엔드 서버로 요청을 전달합니다.
  • 이 구조를 Reverse Proxy라고 합니다.

➕ 9-1. Reverse Proxy 구조

사용자
  ↓
https://api.example.com
  ↓
Nginx
  ↓
localhost:3000 NestJS
  • 사용자는 https://api.example.com으로 요청하지만, 실제 NestJS 서버는 내부에서 localhost:3000으로 실행될 수 있습니다.

➕ 9-2. Nginx 설정 예시

server {
  listen 80;
  server_name api.example.com;

  location / {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}
  • 운영에서는 여기에 HTTPS, SSL 인증서, gzip, 보안 헤더, 로그 설정 등을 추가합니다.

✅ 10. 프론트엔드 정적 파일 배포

  • React/Vite 프로젝트는 빌드 후 정적 파일을 Nginx로 제공할 수 있습니다.

➕ 10-1. Nginx 정적 파일 설정 예시

server {
  listen 80;
  server_name www.example.com;

  root /var/www/frontend;
  index index.html;

  location / {
    try_files $uri /index.html;
  }
}
  • try_files $uri /index.html;은 React Router를 사용하는 SPA에서 중요합니다.
  • /products/1 같은 경로로 직접 접속해도 index.html을 반환해서 React 라우터가 처리할 수 있게 합니다.

✅ 11. SSL과 HTTPS

  • 운영 서비스에서는 HTTPS 적용이 필수입니다.
  • HTTPS는 사용자의 브라우저와 서버 사이 통신을 암호화합니다.

➕ 11-1. HTTPS가 필요한 이유

  • 로그인 정보 보호
  • 개인정보 보호
  • 중간자 공격 방지
  • 브라우저 보안 경고 방지
  • SEO와 사용자 신뢰도 향상
  • 쿠키의 Secure 옵션 사용 가능

➕ 11-2. Let's Encrypt와 Certbot

  • Let's Encrypt는 무료 SSL 인증서를 제공하는 서비스입니다.
  • Certbot을 사용하면 Nginx에 SSL 인증서를 쉽게 적용할 수 있습니다.
sudo certbot --nginx -d www.example.com -d api.example.com

➕ 11-3. 인증서 갱신 확인

sudo certbot renew --dry-run
  • SSL 인증서 갱신이 실패하면 사이트에 보안 경고가 뜰 수 있습니다.
  • 운영자는 인증서 자동 갱신 상태를 정기적으로 확인해야 합니다.

✅ 12. 배포 전 체크리스트

➕ 12-1. 코드 체크

  1. main 브랜치가 최신 상태인가?
  2. PR 리뷰 또는 자체 검토를 완료했는가?
  3. 불필요한 console.log가 남아 있지 않은가?
  4. .env나 민감정보가 커밋되지 않았는가?
  5. 로컬에서 빌드가 성공하는가?

➕ 12-2. 백엔드 체크

  1. 운영 환경변수가 모두 설정되어 있는가?
  2. DB 마이그레이션이 필요한가?
  3. 마이그레이션 전 백업이 필요한가?
  4. 인증/권한 기능이 정상 동작하는가?
  5. 외부 API Key가 운영용인가?
  6. CORS Origin이 운영 도메인으로 설정되어 있는가?

➕ 12-3. 프론트엔드 체크

  1. API Base URL이 운영 주소인가?
  2. 빌드 결과물이 정상 생성되는가?
  3. 이미지와 정적 파일 경로가 깨지지 않는가?
  4. 라우팅 직접 접속이 정상 동작하는가?
  5. 모바일 화면이 깨지지 않는가?
  6. GA, 광고 추적, 채널톡 등 운영 태그가 정상인가?

✅ 13. 배포 후 체크리스트

➕ 13-1. 기본 접속 확인

  1. 메인 페이지 접속 확인
  2. 주요 상품/이벤트 페이지 접속 확인
  3. 관리자 페이지 접속 확인
  4. API health check 확인
  5. HTTPS 인증서 정상 확인
https://www.example.com
https://api.example.com/health

➕ 13-2. 기능 확인

  1. 로그인 정상 동작
  2. 상담 신청 정상 저장
  3. 관리자 목록 조회 정상 동작
  4. 파일 업로드 정상 동작
  5. 외부 API 연동 정상 동작
  6. 문자/알림 발송 정상 동작
  7. 결제나 주문 기능이 있다면 테스트 결제 확인

➕ 13-3. 로그 확인

pm2 logs api
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
  • 배포 후에는 사용자가 문제를 말하기 전, 개발자가 먼저 로그를 확인해야 합니다.
  • 500 오류, DB 연결 오류, 외부 API 실패, CORS 오류가 없는지 확인합니다.

✅ 14. 롤백이란 무엇인가?

  • 롤백(Rollback)은 배포 후 문제가 발생했을 때 이전 정상 버전으로 되돌리는 작업입니다.
  • 배포는 항상 성공한다고 가정하면 안 됩니다.
  • 운영에서는 “문제가 생기면 어떻게 되돌릴 것인가?”까지 준비해야 합니다.

➕ 14-1. 롤백이 필요한 상황

  • 로그인 불가
  • 상담 신청 실패
  • 관리자 페이지 오류
  • 결제/주문 오류
  • API 500 오류 급증
  • 배포 후 화면 깨짐
  • DB 마이그레이션 오류

➕ 14-2. 간단한 코드 롤백 예시

# 이전 커밋 확인
git log --oneline

# 특정 커밋으로 되돌리기
git checkout <commit-hash>

# 빌드 및 재시작
npm install
npm run build
pm2 reload api
  • 운영에서는 직접 checkout하기보다 release 디렉토리 관리, Docker 이미지 태그, GitHub Actions 재배포 등 더 안전한 방식을 사용할 수 있습니다.
  • DB 마이그레이션이 포함된 배포는 롤백이 더 복잡하므로 특히 조심해야 합니다.

✅ 15. Blue-Green 배포와 무중단 배포 개념

  • 사용자가 있는 서비스에서는 배포 중에도 서비스가 끊기지 않도록 하는 것이 중요합니다.

➕ 15-1. Blue-Green 배포

  • 기존 운영 환경을 Blue, 새 배포 환경을 Green으로 두고, 새 환경 검증 후 트래픽을 전환하는 방식입니다.
Blue: 현재 운영 중
Green: 새 버전 배포 및 검증
  ↓
문제 없으면 트래픽을 Green으로 전환
  • 문제가 생기면 다시 Blue로 트래픽을 돌릴 수 있습니다.

➕ 15-2. 무중단 배포

  • 서비스 중단 없이 새 버전을 반영하는 배포 방식입니다.
  • PM2의 reload, Docker rolling update, 로드밸런서 기반 배포 등이 사용될 수 있습니다.
pm2 reload api
  • 단순한 restart는 짧은 순간 서비스가 끊길 수 있지만, reload는 무중단에 가깝게 프로세스를 교체할 수 있습니다.

✅ 16. 배포 자동화 시 주의할 점

➕ 16-1. 자동 배포가 무조건 좋은 것은 아님

  • 자동 배포는 편리하지만, 잘못된 코드가 자동으로 운영에 반영될 위험도 있습니다.
  • 그래서 최소한 다음 조건은 필요합니다.
  1. 빌드 성공 확인
  2. 테스트 통과 확인
  3. 환경변수 검증
  4. 마이그레이션 확인
  5. 배포 후 헬스체크
  6. 실패 시 알림
  7. 롤백 방법 준비

➕ 16-2. 배포 스크립트에서 위험한 명령어 주의

rm -rf
git reset --hard
prisma migrate reset
docker system prune -a
  • 위 명령어들은 운영 서버에서 잘못 사용하면 치명적인 사고가 날 수 있습니다.
  • 특히 prisma migrate reset은 DB 데이터를 삭제할 수 있으므로 운영에서 사용하면 안 됩니다.

✅ 17. 실무 배포 체크리스트

➕ 17-1. 1인 개발자 최소 배포 루틴

1. 작업 브랜치에서 기능 개발
2. main 최신화
3. 로컬 빌드 확인
4. Git push
5. 서버 배포
6. PM2 상태 확인
7. Nginx 오류 로그 확인
8. 주요 페이지 접속 확인
9. 핵심 기능 테스트
10. 배포 기록 작성

➕ 17-2. 배포 기록 예시

## 배포 기록

### 배포 일시
- 2026-06-07 18:30

### 배포 내용
- 상담 신청 중복 방지 로직 추가
- 관리자 상담 목록 필터 개선
- 배너 이미지 업로드 오류 수정

### 영향 범위
- 상담 신청 페이지
- 관리자 상담 관리
- 배너 관리

### 확인 내용
- 메인 페이지 접속 정상
- 상담 신청 저장 정상
- 관리자 목록 조회 정상
- PM2 로그 이상 없음

### 특이사항
- DB 마이그레이션 없음
  • 배포 기록은 나중에 장애 추적과 경력 정리에 큰 도움이 됩니다.

✅ 18. AI를 활용해 배포 문제를 해결할 때 질문법

  • 배포 문제는 “어디까지 성공했고 어디서 실패했는지”가 중요합니다.
  • AI에게 질문할 때는 환경, 배포 방식, 에러 로그, 최근 변경사항을 함께 알려줘야 합니다.

➕ 18-1. 좋은 질문 예시

NestJS + Prisma + PM2 + Nginx 환경에서 배포 후 502 Bad Gateway가 발생해.

환경:
- 서버: AWS EC2 Ubuntu
- 백엔드: NestJS
- 프로세스 관리: PM2
- 웹서버: Nginx reverse proxy
- DB: PostgreSQL
- 배포 방식: git pull 후 npm run build, pm2 reload api

현재 상태:
- Nginx는 실행 중
- pm2 list에서 api가 errored 상태
- pm2 logs에 DATABASE_URL 관련 에러가 있음
- 로컬에서는 정상 동작

확인해야 할 순서와 가능한 원인을 설명해줘.
운영 서버에서 실행할 명령어도 같이 알려줘.

➕ 18-2. AI 답변 검증 기준

  1. 무작정 서버 재부팅부터 시키지 않는가?
  2. PM2 상태와 로그 확인을 먼저 안내하는가?
  3. Nginx 로그와 애플리케이션 로그를 구분하는가?
  4. 환경변수 누락 가능성을 확인하는가?
  5. DB 연결 상태를 점검하는가?
  6. 최근 배포 변경사항을 확인하게 하는가?
  7. 위험한 명령어를 운영 서버에 바로 쓰라고 하지 않는가?

📌 요약

  • 배포는 개발한 코드를 실제 사용자가 접근할 수 있는 운영 환경에 반영하는 작업입니다.
  • 프론트엔드는 빌드된 정적 파일을 배포하고, 백엔드는 빌드 후 PM2, Docker, systemd 등으로 실행합니다.
  • 운영 배포에서는 환경변수, DB 마이그레이션, Nginx, SSL, CORS, 로그 확인이 함께 필요합니다.
  • CI/CD는 코드 변경부터 테스트, 빌드, 배포까지의 과정을 자동화하는 방식입니다.
  • GitHub Actions를 사용하면 PR 시 빌드 확인, main push 시 서버 배포 같은 자동화를 구성할 수 있습니다.
  • PM2는 Node.js 서버를 운영 환경에서 안정적으로 실행하고 관리하는 데 유용합니다.
  • Nginx는 정적 파일 제공과 Reverse Proxy 역할을 하며, React SPA에서는 try_files $uri /index.html; 설정이 중요합니다.
  • 배포 후에는 반드시 메인 페이지, API health check, 핵심 기능, PM2 로그, Nginx 로그를 확인해야 합니다.
  • 배포는 항상 실패 가능성을 전제로 해야 하며, 롤백 방법과 배포 기록을 준비하는 습관이 중요합니다.

0개의 댓글