클라우드‐WHY‐CD - 100-hours-a-week/16-Hot6-wiki GitHub Wiki

CD

목차

왜 CD 과정이 필요한가요?

CD(Continuous Delivery 또는 Continuous Deployment)는 코드가 빌드된 이후 실제 서비스에 반영되기까지의 전 과정을 자동화하는 기술입니다.
CI가 "쓸 수 있는 코드"를 만들어주는 과정이라면, CD는 "그 코드를 실제 서비스로 전환"하는 연결고리입니다.

1. 수작업 배포에서 마주한 문제

프로젝트 초기, 저희는 직접 SSH로 서버에 접속하여
git pullsystemctl restart 또는 npm run buildscp 전송 등 직접적인 수작업 배포를 통해 서비스를 운영했습니다.

이 방식은 초기에는 충분히 단순하고 빠르게 적용할 수 있었지만, 실제 운영 및 반복 배포를 하며 다음과 같은 문제가 발생했습니다.

문제 상황:

  • FE 정적 자산 누락
    → CloudFront 캐시 무효화를 빠뜨려 구버전 UI가 노출되거나,
    S3에 누락된 파일로 인해 이미지가 표시되지 않는 문제가 발생함
  • 배포 순서 오류
    → AI 서버가 먼저 재시작되기 전에 프론트엔드에서 호출되어 5xx 응답이 발생하는 등 race condition이 빈번하게 발생
  • SSH 명령어 실수
    → 오타나 권한 설정 실수로 인해 서버 프로세스가 죽거나, 로그를 남기지 않고 종료되어 원인 분석이 어려워짐

그 외 예측 가능했던 어려움:

  • 팀원 간 배포 방식이 서로 달라 일관성이 떨어짐
  • 주말이나 야간에 장애 발생 시, 배포자가 아니면 대응이 불가능
  • rollout 이후 FE/BE/AI 중 하나라도 실패하면 전체 시스템이 비정상 상태로 유지됨

이러한 경험을 통해, 단순히 “배포만 되면 된다”는 생각이 얼마나 불안정한지 실감하게 되었습니다.
서비스가 점점 복잡해질수록, **“사람이 빠르게 반복하지 못하는 작업은 기계에 맡기는 것”**이 결국 안정적인 운영의 핵심이라는 결론에 도달했습니다.

2. CD 도입이 왜 해답인가?

CD는 단순히 자동으로 배포하는 기능이 아니라,
서비스를 안전하게 최신 상태로 유지하는 전체 흐름을 자동화하는 시스템입니다.

수작업 배포에서 겪은 문제 CD를 통한 해결
FE 캐시 무효화 누락 FE push 시 S3 업로드 + CloudFront 캐시 무효화 자동 처리
배포 순서 꼬임 BE/AI → FE → CloudFront 전환 순서 고정 및 스크립트화
SSH 실수, 오타, 누락 scp + systemctl restart가 GitHub Actions로 관리됨
BE/AI 서버마다 수동 재배포 단일 디스패치로 모든 인스턴스 자동 반영
배포 후 수동 점검 후 잊고 넘어감 수동 테스트 이후 ‘완료’ 워크플로를 트리거하는 2단계 구조 설계

또한, 서비스 특성상 AI 추천 → 이미지 생성 → 프론트 반영까지가 하나의 사용자 흐름인데,
이 흐름의 중간에서 하나라도 배포 누락이 생기면 사용자는 AI 추천 결과를 제대로 확인할 수 없습니다.
즉, CD는 내부 자동화를 넘어서 사용자 경험(UX) 보호 수단이기도 합니다.

3. 서비스 구조에 맞는 CD 전략이 필요했다

저희 팀은 FE/BE/AI가 서로 다른 방식으로 배포되며, 각각 고유한 특성을 가집니다:

  • FE(Next.js)
    → S3에 정적 자산 업로드 + CloudFront 캐시 무효화
  • BE(Spring Boot)
    .jar 배포 후 systemd 기반 restart, 로그 확인 가능
  • AI(FastAPI)
    → 가상환경 경로 고정 + uvicorn 재시작
  • 공통 조건
    → SSH 접속은 Jump Server를 통해야 함
    → 특정 인스턴스만 배포해야 할 때도 있음

이러한 조건에서 단순한 “docker-compose up” 식의 배포가 아닌,
워크플로 기반의 제어 가능한 CD 흐름이 필요했고,
GitHub Actions + scp + systemctl + 캐시 무효화를 조합한 워크플로를 도입했습니다.

또한, 운영(Prod)은 수동 디스패치, 개발(Dev)은 push 자동화 구조를 택해
안정성과 속도를 각각 보장했습니다.

결론

저희 서비스는 단순한 코드 배포가 아니라,
AI 추천 → 이미지 생성 → 사용자 피드백까지의 전체 흐름을 다루는 서비스입니다.
그리고 이 흐름은 하나라도 어긋나면 사용자가 불편함을 느낄 수 있는 구조입니다.

CD는 단순히 "자동화해서 편하다"가 아니라,
서비스를 안전하게 운영하고, 모든 사용자에게 최신 기능과 추천 결과를 정확히 전달하기 위한 핵심 인프라입니다.

"기계가 잘할 수 있는 반복 작업은 자동화하고,
사람은 그 결과를 점검하고 책임지는 구조"가
우리가 CD를 도입한 진짜 이유였습니다.

🔝 Top


왜 CloudFront를 도입했나요?

CloudFront는 AWS에서 제공하는 글로벌 CDN(콘텐츠 전송 네트워크) 서비스로, S3 등에서 호스팅되는 정적 자산을 가까운 엣지 로케이션에서 캐싱하여 전달함으로써 속도와 비용을 모두 최적화해주는 서비스입니다.

우리 서비스는 커뮤니티 기반의 이미지 공유 플랫폼이라는 특성을 갖고 있으며, 단순히 서버에서 소비되는 정적 이미지가 아닌, AI와 사용자 양쪽에서 빈번하게 접근되는 이미지가 많다는 점이 CloudFront 도입의 결정적 이유가 되었습니다.

1. S3 → CloudFront 캐싱은 "AI + 사용자" 양방향 트래픽을 줄인다

우리 서비스에서 업로드된 책상 이미지는 다음과 같은 순서로 소비됩니다:

  1. 사용자가 책상 이미지를 업로드 → S3 저장
  2. GPT-4o, DALL·E 3 등 이미지 생성 AI가 해당 이미지를 참조 (최소 2~3회 요청 발생)
  3. 생성된 이미지를 사용자가 커뮤니티 게시판에서 확인
    모든 사용자 브라우저에서 해당 이미지에 대한 개별 HTTP 요청 발생

즉, 단일 이미지가 업로드된 뒤에도 수십 번의 조회 요청이 발생할 수 있는 구조입니다.

이러한 구조에서 단순히 S3로 모든 요청이 직접 전달된다면 다음과 같은 문제가 생깁니다:

  • S3 read 요금이 기하급수적으로 증가
  • 사용자 접속 지역에 따라 응답 속도 편차 발생
  • 서버/API는 캐싱을 하지 않기 때문에 매 요청마다 정적 자산 비용이 누적

CloudFront는 이러한 요청들을 캐싱해 주는 중간 계층으로,
한 번만 S3에서 가져오고 이후 동일 이미지 요청은 모두 캐시에서 처리하여
트래픽, 응답 속도, 요금 측면 모두에서 이득을 제공합니다.

2. GPT, DALL·E, 사용자까지 HTTPS가 필수

우리 서비스는 다음과 같은 외부 시스템과의 이미지 연동이 많습니다:

  • GPT-4o: 이미지 기반 프롬프트에서 HTTPS 이미지만 인식
  • DALL·E 3: 텍스트 기반 이미지 생성 시에도 외부 이미지 참조 필요
  • Notion-style 게시판: 미리보기에서 HTTPS 이미지 URL 요구
  • 사용자 커뮤니티: 비HTTPS 이미지가 삽입되면 브라우저에서 mixed content 경고

따라서 정적 자산도 반드시 HTTPS 경로로 제공되어야 하며,
CloudFront는 S3 오리진을 자동으로 HTTPS로 Wrapping해 줍니다.

단순히 "보기 좋게 HTTPS가 된다"는 문제를 넘어서,
서비스 연동의 필수 조건으로 작용합니다.

3. CloudFront는 Nginx 및 HTTPS LB와 함께 SSL 기반 전구간 보안의 완성 요소

현재 우리 서비스는 환경에 따라 HTTPS 구성을 다르게 적용하고 있습니다.

  • Dev 서버(GCP): Nginx를 리버스 프록시로 구성하고,
    Let's Encrypt + Certbot을 통해 HTTPS 인증서를 발급받아 적용

    • Certbot 자동 갱신
    • 가벼운 리소스 소모
    • 운영비 없음
  • Prod 서버(GCP): GCP HTTPS Load Balancer를 사용하여
    정식 SSL 인증서를 통한 프록시 HTTPS 라우팅을 제공

CloudFront는 S3 기반 정적 자산에 HTTPS를 적용하고,
Dev 서버의 Nginx와 Prod 서버의 HTTPS LB는 각각 API 및 앱 서버에 HTTPS를 적용함으로써
서비스 전반이 HTTPS 기반으로 안전하게 구성됩니다.

이것은 보안 뿐만 아니라,

  • 이미지 embed 시 신뢰도 확보
  • API 요청 시 브라우저 mixed content 회피
  • OAuth 연동 등 외부 서비스 요구 조건 충족
    등 다양한 요소에 영향을 미칩니다.

4. CloudFront 도입의 추가 이점

항목 설명
성능 향상 사용자 위치 근처의 AWS 엣지 로케이션에서 이미지 제공 → 응답 시간 최소화
트래픽 오프로드 AI 및 사용자 요청 모두 AWS에서 처리 → GCP 인스턴스 부하 감소
요금 절감 S3 read 요청이 캐시 hit로 처리되어 read 요금 절감
TTL 설정 자산 변경 주기에 따라 유연한 캐시 정책 설정 가능 (immutable 이미지에 유리)
도메인 통합 assets.onthe-top.com 등의 커스텀 도메인 구성 가능 (브랜드 일관성)

결론

CloudFront는 단순히 "정적 파일을 빠르게 전달해주는 CDN"이 아니라,
우리 서비스의 구조에서는 다음과 같은 핵심적 역할을 수행합니다:

  • AI 모델과 사용자 모두가 이미지에 잦은 접근을 하기 때문에, 캐싱 효율이 곧 비용 효율과 직결됨
  • S3 read 요청 최적화 + 응답 속도 개선 + 브라우저 보안 정책 대응(HTTPS) 을 동시에 만족
  • Nginx와 함께 서비스 전 구간 HTTPS 보장
  • 커뮤니티 게시판 중심 서비스에 최적화된 캐싱 레이어로 기능

결과적으로, CloudFront는 단순한 성능 도구가 아닌,
서비스 특성과 사용 패턴에 맞춘 필수 인프라 구성 요소였습니다.

🔝 Top


왜 이 dev 구조인가요?

1. 빠른 개발을 위한 자동화 중심 구조

  • Dev 환경은 운영과 달리 빠른 테스트와 반복적인 배포가 핵심입니다.
  • 코드가 dev 브랜치에 병합되면 CI → CD까지 자동으로 실행되며, 클라우드 엔지니어 개입 없이 전체 배포가 완료됩니다.
  • FE는 정적 자산을 S3에 업로드하고 CloudFront 캐시 무효화,
  • BE/AI는 SSH를 통해 서버에 배포되고, systemd 기반 서비스가 자동으로 재시작됩니다.

즉, 빠르고 반복 가능한 실험이 가능한 자동 배포 환경을 제공하는 것이 핵심입니다.

2. Dev 환경도 분리된 FE/BE/AI 구조를 유지

  • FE/BE/AI는 각각 독립적으로 개발되고, 자동으로 배포되기 때문에
  • 특정 컴포넌트만 바꿔도 전체 Dev 환경에서 바로 확인이 가능합니다.
  • 통합된 서버지만 기능적으로는 운영과 동일한 분리를 지향하고 있습니다.

3. 클라우드 리소스를 직접 활용한 운영 시뮬레이션

  • GCE 인스턴스를 통해 서비스를 직접 띄우기 때문에,
  • 단순 테스트 서버가 아닌, 운영과 거의 동일한 조건에서 문제를 조기 포착할 수 있습니다.
  • CloudFront, S3, Nginx, MySQL 등 모든 리소스를 실제와 같은 방식으로 구성하고 있습니다.

4. 무중단 배포를 위한 유연한 서비스 재시작

  • BE(Spring)와 AI(FastAPI)는 systemd 서비스로 관리되어
  • systemctl restart만으로 서비스 중단 없이 최신 코드 적용이 가능합니다.
  • Dev 환경에서도 서비스 안정성을 확보할 수 있도록 설계했습니다.

요약

이 구조는 “개발자의 빠른 실험과 테스트”를 최우선으로 한 Dev 자동화 구조입니다.

  • 클라우드 엔지니어 개입 없이 전체 CD 흐름이 자동화됨
  • FE/BE/AI를 빠르게 반복 배포하여 실험 가능
  • 운영과 유사한 구조로 문제 조기 발견 가능
  • 무중단 배포, 캐시 제어 등 현실적인 시나리오 테스트에 적합

🔝 Top


왜 이 prod 구조인가요?

이 구조는 운영 환경에서의 배포 흐름으로 Dev 환경의 Blue-Green 방식과는 다르게, 직접 서버에 접근해서 배포하는 방식을 사용했습니다.

1. Blue-Green 배포로 리스크 최소화

  • Dev 환경이라도, 여러 기능이 통합된 FE/BE/AI가 동시에 배포되기 때문에
  • 새로 띄운 v2(Green)에서 문제가 생기면 기존 v1(Blue)로 쉽게 되돌릴 수 있도록 설계하였습니다.
  • 리스크를 줄이는 안전한 구조가 필요하기 때문입니다.

2. 수동 제어 지점 확보 (Dispatch + 수동 테스트)

  • 운영 환경에서는 배포를 완전히 자동화하기보다는, 수동 승인 흐름이 중요합니다.
  • workflow_dispatch를 활용하여 배포 시작은 클라우드 엔지니어가 직접 트리거합니다.
  • 또한 실제 트래픽 전환(LB, CloudFront) 전에는 수동 테스트와 점검이 가능하도록 하여, 예기치 못한 문제를 막습니다.

따라서 systemctl 기반의 수동 프로세스 제어도 병행되고 있으며, 이는 운영 환경의 책임감 있는 배포를 위한 장치입니다.

3. CloudFront와 S3 정적 배포의 효율성 활용

  • FE는 정적 자산으로 이루어져 있어, CloudFront 오리진 전환과 S3 무효화를 통해 다운타임 없는 배포가 가능합니다.
  • GCE에 FE 서버를 직접 띄우지 않고 비용 효율적인 정적 호스팅으로 구성하여, 속도와 안정성, 비용 효율성을 동시에 확보했습니다.

4. 기존 인스턴스를 503으로 전환하여 안전 확보

  • 전환 과정에서 이전 인스턴스를 바로 종료하지 않고 503 응답을 내도록 구성하여 캐시 오염, race condition 등을 방지합니다.
  • 실제 인스턴스는 살아 있어, 필요 시 로그 확인, 디버깅 및 롤백이 가능합니다.

운영을 멈추되 관리를 가능하게 하는 유예 상태 구조입니다.

5. 로드밸런서 기반 전환으로 트래픽 제어

  • 배포 전환은 인스턴스가 아니라 LB의 Target Group만 바꾸는 방식으로 진행됩니다.
  • 트래픽 전환이 무중단으로 이뤄지며, 전환 실패 시 기존 Target Group으로 복원만 하면 되기 때문에 유연성과 안정성 모두 확보됩니다.

요약

운영 환경은 실서비스 무중단 보장 + 안정적인 롤백 경로 + 수동 통제 지점 확보가 핵심입니다.

  • FE/BE/AI 각각의 특성에 맞게 분리된 배포 방식
  • Blue-Green 구조로 전환 리스크를 최소화
  • 배포 실패 시 즉시 롤백 가능
  • 수동 점검 및 트래픽 전환을 통제할 수 있는 구조
  • 캐시 무효화, 오리진 전환 등 클라우드 네이티브 배포 전략 활용

🔝 Top

왜 그렇게 아키텍처를 구축했나요?