개발이군고구마

[멱살잡고 DevOps] 2. 배포 아키텍처 설계 본문

Cloud Deploy

[멱살잡고 DevOps] 2. 배포 아키텍처 설계

김구황 2025. 7. 15. 08:48
728x90

1. 요구사항

[개발 방법] 

Backend와 Frontend는 각각 다른 리파지토리로 관리

 

[기술 스텍]

Backend : Node.js

DB: MongoDB

Frontend : React

Docker 및 Docker compose 사용 

 

[배포 프로덕션]

AWS 프리티어를 사용 (프리티어의 기능을 최대한 사용해야함) 

EC2 1개만 사용함 

Github Action으로 CI/CD 자동화 예정 

 

 

2. 설계 빌드 업 

1) CI/CD 생각하지 않고 Docker 사용 중점

✅ 고려한 것들 

백엔드와 Mongo 그리고 React 설정도 다 컨테이너에 넣어서 EC2로 넣으면 되는 거 아닐까? 

 

❎ 문제점

  • EC2 1개만 쓰는 와중에 모든 컨테이너를 다 EC2에 놓는 것은 서버 부하가 있을 수 있음 
    • DB 서버를 Mongo 에서 제공하는 서버를 사용하거나
    • EBS 볼륨두어 데이터에 영속성을 확보하는 방법 
  • EC2 1개만 사용을 하는 와중에도 Ngnix와 같은 웹서버를 앞에 둠으로써 보안과 부하분산(확장성)을 대비할 수가 있음 

 

 

2) 서버 별로 분리하여 배포하는 방법 

 

👩‍💻 개발자 관점

 

 

 

🤹‍♀️ 사용자 관점

 

✅ 고려한 것들 

  • DB 는 Mongo에서 제공하는 서버를 사용하여 EC2의 부하를 줄인다. 
  • .S3 버킷에 프론트 엔드 서버 
    • 대용량 트래픽에서도 확장성과 성능을 보장할 수 있음 
    • Docker 컨테이너로 띄우기보다 비용·관리 측면에서 더 효율적
  • CloudFront 경로 기반 분기 
    • CDN, SSL 등을 별도 구성 없이 활용 (CDN 캐싱 효율의 이점을 누릴 수가 있음 )
    • Nginx에 TLS 관리를 따로 해주지 않아도 됨 
  • Nginx 웹 서버 사용
    • 보안과 안정성, 확장성 확보 (EC2 증가 대비) 

 

 

❎ 문제점

  • Origin–CloudFront 간 트래픽이 HTTP일 경우 암호화되지 않음
    • Nginx 내부망(프라이빗 서브넷)에 배치해야 보안 강화  
  • EC2가 병목
    • 오토스케일링(AWS Auto Scaling, ECS/Fargate), API Gateway/Lambda 등으로 API 레이어를 보완해나가야 함 

 

 

3. 최종 방안 

  • 애플리케이션 구성
    • Node.js (API 서버)
    • MongoDB (데이터베이스)
    • React (프론트엔드)
  • 배포 환경
    • EC2 t2.micro 1대 (AWS Free Tier)
    • Docker Compose로 백엔드( Node.js + MongoDB → Atlas 전환 가능 ), Nginx 리버스 프록시 구성
    • React 정적 파일은 S3 + CloudFront로 호스팅
  • CI/CD
    • GitHub Actions: 코드 푸시 시 Docker Hub에 빌드·푸시 → EC2에서 pull & up

 

 

4. 한계 

1. 스테이징 (멀티 환경) 구축

사이드 프로젝트는 금액의 한계로 이 단계까지는 진입을 하지는 못 하지만 실무에선 운영/개발 이 분리되어 있음 

 

1) 인프라 분리 

ㄴ같은 아키텍처 모델로 추가 생성

  • AWS 계정을 별도로 사용할 수도 있음 (운용상의 편의)
  • VPC와 보안그룹을 분리 ✨(이 부분 좀 더 살펴봐야) 
EC2 인스턴스 dev-api.example.com (t2.micro) api.example.com (t2.micro or 상위 타입)
S3 버킷 myapp-dev-static myapp-prod-static
CloudFront Distribution–dev Distribution–prod
MongoDB Atlas 무료 티어 클러스터 (dev-cluster) 유료/스케일 가능한 클러스터 (prod-cluster)
도메인·DNS dev.example.com, api.dev.example.com example.com, api.example.com
SSL 인증서(ACM) dev 도메인용 인증서 prod 도메인용 인증서

 

 

2) 환경 변수 설정 

a. .env.dev 와 .env 분리 

  • mongoDB
  • React
  • Node Env 

b. docker compose

 

  • docker-compose.yml (공통)
  • docker-compose.dev.yml
  • docker-compose.prod.yml

c. Nginx 설정 분리 

서버 url 을 환경별로 다르게 설정 

  • nginx.dev.conf
server {
  server_name api.dev.example.com;
  location /api/ { proxy_pass http://api:3000; }
}
  • nginx.prod.conf
server {
  server_name api.example.com;
  location /api/ { proxy_pass http://api:3000; }
}

 

 

 

3) CI/CD 파이프라인 분리

 

  • Git 브랜치 전략
    • main → prod
    • develop 또는 feature/* → dev
  • GitHub Actions 워크플로우 예시
    • .github/workflows/deploy-dev.yml
    • .github/workflows/deploy-prod.yml
  • Secrets & Environments에서 dev / prod 각각에 SSH 키, 도메인 등 시크릿을 관리.
    • Environment secrets  에 환경에 맞는 secret 변수를 설정해줌 
    •  github ref 등으로 구분하여 그에 맞는 yml 파일을 실행하게 함
  - name: Build & Push Images
    run: |
      TAG=${{ github.ref == 'refs/heads/main' && 'prod' || 'dev' }}
      docker build -t myrepo/api:$TAG ./backend
      docker push myrepo/api:$TAG
      docker build -t myrepo/frontend:$TAG ./frontend
      docker push myrepo/frontend:$TAG

 

 

 

 

2. 확장성

ㄴ현재는 EC2를 여러개 사용하는 경우 확장성에 대비하지 못하는 구조 (ECS는 유료 서비스이기 때문에 프리티어로 커버가 안된다)

만약 EC2가 증가한다면, 스크립트에 각각 타겟팅 되는 EC2를 작성해줘야 함 

 

1) ECS를 활용하여 EC2 병목 등을 대비할 수 있음 

ALB 에서 분기처리 하여 cloudfront로 들어가게 할 수도 있음 

 

 

2) subnet 분리

ㄴ 네트워크 레벨에서 격리시키기 위함 

ㄴ 이와 같은 VPC를 2개로 운영을 해도 되고, 하나의 VPC 안에 각각의 subnet을 주고 운영을 해도 됨 

private/ public subnet 을 나눈 예

  • 퍼블릭 영역 - ALB
  • 프라이빗 영역 - API 서버 
  • * S3/Cloudfront - VPC 외부에 위치함