Search

CINEBOX

Subject
영화 예매 서비스
Key Tech
Kubernetes
ArgoCD
Kustomize
Prometheus
Grafana
Loki
AWS
Description
환경 분리와 공통 운영 체계를 정리해 안정적인 배포∙관측 기반을 마련한 플랫폼 구축
Role: BE, Infra & DevOps Lead — 아키텍처 설계 | 인프라 구축 | CI/CD | 모니터링 Period: 2025.02 – 2025.03 Stack: AWS · Terraform · EKS · ArgoCD · Kustomize Prometheus · Grafana · Loki · CloudFront Link: [GitHub]

1. 프로젝트 소개

CINEBOX는 실시간 좌석 점유와 예매가 발생하는 영화 예매 서비스를 가정하고 구축한 프로젝트입니다.
이 프로젝트에서 집중한 것은 단순히 서비스를 Kubernetes 위에 배포하는 것이 아니라, 관측 가능한 운영 환경을 먼저 만들고, 그 데이터를 바탕으로 확장 구조를 결정하며, Dev와 Prod 환경을 선언적으로 분리해 운영 일관성을 확보하는 것이었습니다.
서비스가 커질수록 운영 리스크는 코드 자체보다도 환경 차이, 수동 배포, 추적 불가능한 변경, 클러스터 내부 런타임 문제에서 더 자주 발생한다고 보았습니다. 그래서 CINEBOX에서는 공통 운영 기반을 먼저 정리하고, 변경을 Git 기반으로 추적하며, 장애가 발생했을 때 빠르게 원인을 좁힐 수 있는 구조를 만드는 데 초점을 맞췄습니다.
[이미지 1] CINEBOX 아키텍처

2. 플랫폼 관점의 접근

영화 예매 서비스는 읽기 요청과 실시간 상태 변경이 함께 존재하는 구조입니다. 특히 어떤 도메인에 트래픽이 몰리는지, 운영 중 어떤 병목이 먼저 드러나는지 파악하지 못하면 인프라 확장이나 데이터 구조 변경이 감에 의존하게 됩니다. 그래서 CINEBOX에서는 먼저 애플리케이션과 인프라 상태를 함께 볼 수 있는 관측 체계를 구성하고, 그 데이터를 기준으로 구조를 조정하는 방향을 택했습니다.
또한 Dev와 Prod 환경을 동시에 운영하면서 kubectl 중심의 수동 반영을 계속하면, 실제 클러스터 상태와 저장소의 상태가 어긋나고, Dev에서 검증한 설정이 Prod에 동일하게 반영된다는 보장도 사라집니다. 배포 이력까지 남지 않으면 문제 발생 시 원인 추적이 더 어려워집니다. 이 때문에 CINEBOX에서는 배포 자체보다도 환경 분리와 선언적 재현성을 먼저 운영 과제로 보았습니다.

3. 플랫폼 기능 구현

3-1. Observability Platform

모니터링으로 설계의 타당성을 검증하고, 운영 이상 징후를 식별했습니다.
CINEBOX에서는 Prometheus와 Grafana로 인프라 리소스와 애플리케이션 상태를 함께 모니터링하고, Loki로 각 파드에 흩어진 로그를 중앙 수집해 Grafana에서 함께 확인할 수 있도록 구성했습니다.
인프라∙애플리케이션 메트릭
Prometheus → Grafana
파드 로그
Promtail → Loki → Grafana
 수집 지표
CPU∙Memory∙Node Disk I/O 등 시스템 메트릭
HTTP 응답 시간 및 상태값
Method별 요청 빈도, 로그 레벨, 도메인별 요청 패턴
[이미지 2] Node Metrics
[이미지 3] Application Metrics
[이미지 4] Application Logs
웹 서비스 특성상 조회 요청이 예매∙결제 같은 쓰기 요청보다 훨씬 많을 것으로 예측하고, Read Replica를 분리해 조회 트래픽을 Replica에서 처리하도록 설계했습니다. 이후 모니터링을 통해 movie 도메인의 GET 요청에 트래픽이 집중되는 패턴을 확인할 수 있었습니다.

3-2. Delivery Platform — GitOps 기반 배포 재현성 확보

‘배포했다’에서 마치는 것이 아닌, 환경 충돌을 구조적으로 차단하고 변경을 추적 가능하게 만들었습니다.
운영 환경의 안정성은 “배포를 했다”보다 “어떻게 배포했는가”에서 결정된다고 보았습니다. CINEBOX에서는 Dev와 Prod를 동시에 운영하며 수동 배포가 drift를 만들고, 환경별 차이를 사람의 기억에 의존하게 만드는 문제를 줄이기 위해 GitOps를 도입했습니다.
 Kustomize — 환경별 리소스 격리
k8s-manifests/ ├── base/ # 공통 리소스 정의 └── overlays/ ├── dev/ # Dev 환경별 설정 └── prod/ # Prod 환경별 설정
Plain Text
복사
Base에 공통 리소스를 정의하고, Overlay에서 환경별 설정만 덮어쓰는 구조를 통해 환경 간 설정 충돌을 구조적으로 차단했습니다.
 ArgoCD — 선언적 배포
[이미지 5] CI/CD 파이프라인
수동 변경은 PR 기반 흐름으로 제한해 drift가 발생할 수 있는 지점을 줄였습니다. CI와 CD 역시 GitHub Actions에서 빌드∙검증을 수행하고, ArgoCD가 배포와 수렴을 담당하는 구조로 역할을 분리했습니다.
그 결과 환경별 설정 충돌을 줄이고, 변경 이력을 Git 기준으로 추적할 수 있으며, 동일한 운영 상태를 반복 가능하게 만드는 전달 플랫폼을 구축할 수 있었습니다.

3-3. Runtime Reliability — 클러스터 기능 안정성 확보

플랫폼은 배포가 잘 되는 것뿐만 아니라 클러스터 내부 기능이 정상 동작해야 애플리케이션이 안정적으로 운영됩니다. CINEBOX에서는 CoreDNS에 대한 트러블슈팅을 통해 이 점을 경험했습니다.
 상황
애플리케이션 Pod가 RDS와 연결되지 못하고 CrashLoopBackOff를 반복했습니다.
 원인 추적
Step 1. RDS 설정, Security Group, 환경변수 확인 → 모두 정상 Step 2. endpoint 기반 연결 실패라는 점에 주목 → DNS 해석 문제 의심 Step 3. CoreDNS Pod 상태 확인 → Pending 발견 Step 4. 모든 노드에 Taint 적용 확인 → CoreDNS에 Toleration 없어 스케줄링 불가가 근본 원인으로 판별
 해결
CoreDNS Deployment에 tolerations를 추가해 모든 노드에서 스케줄링 가능하도록 변경했습니다. 이로 인해 DNS 해석이 복구되며 애플리케이션과 RDS 간 연결도 정상화되었습니다.
이를 통해 애플리케이션 장애처럼 보이는 현상도 클러스터 공통 서비스의 스케줄링 문제일 수 있으며, 공통 컴포넌트의 가용성 자체를 운영 설계의 일부로 봐야 한다는 점을 배울 수 있었습니다.

3-4. Infra Provisioning — 재현성과 비용 최적화

프로젝트 특성상 빈번한 Recreate/Destroy가 이뤄졌기 때문에 플랫폼이 동작하는 AWS 인프라를 Terraform으로 코드화해 재현성을 확보했습니다.
cinebox-terraform/ ├── vpc.tf # VPC, 서브넷, 라우팅 테이블, NAT ├── eks.tf # EKS 클러스터 및 노드 그룹 ├── rds.tf # RDS MySQL (Primary + Read Replica) ├── elasticache.tf # ElastiCache Redis ├── bastion.tf # Bastion EC2 ├── variables.tf ├── outputs.tf └── provider.tf
Plain Text
복사
또한 비용 제약을 가지고 있었기 때문에 비용 최적화를 위해 세 가지를 사용했습니다.
NAT Instance — NAT Gateway 대신 NAT Instance를 선택해 비용을 절감했습니다. 단일 장애점이 존재하는 trade-off가 있었지만 부트캠프 프로젝트 특성상 트래픽이 많지 않음을 감안하여 NAT Instance를 선택했습니다.
S3 Gateway Endpoint — Private Subnet에서 S3로의 트래픽을 Gateway Endpoint로 라우팅했습니다. NAT를 거치지 않기 때문에 외부 노출 경로 제거, 트래픽 비용 절감, 지연시간 감소 등의 효과를 얻을 수 있었습니다.
CloudFront + S3 — 이미지 조회가 빈번한 서비스 특성에 맞게 CloudFront로 S3 콘텐츠를 캐싱했습니다. 엣지 캐싱으로 이미지 조회 응답속도를 개선하고 S3 트래픽 비용을 절감했습니다.

4. 의사결정 및 Trade-off

서비스 특성 예측 기반 설계와 모니터링 검증

영화 예매 서비스의 트래픽 특성상 조회 요청이 예매·결제보다 많을 것으로 사전에 예측하고 Read Replica를 분리해 설계했습니다. 초기 설계에서 모든 것을 감으로 결정하기보다, 서비스 특성을 분석해 설계 방향을 세우고 모니터링으로 그 타당성을 확인하는 방식을 택했습니다. 실제 트래픽 패턴이 예측과 일치함을 확인하면서, 모니터링이 운영 중 문제를 발견하는 것 외에도 설계 결정의 근거를 검증하는 역할을 한다는 점을 체감했습니다.

GitOps를 통한 운영 기준 일원화

ArgoCD와 Kustomize를 도입한 것은 단순히 새로운 도구를 쓰기 위해서가 아니라, 운영 기준을 Git으로 일원화하기 위한 선택이었습니다. 수동 반영은 빠를 수 있지만 환경 간 일관성을 해치고, 변경을 재현하기 어렵게 만듭니다. 반면 GitOps는 PR과 저장소 상태를 중심으로 운영하게 해주므로, 관리 비용이 약간 늘어나는 대신 재현성과 추적 가능성을 확보할 수 있습니다.

클러스터 기본 컴포넌트도 플랫폼의 일부로 보는 관점

CoreDNS 이슈는 애플리케이션 장애처럼 보였지만, 실제로는 클러스터 공통 서비스의 스케줄링 문제였습니다. 이 경험을 통해 운영 플랫폼은 배포 도구나 모니터링 스택만이 아니라, DNS처럼 평소에는 드러나지 않는 기본 컴포넌트까지 포함해 설계해야 한다는 점을 배웠습니다.

5. 결과 및 성과

5. 결과

항목
변화
DB 읽기 부하
관측 기반 Read Replica 분리로 조회 트래픽 분산
환경 드리프트
kubectl 직접 적용 → GitOps 기반 선언적 관리로 제거
배포 재현성
Kustomize Dev/Prod 분리로 환경별 설정 충돌 방지
배포 이력
Git commit으로 자동 기록
운영 가시성
Prometheus∙Grafana∙Loki 통합 모니터링 체계 확보
RDS 연결 장애
CoreDNS 스케줄링 문제 규명 및 해소

6. 배운 점

이 프로젝트를 진행하며 반드시 거대한 플랫폼을 새로 만드는 것만이 엔지니어의 역할이 아니라는 점을 느꼈습니다. 때로는 운영 환경을 일관되게 유지할 수 있는 기준을 세우고, 데이터를 근거로 구조를 바꾸며, 보이지 않던 공통 컴포넌트 문제를 찾아내는 일이 더 중요한 플랫폼 작업이 될 수 있다고 생각하게 되었습니다.
CINEBOX에서는 특히 세 가지를 더 중요하게 보게 되었습니다.
첫째, 모니터링은 사후 문제 발견 도구이기도 하지만, 사전에 세운 설계 방향이 실제 운영에서 타당했는지 검증하는 수단이 될 수 있다는 점을 느꼈습니다. 서비스 특성을 예측해 DB 구조를 결정하고, 실제 트래픽 패턴으로 그 타당성을 확인한 것이 그 경험이었습니다.
둘째, 운영 환경은 Git 기준으로 관리될수록 재현성과 추적 가능성이 높아진다고 느꼈습니다. 다만 GitOps 도입 자체가 복잡도를 만들 수 있기 때문에, 팀의 운영 성숙도에 맞는 수준에서 적용하는 것이 중요하다고 생각합니다.
셋째, 애플리케이션 장애처럼 보이는 현상도 클러스터 공통 서비스의 문제일 수 있으므로, 플랫폼 기본 요소의 안정성을 우선적으로 점검하는 습관이 필요하다고 느꼈습니다.
CINEBOX는 이러한 관점을 엔지니어로서 어떤 기준으로 운영 구조를 바라봐야 하는지 구체화하는 계기가 된 프로젝트였습니다.