Guider/Backend/BackendDevGuide0007
Backend#07

BackendDevGuide0007

배포와 DevOps 완전 정복

 
🚀
BackendDevGuide Series · Episode 7

BackendDevGuide0007

배포와 DevOps 완전 정복 A-Z

🍕 피자 배달처럼 코드를 세상에 배달하는 모든 기술

⏱ 예상 학습: 3~4주🐳 Docker 완전정복☁️ AWS 실전 배포🔄 CI/CD 자동화
🐳
Docker
컨테이너 완전정복
⚙️
CI/CD
GitHub Actions
☁️
AWS
클라우드 인프라
📊
모니터링
Prometheus/Grafana

📋 전체 학습 목차 (14개 섹션)

01DevOps란? 배포의 A-Z 전체 그림
02Linux 서버 완전 정복
03Docker 완전 정복 (기초~고급)
04Docker Compose 멀티 컨테이너
05Nginx 리버스프록시 + HTTPS
06PM2 프로세스 관리 + 무중단
07GitHub Actions CI/CD 완전정복
08AWS EC2 + RDS + S3 실전
09환경변수 & 시크릿 관리
10모니터링 & 로깅 완전정복
11블루그린 & 카나리 배포 전략
12Kubernetes 입문
13장애 대응 & 포스트모템
면접 Q&A + 체크리스트 + 로드맵

🚀 Section 01. DevOps란? 배포의 A-Z 전체 그림

개발자가 만든 코드가 어떻게 전 세계 사용자에게 도달하는가

🍕 피자 배달로 이해하는 배포

피자 가게를 운영한다고 상상해보세요. 개발자 = 요리사, 코드 = 레시피, 서버 = 주방, 사용자 = 손님. 레시피가 아무리 완벽해도 손님에게 배달되지 않으면 의미가 없습니다!

배포 개념 피자 가게 비유 실제 기술
코드 작성 새 레시피 개발 git commit, push
빌드 재료 손질 + 반죽 npm run build
테스트 맛 검수 npm run test
컨테이너화 피자박스 포장 docker build
배포 배달 완료 docker compose up
모니터링 고객 만족도 확인 Prometheus + Grafana

🔄 DevOps = Dev + Ops 문화 혁명

😤 DevOps 이전 (전통적 방식)
❌ 개발팀 / 운영팀 완전 분리
❌ "내 컴엔 되는데요" 현상
❌ 배포: 수개월에 한 번
❌ 장애 시 책임 전가
❌ 수동 배포 = 휴먼에러 다수
✅ DevOps 방식
✅ 개발+운영 공동 책임
✅ Docker로 환경 완전 통일
✅ 배포: 하루에도 수십 번
✅ 장애 시 함께 빠른 대응
✅ CI/CD 자동화 100%

📊 DevOps 도입 후 실제 효과 (DORA 리서치)

208x
배포 빈도 증가
106x
리드타임 감소
2604x
장애복구 빨라짐
7x
변경 실패율 감소

🗺️ DevOps 전체 도구 생태계

📝
소스 관리
Git · GitHub · GitLab
🔨
CI/CD
GitHub Actions · Jenkins
🐳
컨테이너
Docker · Kubernetes
☁️
클라우드
AWS · GCP · Azure · NCP
🌐
웹서버
Nginx · Apache · Caddy
📊
모니터링
Prometheus · Grafana · Datadog

🐧 Section 02. Linux 서버 완전 정복

서버의 96%가 Linux — 백엔드 개발자의 기본 무기

🔑 SSH 서버 접속부터 시작

# EC2 인스턴스 접속
ssh -i ~/.ssh/my-key.pem ubuntu@43.201.xxx.xxx
# 권한 오류 해결
chmod 400 ~/.ssh/my-key.pem
# SSH config 단축키 설정 (~/.ssh/config)
Host myserver
HostName 43.201.xxx.xxx
User ubuntu
IdentityFile ~/.ssh/my-key.pem
# 이후 이렇게만 접속!
ssh myserver

🛠️ 필수 Linux 명령어 완전 정리

카테고리 명령어 용도 & 예시
📂 파일 탐색 ls -la / cd / pwd ls -la /var/log (숨김포함 상세)
📝 파일 내용 cat / tail / grep tail -f app.log | grep ERROR
⚙️ 프로세스 ps / kill / top / htop ps aux | grep node
🌐 네트워크 ss / curl / netstat ss -tulnp | grep 3000
💾 디스크/메모리 df -h / free -h df -h (장애 시 디스크 풀 확인)
🔐 권한 chmod / chown / sudo chmod 755 deploy.sh
🔧 서비스 systemctl / journalctl journalctl -u nginx -f

🔐 방화벽(UFW) + 서버 보안 기초

# UFW 방화벽 설정
sudo ufw enable
sudo ufw allow 22/tcp   # SSH
sudo ufw allow 80/tcp   # HTTP
sudo ufw allow 443/tcp  # HTTPS
# fail2ban 브루트포스 방지
sudo apt install fail2ban -y && sudo systemctl enable fail2ban
# 로그 실시간 감시
tail -f /var/log/syslog
journalctl -f --since "5 min ago"

📜 배포 자동화 셸 스크립트

#!/bin/bash
# deploy.sh - 롤백 포함 배포 스크립트
set -e                            # 에러 시 즉시 종료
APP_DIR="/app"
cd $APP_DIR
# 새 이미지 pull
docker compose pull app
# 무중단 재배포
docker compose up -d --no-deps app
# 헬스체크
sleep 5 && curl -sf http://localhost:3000/health || { echo "롤백!"; exit 1; }
echo "✅ 배포 완료: $(date)"

🐳 Section 03. Docker 완전 정복 (기초~고급)

"내 컴에선 되는데요"를 영원히 없애주는 기술

🍱 도시락 비유로 이해하기

도시락은 어디서 먹든 항상 같은 내용물! Docker도 마찬가지입니다.

📄
Dockerfile
이미지 생성 명세
📦
Image
앱 설계도 (불변)
🏃
Container
실행 중인 인스턴스
🏭
Registry
이미지 저장/공유

📝 Dockerfile 완전 가이드 — NestJS 프로덕션용 (멀티스테이지)

# ============ Stage 1: 의존성 ============
FROM
node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# ============ Stage 2: 빌드 ============
FROM
node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# ============ Stage 3: 프로덕션 ============
FROM
node:20-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 -S nodejs && adduser -S nestjs -u 1001
COPY --from=builder --chown=nestjs:nodejs /app/dist ./dist
COPY --from=deps --chown=nestjs:nodejs /app/node_modules ./node_modules
USER nestjs
EXPOSE 3000
# 헬스체크 필수!
HEALTHCHECK --interval=30s --timeout=3s
  CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/main.js"]
💡 멀티 스테이지 빌드 효과
빌드 도구 제외 → 이미지 크기: 1.2GB → 180MB (85% 감소!)

⚡ Docker 핵심 명령어 A-Z

🔨 이미지 관리
docker build -t myapp:1.0 .
docker build --no-cache -t myapp .
docker images
docker rmi myapp:1.0
docker push user/myapp:1.0
🏃 컨테이너 관리
docker run -d -p 3000:3000 myapp
docker ps -a
docker logs -f --tail=100 app
docker exec -it app /bin/sh
docker stop app && docker rm app
🗂️ 볼륨 & 네트워크
docker volume create pgdata
docker network create mynet
docker system df
docker system prune -a
⚠️ .dockerignore 필수!
node_modules
.git
.env*
dist
coverage
*.log

🎼 Section 04. Docker Compose 멀티 컨테이너

NestJS + PostgreSQL + Redis + Nginx을 한 파일로!

📄 실전 docker-compose.yml (프로덕션 풀스택)

services
:

# ─── NestJS 앱 ─────────────────
app:
  build:
    context: .
    target: production
  container_name: nestjs-app
  restart: unless-stopped
  ports: ["3000:3000"]
  env_file: [.env.production]
  depends_on:
    postgres: {condition: service_healthy}
    redis: {condition: service_healthy}
  healthcheck:
    test: ["CMD","wget","-qO-","http://localhost:3000/health"]
    interval: 30s
    retries: 3
  networks: [backend]
  logging:
    driver: "json-file"
    options: {max-size: "10m", max-file: "3"}

# ─── PostgreSQL ────────────────
postgres:
  image: postgres:16-alpine
  container_name: postgres-db
  restart: unless-stopped
  environment:
    POSTGRES_DB: ${DB_NAME}
    POSTGRES_USER: ${DB_USER}
    POSTGRES_PASSWORD: ${DB_PASSWORD}
  volumes: [pgdata:/var/lib/postgresql/data]
  healthcheck:
    test: ["CMD-SHELL","pg_isready -U ${DB_USER}"]
    interval: 10s
    retries: 5
  ports: ["127.0.0.1:5432:5432"]
  networks: [backend]

# ─── Redis ─────────────────────
redis:
  image: redis:7-alpine
  container_name: redis-cache
  restart: unless-stopped
  command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 256mb
  volumes: [redisdata:/data]
  healthcheck:
    test: ["CMD","redis-cli","-a","${REDIS_PASSWORD}","ping"]
    interval: 10s
  networks: [backend]

# ─── Nginx ─────────────────────
nginx:
  image: nginx:1.25-alpine
  container_name: nginx-proxy
  restart: unless-stopped
  ports: ["80:80","443:443"]
  volumes:
    - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    - certbot-etc:/etc/letsencrypt
  depends_on: [app]
  networks: [backend]

volumes
: {pgdata:, redisdata:, certbot-etc:}
networks
: {backend: {driver: bridge}}

⚡ Docker Compose 핵심 명령어

# 시작/재빌드/로그/상태/중지
docker compose up -d
docker compose up -d --build --no-deps app   # 특정 서비스 재빌드
docker compose logs -f --tail=100
docker compose ps
docker compose exec app sh
docker compose down                        # 볼륨 유지
docker compose down -v                     # ⚠️ DB 데이터 삭제!

🌐 Section 05. Nginx 리버스 프록시 + HTTPS

도메인 연결 · SSL · 로드밸런싱 · Rate Limiting — 실서비스 필수

🏨 호텔 프런트 데스크 비유

손님(사용자)은 항상 프런트(Nginx :443)에 옵니다. 어느 방(포트)으로 갈지는 프런트가 결정. 손님은 방 번호(:3000)를 몰라도 됩니다 → 보안!

# nginx.conf (프로덕션 완전 설정)
events { worker_connections 2048; multi_accept on; }
http {
# Rate Limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# Upstream
upstream nestjs { server app:3000; keepalive 32; }
# HTTP → HTTPS 리다이렉트
server {
listen 80;
    server_name api.myapp.com;
    return 301 https://$host$request_uri;
}
# HTTPS 서버
server {
listen 443 ssl http2;
    server_name api.myapp.com;
    ssl_certificate /etc/letsencrypt/live/api.myapp.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.myapp.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header Strict-Transport-Security "max-age=63072000" always;
    location /api {
      limit_req zone=api burst=20 nodelay;
      proxy_pass http://nestjs;
      proxy_http_version 1.1;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
}

🔒 Let's Encrypt 무료 SSL 발급

# 설치 및 발급
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d api.myapp.com
# 크론탭 자동 갱신 (90일마다)
0 0,12 * * * certbot renew --quiet --post-hook "nginx -s reload"

⚙️ Section 06. PM2 프로세스 관리 + 무중단 배포

서버 꺼도 앱이 살아있는 비결 — 클러스터 모드로 성능 2배

📄 ecosystem.config.js — 현업 수준 설정

// ecosystem.config.js
module.exports = { apps: [{
name: 'nestjs-app',
script: 'dist/main.js',
// 클러스터 모드: CPU 코어 수만큼
instances: 'max',
exec_mode: 'cluster',
env_production: { NODE_ENV: 'production', PORT: 3000 },
max_memory_restart: '1G',
out_file: './logs/out.log',
error_file: './logs/error.log',
autorestart: true,
restart_delay: 3000
}]};

⚡ PM2 핵심 명령어

pm2 start ecosystem.config.js --env production
pm2 reload nestjs-app          # ✅ 무중단 재시작
pm2 status / pm2 monit
pm2 logs nestjs-app --lines 200
pm2 startup && pm2 save        # 부팅 시 자동시작

⚙️ Section 07. GitHub Actions CI/CD 완전정복

push 한 번 → 테스트 → 빌드 → 배포 — 완전 자동화!

🏭 CI/CD 파이프라인 전체 흐름

📝
git push
🔨
lint+test
🐳
Docker
build+push
🚀
SSH
배포(EC2)
서비스
운영중

📄 .github/workflows/deploy.yml 완전 구현

name
: 🚀 CI/CD Pipeline

on
:
push: {branches: [main, develop]}
pull_request: {branches: [main]}

env
:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs
:

# ════ Job 1: 테스트 ════
test:
  runs-on: ubuntu-latest
  services:
    postgres:
      image: postgres:16
      env: {POSTGRES_PASSWORD: testpass, POSTGRES_DB: testdb}
      ports: ['5432:5432']
      options: --health-cmd pg_isready
    redis:
      image: redis:7
      ports: ['6379:6379']
  steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with: {node-version: '20', cache: 'npm'}
    - run: npm ci
    - run: npm run lint
    - run: npm run test:cov
    - run: npm run test:e2e
      env:
        DATABASE_URL: postgresql://postgres:testpass@localhost:5432/testdb
        REDIS_URL: redis://localhost:6379

# ════ Job 2: Docker 빌드 ════
build:
  needs: test
  runs-on: ubuntu-latest
  if: github.ref == 'refs/heads/main'
  permissions: {contents: read, packages: write}
  steps:
    - uses: actions/checkout@v4
    - name: GHCR 로그인
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    - name: 빌드 & 푸시
      uses: docker/build-push-action@v5
      with:
        push: true
        target: production
        tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
        cache-from: type=gha
        cache-to: type=gha,mode=max

# ════ Job 3: EC2 배포 ════
deploy:
  needs: build
  runs-on: ubuntu-latest
  environment: production
  steps:
    - name: EC2 SSH 배포
      uses: appleboy/ssh-action@v1.0.0
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ubuntu
        key: ${{ secrets.EC2_SSH_KEY }}
        script: |
          cd /app
          docker compose pull app
          docker compose up -d --no-deps --remove-orphans app
          docker image prune -f
          echo "✅ 배포완료: $(date)"

🔑 GitHub Secrets 설정 (Settings → Secrets → Actions)

EC2_HOST EC2 퍼블릭 IP
EC2_SSH_KEY .pem 파일 전체 내용
GITHUB_TOKEN 자동 제공 (설정 불필요)

☁️ Section 08. AWS EC2 + RDS + S3 실전 배포

국내 스타트업 70%가 선택 — 처음부터 프로덕션까지

🏗️ AWS 핵심 서비스 완전 정리

서비스 역할 비유 월 비용
EC2 t3.small 가상 서버 임대 컴퓨터 ~$17
RDS (PostgreSQL) 관리형 DB 전문 창고 관리인 ~$25
S3 객체 스토리지 무한 USB ~$0.023/GB
ElastiCache 관리형 Redis 초고속 메모 ~$20
ALB 로드 밸런서 고객 안내 데스크 ~$20
CloudFront CDN 전국 배송 허브 ~$0.0085/GB

🚀 EC2 서버 초기화 스크립트 (한 번에 실행)

#!/bin/bash
# Ubuntu 22.04 EC2 초기 세팅
set -e
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git unzip htop fail2ban
# Docker 공식 설치
curl -fsSL https://get.docker.com | sudo bash
sudo usermod -aG docker ubuntu
sudo apt install -y docker-compose-plugin
# Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
sudo apt install -y nodejs
sudo npm install -g pm2
# Nginx
sudo apt install -y nginx certbot python3-certbot-nginx
# UFW 방화벽
sudo ufw allow 22 && sudo ufw allow 80 && sudo ufw allow 443 && sudo ufw --force enable
# 앱 디렉토리
sudo mkdir -p /app && sudo chown ubuntu:ubuntu /app
echo "✅ 서버 초기 세팅 완료!"

🗄️ S3 파일 업로드 — NestJS + AWS SDK v3

// s3.service.ts
import
{ Injectable } from '@nestjs/common';
import
{ S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
import
{ getSignedUrl } from '@aws-sdk/s3-request-presigner';

@Injectable()
export class S3Service {
private readonly s3 = new S3Client({
region: process.env.AWS_REGION,
credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY },
});

async upload(file: Express.Multer.File, folder = 'uploads') {
const key = `${folder}/${Date.now()}-${file.originalname}`;
await this.s3.send(new PutObjectCommand({ Bucket: process.env.AWS_S3_BUCKET, Key: key, Body: file.buffer, ContentType: file.mimetype }));
return `https://${process.env.AWS_S3_BUCKET}.s3.amazonaws.com/${key}`;
}

async getPresignedUrl(key: string) {
return getSignedUrl(this.s3, new GetObjectCommand({ Bucket: process.env.AWS_S3_BUCKET, Key: key }), { expiresIn: 3600 });
}
}

🔐 Section 09. 환경변수 & 시크릿 관리

비밀번호를 코드에 박으면 AWS 요금 폭탄! 올바른 관리법

🚨 절대 하면 안 되는 것!

// ❌ 절대 금지!
const dbPass = 'mypassword';
const awsKey = 'AKIAIOSFODNN7EXAMPLE';
const jwt = 'super-secret';
// ✅ 올바른 방법!
const dbPass = process.env.DB_PASSWORD;
const awsKey = process.env.AWS_ACCESS_KEY_ID;
const jwt = process.env.JWT_SECRET;

📋 환경별 .env 파일 구조

.env.development (로컬)
NODE_ENV=development
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp_dev
DB_PASSWORD=devpass
JWT_SECRET=dev-secret-key
REDIS_URL=redis://localhost:6379
.env.production (서버 전용 — 커밋 금지!)
NODE_ENV=production
PORT=3000
DB_HOST=mydb.xxx.rds.amazonaws.com
DB_PORT=5432
DB_NAME=myapp_prod
DB_PASSWORD=[절대 커밋 금지]
JWT_SECRET=[최소 32자 랜덤]
AWS_S3_BUCKET=myapp-prod
📌 .gitignore에 반드시!
.env
.env.local
.env.development
.env.production

🔒 NestJS ConfigModule + Joi 검증

// app.module.ts — 앱 시작 시점에 누락/오타 즉시 감지!
ConfigModule.forRoot({
isGlobal: true,
envFilePath: `.env.${process.env.NODE_ENV || 'development'}`,
validationSchema: Joi.object({
NODE_ENV: Joi.string().valid('development','production','test').required(),
PORT: Joi.number().default(3000),
DB_HOST: Joi.string().required(),
DB_PASSWORD: Joi.string().min(8).required(),
JWT_SECRET: Joi.string().min(32).required(),
}),
})

🏆 시크릿 관리 도구 비교

도구 추천 상황 비용
.env 파일 로컬 개발, 소규모 무료
GitHub Secrets CI/CD 파이프라인 무료
AWS Secrets Manager AWS 프로덕션 $0.4/시크릿/월
HashiCorp Vault 대규모 엔터프라이즈 오픈소스/유료

📊 Section 10. 모니터링 & 로깅 완전 정복

장애 전에 알아채기 — Prometheus + Grafana + Winston

👀 4 Golden Signals (Google SRE 핵심 지표)

⏱️
Latency
응답 시간
P95 <200ms 목표
📊
Traffic
트래픽 양
초당 요청 수(RPS)
Errors
에러율
5xx <0.1% 목표
💾
Saturation
포화도
CPU/메모리 <80%

📦 NestJS Winston 구조화 로깅

// npm install nest-winston winston winston-daily-rotate-file
WinstonModule.forRoot({
transports: [
// 개발: 컬러 콘솔
new winston.transports.Console({
format: winston.format.combine(winston.format.timestamp({format:'HH:mm:ss'}), winston.format.colorize(), winston.format.printf(({timestamp,level,message,context}) => `[${timestamp}] ${level} [${context||'App'}] ${message}`)),
}),
// 프로덕션: 날짜별 파일 저장 (14일 보관)
new (winston.transports as any).DailyRotateFile({
filename: 'logs/app-%DATE%.log',
datePattern: 'YYYY-MM-DD',
maxSize: '20m', maxFiles: '14d',
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
}),
]
})

📈 Prometheus 메트릭 수집 + Grafana 대시보드

# npm install @willsoto/nestjs-prometheus prom-client
// app.module.ts
PrometheusModule.register({ path: '/metrics', defaultMetrics: { enabled: true } })

// 커스텀 메트릭 예시
@Injectable()
export class
MetricsService {
private httpReqCounter = new Counter({
name: 'http_requests_total',
help: 'Total HTTP requests',
labelNames: ['method','path','status'],
});
increment(method,path,status) { this.httpReqCounter.labels(method,path,String(status)).inc(); }
}

🔀 Section 11. 블루그린 & 카나리 배포 전략

다운타임 제로 배포 — 대기업에서 사용하는 전략

🎨 배포 전략 3가지 완전 비교

전략 방식 다운타임 롤백 속도 비용
롤링 업데이트 인스턴스 순차 교체 없음 보통 낮음
블루/그린 두 환경 동시 운영 후 전환 없음 즉시(<1초) 2배 비용
카나리 배포 소수 트래픽으로 먼저 테스트 없음 빠름 약간 높음

☸️ Section 12. Kubernetes 입문

Docker Compose의 다음 단계 — 대규모 서비스 표준

🏗️ K8s 핵심 개념

Pod
K8s 최소 배포 단위
컨테이너 1개 이상
같은 IP 공유
Deployment
Pod 복제본 관리
롤링 업데이트
원하는 상태 유지
Service
안정적 네트워크
로드밸런싱
DNS 자동 등록
Ingress
외부 HTTP/S 진입
도메인 라우팅
SSL 처리
HPA
CPU 기준 자동 확장
트래픽 급증 대응
min~max 범위 설정
ConfigMap/Secret
설정 & 시크릿 분리
Pod 재시작 없이 업데이트

📄 NestJS K8s Deployment + HPA

apiVersion
: apps/v1
kind
: Deployment
metadata: {name: nestjs-app}
spec
:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate: {maxSurge: 1, maxUnavailable: 0}    # 무중단!
template:
spec:
containers:
- name: nestjs
image: ghcr.io/myorg/myapp:latest
resources:
requests: {memory: "256Mi", cpu: "250m"}
limits: {memory: "512Mi", cpu: "500m"}
readinessProbe: {httpGet: {path: /health, port: 3000}, initialDelaySeconds: 10}

---
# HPA: CPU 70% 초과 시 자동 스케일 아웃
apiVersion
: autoscaling/v2
kind
: HorizontalPodAutoscaler
spec: {minReplicas: 2, maxReplicas: 10, metrics: [{type: Resource, resource: {name: cpu, target: {type: Utilization, averageUtilization: 70}}}]}

🚨 Section 13. 장애 대응 & 포스트모템

새벽 3시 알람 — 프로처럼 장애 대응하는 법

🔥 장애 대응 5단계 프로세스

1
탐지 — Grafana/슬랙 알림 수신
현재 영향 범위 즉시 파악 (몇 % 사용자?)
2
완화 — 원인 파악 전에 롤백 먼저!
서비스 복구 최우선 → docker compose up --no-deps 이전 이미지
3
조사 — 로그 & 리소스 확인
pm2 logs / docker logs / kubectl logs → DB연결? OOM? 디스크풀?
4
해결 & 재배포
근본 원인 수정 → CI/CD로 재배포 → 정상 확인
5
포스트모템 작성 (24시간 이내)
타임라인 → 근본원인 → 재발방지책 → 팀 전체 공유

📋 장애 대응 체크리스트

# 1. 서비스 상태
curl -I https://api.myapp.com/health
# 2. 컨테이너/프로세스
docker compose ps && pm2 status
# 3. 최근 로그
docker compose logs --tail=100 app
# 4. 시스템 리소스
free -h && df -h && top
# 5. DB 연결
docker compose exec postgres pg_isready

💼 Section 14. 면접 Q&A + 체크리스트 + 로드맵

취업 완전 정복 — 실제 기술 면접 DevOps 질문들

❓ 실제 기술 면접 Q&A

Q1. Docker와 VM(가상머신)의 차이점?
A: VM은 OS 전체를 가상화해 수GB/수분 부팅. Docker는 OS 커널 공유, 프로세스 격리로 수MB/수초 시작. 현업에서는 환경 통일 목적으로 Docker를 주로 사용합니다.
Q2. CI/CD 파이프라인을 직접 구축해본 경험이 있나요?
A: GitHub Actions로 main push 시 ①lint+test → ②Docker 빌드/GHCR 푸시 → ③EC2 SSH 배포 자동화를 구축했습니다. 배포 시간이 40분→4분으로 단축되었습니다.
Q3. 무중단 배포를 어떻게 구현하나요?
A: ①PM2 cluster 모드 reload ②Docker Compose --no-deps 교체 ③K8s RollingUpdate (maxUnavailable:0) ④블루/그린 Nginx 업스트림 즉시 전환 — 상황에 맞게 선택합니다.
Q4. 환경변수 관리는 어떻게 하시나요?
A: .env는 절대 Git 커밋 안 합니다. 로컬=.env.development, CI/CD=GitHub Secrets, 서버=.env.production (서버 직접 보관). NestJS ConfigModule+Joi로 시작 시점에 검증합니다.
Q5. 서비스 장애 발생 시 어떻게 대응하나요?
A: ①Grafana 알림 수신 ②즉시 롤백 (서비스 복구 우선) ③로그/리소스 확인 ④근본 원인 수정 후 재배포 ⑤24시간 내 포스트모템 작성. 평상시 /health 엔드포인트와 모니터링 연동이 필수입니다.
Q6. Nginx를 왜 사용하나요?
A: ①리버스 프록시로 내부 포트 보호 ②SSL/TLS 종단처리 ③정적 파일 서빙(10배 빠름) ④Rate Limiting으로 DDoS 방어 ⑤로드밸런싱 ⑥Gzip 압축. 현업에서는 거의 무조건 Nginx를 앞에 둡니다.

✅ DevOps 현업 준비도 체크리스트

🌱 주니어 (신입)
☐ Docker run/build
☐ docker-compose up
☐ .env 관리
☐ SSH 서버 접속
☐ Linux 기본 명령어
☐ GitHub Actions 기본
☐ Nginx 기본 설정
🌿 미드레벨 (1~3년)
☐ CI/CD 파이프라인 구축
☐ Nginx SSL + 리버스프록시
☐ PM2 클러스터 모드
☐ AWS EC2/RDS/S3
☐ 무중단 배포
☐ Winston 구조화 로깅
☐ 장애 대응 경험
🌳 시니어 (3년+)
☐ Kubernetes 운영
☐ Prometheus/Grafana
☐ 블루/그린 카나리 배포
☐ AWS VPC/ALB 설계
☐ IaC (Terraform)
☐ 포스트모템 문화
☐ SLA/SLO 운영

🗺️ DevOps 마스터 로드맵 (6단계)

1
Linux 기초 & SSH (1주)
터미널 명령어, SSH 접속, 방화벽, 셸 스크립트
2
Docker + Docker Compose (1주)
Dockerfile 멀티스테이지 빌드, 멀티 컨테이너 구성
3
AWS EC2 + Nginx + PM2 (1~2주)
실서버 배포, HTTPS, 무중단 서비스
4
GitHub Actions CI/CD (1주)
자동 테스트 → Docker 빌드 → EC2 자동 배포
5
모니터링 + 장애 대응 (1주)
Prometheus/Grafana, 슬랙 알림, 포스트모템
6
Kubernetes 입문 (2~3주)
Pod/Deployment/HPA — EKS(AWS) 실습
🚀

BackendDevGuide0007 완료!

Docker부터 Kubernetes까지 — 이제 코드를 세상에 배포할 수 있습니다!
다음: BackendDevGuide0008 - 성능 최적화와 캐싱 전략 A-Z

✅ Docker 완전정복✅ CI/CD 자동화✅ AWS 실전 배포✅ 모니터링 & 장애대응✅ Kubernetes 입문
반응형