O+T OTT 플랫폼 인프라 아키텍처 정리
이번 글에서는 O+T OTT 플랫폼의 인프라 아키텍처를 정리해보려고 한다.
단순히 서버를 여러 대 두는 수준이 아니라, 사용자 요청 처리, 관리자 기능, AI 기능, 영상 업로드 후 트랜스코딩, 모니터링, 정적 파일 배포까지 각각의 역할을 나누어 구성한 구조다. 전체적으로는 AWS 기반으로 설계했으며, 확장성과 운영 편의성, 그리고 서비스 분리를 함께 고려했다.

1. 전체 아키텍처 개요
전체 구조는 AWS Cloud 내부의 VPC를 기준으로 구성되어 있다.
외부 사용자는 Route 53을 통해 서비스에 접근하고, 요청은 ALB를 거쳐 내부 서버로 전달된다. 영상 파일이나 정적 리소스는 S3에 저장되며, 조회 시에는 CloudFront를 통해 캐싱된 콘텐츠가 전달된다. 또한 관리자 기능, 사용자 기능, AI 기능, 트랜스코딩 처리, 모니터링 기능을 각각 역할별로 분리해 배치했다.
이 구조의 핵심은 다음과 같다.
- 요청 처리 서버를 역할별로 분리
- 업로드 이후 비동기 처리 구조 도입
- 트랜스코딩 작업량에 따라 ECS 확장
- S3 + CloudFront로 파일 저장 및 배포 최적화
- Grafana, Loki, Prometheus 기반 모니터링 환경 구성
2. 서버 역할 분리
아키텍처에서 사용한 주요 EC2 및 서비스 역할은 다음과 같다. 문서에는 Admin, AI-Server, User, RabbitMQ, 그리고 모니터링 서버 구성이 별도로 정리되어 있다.

Admin 서버
관리자용 백오피스 서버다.
영상 업로드, 검색, 수정 같은 관리 기능을 담당하며, 간단한 모니터링 기능도 함께 제공한다. 즉, 콘텐츠 운영자가 실제로 사용하는 관리 시스템의 진입점이라고 보면 된다.
User 서버
일반 사용자 요청을 처리하는 서버다.
OTT 플랫폼에서 사용자가 콘텐츠를 조회하거나 필요한 기능을 요청할 때 이 서버가 응답을 담당한다.
AI-Server
AI 관련 기능을 처리하는 서버다.
문서에서는 자세한 기능 설명은 추후 기술한다고 되어 있지만, AI 기능을 별도 서버로 분리했다는 점에서 향후 독립적인 확장이나 모델 서비스 운영을 고려한 구조라고 볼 수 있다.
RabbitMQ
영상 업로드 이후 처리 흐름을 비동기로 연결하기 위한 메시지 큐다.
트랜스코딩처럼 오래 걸리는 작업은 요청-응답 구조로 즉시 처리하기 어렵기 때문에, 메시지 큐를 두어 느슨한 결합을 만들고 작업 실패나 재처리에도 대응하기 쉽게 구성했다.
모니터링 서버
Grafana, Loki, Prometheus를 사용해 시스템 상태를 수집하고 시각화한다.
Prometheus가 메트릭을 수집하고, Loki가 로그를 수집하며, Grafana가 이를 한눈에 볼 수 있게 시각화하는 구조다. 운영 관점에서 장애 대응과 상태 파악을 위해 꼭 필요한 영역이다.

3. 네트워크 구성: Public Subnet의 역할
문서에서는 Public Subnet 안에 NAT Gateway와 ALB를 배치한 이유를 따로 설명하고 있다. 이 부분은 단순한 네트워크 구성이 아니라, 보안과 운영 전략을 함께 반영한 설계다.
외부에서 내부로 들어오는 트래픽: ALB
외부 요청은 ALB를 통해 내부 서버로 라우팅된다.
이때 ALB가 사용자 서버와 관리자 서버로 요청을 분기하는 역할을 맡는다. 즉, 클라이언트는 하나의 진입점으로 접근하지만, 실제 내부에서는 목적에 맞게 트래픽이 나뉜다.
내부에서 외부로 나가는 트래픽: NAT Gateway
Private Subnet 내부 서버가 외부 자원에 접근해야 할 경우 NAT Gateway를 사용한다.
이렇게 하면 내부 서버를 직접 외부에 노출하지 않으면서도 필요한 아웃바운드 요청은 가능하게 만들 수 있다.
이렇게 분리한 이유
Ingress와 Egress를 분리하면 보안상 이점이 있다.
특히 문서에서는 ALB가 HTTP/HTTPS 요청만 받기 때문에, 그 외 임의의 접근이 Private Subnet 내부 서버까지 직접 닿기 어렵다는 점을 장점으로 설명하고 있다. 즉, 외부 노출 범위를 줄이고 필요한 통로만 열어두는 구조다.
또한 ALB를 사용한 이유로는 다음 두 가지가 제시되어 있다.
- 하나의 도메인 체계에서 서브도메인 등을 활용해 user와 admin 요청을 분리하기 위함
- 추후 장애 복구 시나리오나 무중단 배포를 고려하기 위함
이 부분은 실제 서비스 운영을 염두에 둔 설계라는 점에서 의미가 크다.

4. 영상 업로드와 트랜스코딩 처리 흐름
이 문서에서 가장 흥미로운 부분은 영상 업로드 이후 처리 방식이다.
업로드는 단순히 파일만 받는 것이 아니라, 이후 트랜스코딩 작업과 서버 확장까지 연결되는 파이프라인 형태로 구성되어 있다. 관련 다이어그램도 함께 포함되어 있다.
전체 흐름은 다음과 같다.
1) Admin 서버에서 업로드 요청 수신
관리자가 영상을 업로드하면 요청은 Admin 서버로 들어온다.
이때 Admin 서버는 DB에 필요한 정보를 저장하고, RabbitMQ에 메시지를 발행한다.
2) RabbitMQ가 작업 대기열 관리
RabbitMQ는 트랜스코딩 전 작업들을 관리한다.
즉, 업로드된 영상이 바로 처리되는 것이 아니라 큐에 적재되고, 이후 처리 시스템이 순차적이거나 병렬적으로 가져가게 된다.
3) ECS가 트랜스코딩 처리
트랜스코딩은 ECS에서 수행된다.
문서 설명에 따르면 트랜스코딩 작업은 시간이 오래 걸릴 수 있기 때문에, 짧은 작업까지 함께 지연되지 않도록 서버 확장이 가능해야 한다. 그래서 ECS 기반으로 작업 처리량에 따라 유연하게 대응하는 구조를 택했다.
4) EventBridge와 Lambda를 활용한 ECS 스케일링 제어
트랜스코딩 작업은 요청량의 편차가 큰 편이다.
업로드가 몰리는 순간에는 처리 대기열이 빠르게 쌓이고, 반대로 한가한 시간에는 인프라가 거의 놀게 된다. 그래서 이 구간은 고정된 수의 ECS 인스턴스로 운영하기보다, 현재 작업량에 맞춰 유동적으로 확장·축소되는 구조가 더 적절하다고 판단했다.
처음에는 CloudWatch 기반으로 스케일링하는 방안도 고민했다.
특정 이벤트나 메트릭을 기준으로 ECS 수를 조정하면 AWS가 제공하는 관리형 기능을 활용할 수 있고, 구조도 비교적 깔끔해 보였기 때문이다. 하지만 실제 설계 과정에서 한 가지 문제가 있었다. 트랜스코딩이 실패해 메시지가 RabbitMQ에 다시 적재되는 경우, 그 상태를 서비스 입장에서 신뢰성 있게 파악하기 어렵다는 점이었다.
즉, 겉으로 보이는 처리 이벤트만으로는 현재 작업량을 정확히 판단하기 어려웠다.
어떤 작업은 정상적으로 끝났지만, 어떤 작업은 실패 후 다시 큐에 들어가 재처리를 기다릴 수 있다. 이 경우 서비스 외부에서 보이는 신호만으로는 “지금 실제로 얼마나 많은 작업이 밀려 있는지”를 정확히 알기 어렵다. 결국 스케일링 기준으로 더 중요한 것은 애플리케이션 레벨의 이벤트보다, 실제 작업이 쌓여 있는 RabbitMQ의 큐 상태 자체라고 봤다.
그래서 현재는 조금 더 직접적인 방식을 선택했다.
EventBridge가 1분마다 Lambda를 실행하고, Lambda가 RabbitMQ의 메시지 수를 확인한 뒤 그 결과에 따라 ECS 인스턴스 수를 조정하는 구조다. 큐에 메시지가 많이 쌓여 있으면 ECS 처리량을 늘리고, 반대로 큐가 비어 있거나 적으면 인스턴스 수를 줄이는 방식이다.
이 방식의 장점은 기준이 명확하다는 점이다.
단순히 “이벤트가 발생했는가”가 아니라, **“지금 처리해야 할 작업이 실제로 얼마나 남아 있는가”**를 보고 판단할 수 있다. 특히 트랜스코딩 실패 후 메시지가 다시 큐에 적재되는 상황까지 반영할 수 있어서, 운영 관점에서는 오히려 더 현실적인 스케일링 방식이라고 느꼈다.
물론 현재 방식이 완벽한 해법이라고 생각하는 것은 아니다.
주기적으로 RabbitMQ를 확인하는 방식은 구현이 단순하고 이해하기 쉽다는 장점이 있지만, 결국 폴링 기반이기 때문에 반응 속도에 한계가 있고, 주기 설정에 따라 불필요한 호출이 생길 수도 있다. 그래서 지금도 더 나은 방향을 고민하고 있다. 예를 들어 RabbitMQ 상태를 좀 더 정교하게 메트릭화하거나, 실패·재시도 상황까지 자연스럽게 반영할 수 있는 오토스케일링 구조로 발전시킬 여지가 있다.
정리하면, 이 구조는 “AWS에서 제공하는 기본 스케일링 기능을 그대로 사용한 사례”라기보다, 실제 운영 흐름을 기준으로 더 신뢰할 수 있는 지표가 무엇인지 고민한 결과에 가깝다. 현재는 RabbitMQ 큐 상태를 직접 확인하는 방식이 가장 현실적이라고 판단해 그렇게 구성했고, 앞으로는 이 부분을 더 개선해 나갈 계획이다.

5. 저장과 배포: S3 + CloudFront
트랜스코딩된 영상과 원본 영상은 S3에 저장된다.
이후 사용자가 영상을 조회할 때는 CloudFront를 통해 캐싱된 콘텐츠를 제공한다. 문서 마지막 다이어그램에서도, 관리자가 업로드한 원본 영상과 ECS가 처리한 결과 영상을 S3에 저장하고, 조회 시 CloudFront를 통해 서비스하는 구간을 설명하고 있다.
이 방식의 장점은 명확하다.
- 영상 파일을 서버 디스크가 아니라 객체 스토리지에 안정적으로 저장 가능
- 반복 조회되는 콘텐츠를 CDN으로 캐싱해 응답 속도 개선
- 애플리케이션 서버와 정적 콘텐츠 제공 역할을 분리 가능
OTT 같은 서비스에서는 영상 파일 자체가 크고 전송량도 많기 때문에, S3와 CloudFront 조합은 거의 필수에 가깝다.
6. 이 아키텍처의 장점
정리하면 이 구조는 다음과 같은 장점이 있다.
역할 분리
Admin, User, AI-Server를 분리함으로써 서비스 책임이 명확하다.
기능별로 확장 전략도 अलग르게 가져갈 수 있다.
비동기 처리
업로드 직후 무거운 작업을 바로 수행하지 않고 RabbitMQ를 통해 비동기로 넘기기 때문에 사용자 경험이 더 안정적이다.
유연한 확장
트랜스코딩 수요에 따라 ECS 인스턴스를 조절할 수 있어, 리소스를 효율적으로 사용할 수 있다.
안전한 네트워크 구조
외부 진입은 ALB로 제한하고, 내부 서버의 외부 접근은 NAT Gateway로 처리해 보안상 이점을 확보했다.
운영 가시성 확보
Grafana, Loki, Prometheus를 통해 로그와 메트릭을 수집하고 시각화해 운영 상태를 빠르게 파악할 수 있다.
마무리
이번 O+T OTT 플랫폼 인프라 아키텍처는 단순히 “서버를 띄워놓은 구조”가 아니라,
서비스 역할 분리, 비동기 작업 처리, 자동 확장, 정적 자원 배포 최적화, 모니터링 체계까지 고려한 구조라는 점에서 의미가 있다.
특히 영상 업로드 이후의 트랜스코딩 파이프라인을 RabbitMQ, ECS, EventBridge, Lambda로 연결한 부분은 운영성과 확장성을 함께 고려한 설계로 볼 수 있다. 앞으로 이 구조를 Terraform 같은 IaC 도구와 연결해 관리한다면, 인프라 재현성과 유지보수성도 훨씬 좋아질 것 같다.