전체적인 시나리오
다형님이 작성해주신 전체적인 시나리오
- 클라이언트 → ALB 접속
- 사용자는 인터넷을 통해 인터넷 게이트웨이(IGW) → ALB (퍼블릭 서브넷) 에 접속
- ALB → EC2 인스턴스로 라우팅
- ALB는 여러 AZ에 분산된 EC2 중 healthy한 인스턴스로 연결
- WebSocket 및 HTTP 요청 처리
- EC2 ↔ Redis Pub/Sub
- 메시지를 보낸 클라이언트와 받는 클라이언트가 서로 다른 AZ/인스턴스에 연결되어 있어도
- 중앙 Redis를 통해 메시지가 중계되어 실시간 전달
- EC2 → DynamoDB (VPC Endpoint)
- 메시지 전송과 동시에 채팅 내역을 DynamoDB에 저장
- VPC 엔드포인트를 통해 NAT 없이 안전하게 접근
- DynamoDB TTL 설정
- 메시지 저장 시 expireAt 필드에 6개월 후 timestamp를 기록
- DynamoDB가 TTL 도래 시 해당 메시지를 자동으로 삭제
- 서비스 중 에러가 발생한 경우
- 모든 EC2 인스턴스의 로그는 CloudWatch Logs로 수집
- 콘솔에서 검색 및 조회 가능하며, 알람 설정 시 자동 감지 및 알림 전송 가능
Trouble Shooting
EC2에 Websocket을 띄우느냐 vs Websocket API Gateway + Lambda를 사용하느냐
- EC2 서버에 websocket 구축
- 트래픽/접속량을 직접 관리해야하는데, 접속자 수가 많아지면 loadbalancer + auto scaling + redis pub/sub 추가 구성 필요
- 서버 관리 필요 →유지보수 비용 높음
2. API Gateway Websocket + lambda
- serverless
- 자동확장
- 브로드캐스트 비효율
- lambda는 휘발성 환경, 짧은 실행시간에 최적화 (지속 연결 유지 적합하지 X)
- Redis subscriber 역할을 lambda가 수행하면, lambda는 redis와 지속 연결을 유지해야함 (lambda의 특성과 맞지 않음)
- 병렬 fan-out 관리 복잡성 (구독자 100명이면 connectionID를 조회하고 각각보내고.. 복잡)
결론: 정확한 시나리오 (접속자 수, 채팅방에 몇명, ...) 를 정해서 아키텍처 성능을 비교 하는게 맞다고 판단
따라서...
전체 인프라 비용이 40$~60$ 를 고려하여
- 동시접속자: 500명
- 채팅방 인원: 최대 100명
- 총 가입자 수: 1000명
- 하루 채팅 메시지 수: 5000건 이상
일때 어떤 것이 비용 효율적이고 성능적으로 더 나은가를 비교하였다.
ex) 팬 100명이 접속한 채팅방에 방장이 메시지를 보낼 경우
- EC2 WebSocket:
- 연결된 100개의 WebSocket에 for 루프 혹은 Redis Pub/Sub로 한 번에 브로드캐스트
- API Gateway WebSocket:
- 각 클라이언트에 Lambda를 100번 실행해 callback URL로 보내야 함
- → 비용 증가, 딜레이 발생, 동시 실행 제한에 걸릴 수도 있음
우리는 아티스트가 채팅을 보내면 개인의 익명의 사용자에게 채팅 내역을 보내고 익명의 사용자가 채팅을 치면 아티스트는 여러 사용자에게 오는 메세지를 볼 수 있어야하기 때문에 lambda (1:1 채팅에 효율)를 호출하는 것이 매우 비효율적이라고 생각하여
결론적으로 우리의 시나리오 (1: N 구조의 채팅) 대로라면 EC2 + websocket 이 맞다고 생각하여 최종 아키텍처를 완성하였다.