실시간 웹 애플리케이션을 개발하는 .NET 개발자에게 SignalR은 매우 친숙한 라이브러리입니다.
하지만 서비스 규모가 커지면서 WebSocket 연결 유지, 상시 가동 인프라 운영, Redis 백플레인 확장 등 운영상의 어려움에 직면하는 경우가 많습니다.
이러한 운영 비용은 사용자가 늘어날수록 기하급수적으로 증가하며, 정작 중요한 기능 개발에 투입되어야 할 엔지니어링 리소스를 잠식합니다.
이 글에서는 기존 SignalR Hub 기반 아키텍처를 AWS의 완전 관리형 서버리스 WebSocket 솔루션인 AWS AppSync Event API로 현대화하는 방법을 심층적으로 분석합니다.
아키텍처의 근본적인 차이점부터 실제 .NET 및 React 코드 예시, 그리고 어떤 상황에서 이러한 전환이 합리적인지에 대한 구체적인 가이드라인을 제시합니다.
SignalR의 숙명적 과제: 확장성의 한계
SignalR은 .NET 개발자에게 실시간 웹 기능을 손쉽게 구현할 수 있도록 돕는 훌륭한 도구입니다.
WebSocket, Server-Sent Events, Long Polling 등 복잡한 기술을 단일 API로 추상화하고, RPC(원격 프로시저 호출) 스타일의 통신을 위한 Hub 패턴을 제공하는 등 강력한 장점을 가지고 있습니다.
하지만 시스템이 성장함에 따라 아키텍처의 한계가 명확해집니다.
- Redis 백플레인 의존성: 여러 서버로 확장하기 위해서는 모든 서버가 메시지를 공유할 수 있도록 Redis와 같은 외부 메시지 브로커(백플레인)를 사용한 발행-구독(Pub/Sub) 패턴이 필수적입니다. 이는 아키텍처 복잡성을 높이고 잠재적인 장애 지점을 추가합니다.
- 상시 가동 인프라 비용: SignalR 서버는 클라이언트 연결을 지속적으로 유지해야 하므로 24시간 내내 가동되어야 합니다. 이는 트래픽이 적은 시간에도 고정적인 인프라 비용을 발생시킵니다.
- 서버 측 연결 상태 관리: 모든 클라이언트의 연결 상태를 서버가 직접 관리하기 때문에, 클라이언트와 특정 서버 인스턴스 간에 강한 결합이 발생합니다. 이로 인해 유연한 확장이 어렵고 장애 발생 시 연결이 끊어질 위험이 있습니다.
결국, 스케일링을 위한 모든 결정은 신중한 용량 계획과 인프라 관리를 요구하며, 이는 개발팀에 상당한 운영 부담으로 작용합니다.
패러다임의 전환: 연결 중심에서 이벤트 기반으로
SignalR에서 AppSync로의 전환은 단순히 기술 스택을 바꾸는 것을 넘어, 아키텍처 패러다임 자체를 ‘연결 중심(Connection-Centric)’에서 ‘이벤트 기반(Event-Driven)’으로 전환하는 것을 의미합니다.
이것이 가장 핵심적인 차이점입니다.
SignalR은 서버가 모든 클라이언트와의 영구적인 연결을 추적하고, 이 연결을 통해 직접 데이터를 푸시하는 방식입니다.
반면, AppSync는 서버가 특정 채널(Channel)에 이벤트를 발행(Publish)하기만 하면, AppSync 서비스가 해당 채널을 구독(Subscribe)하는 모든 클라이언트에게 이벤트를 전달하는 책임을 집니다.
서버는 더 이상 개별 클라이언트의 연결 상태를 알 필요가 없습니다.
이러한 구조적 차이 덕분에 Redis 백플레인이 완전히 불필요해집니다. 애플리케이션 서버는 AppSync를 향해 단일 HTTP POST 요청만 보내면 됩니다.
그 후 AppSync Event API가 구독 중인 클라이언트가 10명이든 10,000명이든 상관없이 모든 클라이언트에게 WebSocket을 통해 이벤트를 효율적으로 전파(Fan-out)합니다.
AWS AppSync 아키텍처 분석: 무엇이 다른가
AppSync를 활용한 실시간 주문 업데이트 아키텍처는 SignalR이 상시 가동 인프라로 관리하던 작업을 단 3개의 AWS 서비스로 대체합니다.
데이터 흐름은 다음과 같습니다.
- 고객 주문 발생: 고객이 React 프론트엔드에서 주문을 생성합니다.
- .NET API의 자격 증명 검색: 주문 API는 런타임에 AWS Secrets Manager에서 AppSync 엔드포인트와 API 키를 안전하게 검색합니다.
- AppSync로 이벤트 발행: 주문 API는 특정 도메인 채널(예:
/default/orders)로 주문 이벤트를 담아 HTTP POST 요청을 보냅니다. - 실시간 전파: AppSync Event API가 해당 채널을 구독하고 있는 모든 클라이언트(재고 관리, 배송 추적 등)에게 WebSocket을 통해 실시간으로 이벤트를 푸시합니다.
이 아키텍처는 다음과 같은 핵심 설계 원칙을 따릅니다.
- 분리된 발행자와 구독자: API 서버는 단 한 번 이벤트를 발행할 뿐, 구독자에게 이벤트를 분배하는 로직은 모두 AppSync가 담당하여 완벽하게 분리됩니다.
- 서버 측 WebSocket 관리 부재: API 서버는 단순한 HTTP POST 요청만 처리하며, WebSocket 연결의 복잡성은 AppSync에 의해 완벽히 추상화됩니다.
- 안전한 자격 증명 처리: 민감한 API 키와 엔드포인트 URL은 코드에 하드코딩하지 않고, 런타임에 Secrets Manager를 통해 안전하게 주입받습니다.
다음 표는 SignalR과 AppSync Event API의 주요 차이점을 요약한 것입니다.
| 기능 | SignalR | AppSync Event API |
|---|---|---|
| 인프라 | 직접 관리하는 서버 | 서버리스 (AWS 관리) |
| 확장성 | 수동 + Redis 백플레인 필요 | 수백만 연결까지 자동 확장 |
| WebSocket 관리 | 서버 측에서 직접 연결 추적 | AppSync가 완전 관리 |
| 비용 모델 | 상시 가동 인프라 비용 | 사용한 만큼만 지불 (Pay-per-use) |
| 지연 시간 | Redis 구성 및 배포에 따라 다름 | AWS 글로벌 인프라 기반의 낮은 지연 시간 |
| 다중 AZ | 복잡한 수동 설정 필요 | 다중 가용 영역에 걸친 이중화 기본 내장 |
실제 코드 비교: SignalR을 AppSync로 교체하기
실제 코드를 통해 마이그레이션이 어떻게 이루어지는지 살펴보겠습니다.
백엔드: .NET 이벤트 발행
기존 SignalR Hub의 `IHubContext.Clients.All.SendAsync(\”ReceiveMessage\