서비스를 개발하면서 가장 처음 마주한 배포 환경은 단순한 EC2 기반 수동 배포였다. 스케일링된 모든 인스턴스에 접속해서 수작업으로 코드를 최신화하고, 의존성을 설치하고, 서버를 재시작했다. 이 방식은 실수가 잦고 반복 작업이 많아 생산성과 안정성 모두에 문제를 야기했다. 배포 시간도 오래 소요될 뿐더러, 위험도가 높아 배포 가능인원이 제한됐다. 오류 발생 시 롤백하는 것도 어려웠다.
배포 환경의 일관성과 자동화를 고민하면서, 일단 Docker 기반의 배포를 진행해야겠다고 생각했고, ECS와 Elastic Beanstalk 사이에서 고민을 하다, ECS로 선택했다.
결론적으로, Beanstalk은 빠른 MVP 배포엔 적합하지만, 서비스 구조가 복잡해지고 운영 요소가 많아질수록 ECS가 훨씬 더 적합하다는 판단이었다.
production과 development 클러스터를 따로 구성했다. 각 클러스터는 다음과 같은 서비스들로 구성되어 있다.
각 서비스마다 스케일링 정책, 배포 주기, 환경변수를 독립적으로 설정할 수 있다
처음에는 로컬에서 수동으로 Docker 이미지를 빌드하고, ECR에 푸시한 뒤 콘솔에서 ECS 서비스를 강제 업데이트했는데, 휴먼에러가 발생하거나 개발자마다 빌드환경이 달라서 이슈가 생기기도 했다.현재 Docker는 앱을 빌드하지는 않고, CI에서 미리 빌드된 Next.js standalone 결과물을 패키징해서 실행 가능한 이미지로 만드는 역할만 수행한다.
Next.js 빌드 시 생성된 .next/static 및 public/next-assets를 S3에 업로드해 CloudFront와 연결했다. 정적 자산은 CloudFront를 통해 캐싱되고, SSR 페이지는 ECS에서 처리된다.
배포 시간 단축: 수동 => 자동 배포
환경 일관성 확보: Docker 기반으로 어디서든 동일한 실행 환경
배포 신뢰도 향상: 커밋 태그 기반 이미지 관리, 롤백 쉬움
운영 효율 증가: 서비스별 배포/스케일링/모니터링 분리 운영