실시간 업데이트에는 SignalR이 필요하지 않습니다 | .NET/C#의 서버 전송 이벤트 | 데니스 마카렌코


요약

.NET/C#에서 SignalR 없이 Server-Sent Events(SSE)를 사용하여 실시간 업데이트를 구현하는 방법을 설명한 기술 가이드입니다.

배경 및 문제점

애플리케이션에서 알림과 같은 대화형 부분을 별도로 업데이트해야 하는 경우가 있습니다. 일반적으로 SignalR을 떠올리지만, SignalR은 작은 데이터 전송을 위해 전체 소켓 연결을 유지하며 양방향 통신을 지원하므로 서버에서 클라이언트로만 데이터를 전송하는 경우에는 과도합니다.

AJAX 폴링의 단점들:

  • 클라이언트 코드베이스 접근 제한
  • JavaScript 코드 작성 필요
  • 이벤트 발생과 클라이언트 폴링 간의 지연 시간

Server-Sent Events 솔루션 SSE는 최소한의 클라이언트 측 코드로 이벤트 발생과 수신 간 지연 없이 서버에서 클라이언트로 이벤트를 전송할 수 있는 방법입니다.

구현 과정

1. 알림 이벤트 정의

internal sealed record NotificationEvent(Guid Id, string Message);

2. 기본 엔드포인트 생성 RandomDataGenerator.Net NuGet 패키지를 추가하여 랜덤 데이터 생성기를 등록하고 DI 컨테이너에 구성합니다.

3. 엔드포인트 업데이트

  • CancellationToken을 통해 클라이언트가 언제든지 알림을 취소할 수 있도록 구현
  • 등록된 랜덤화기를 사용하여 랜덤 문자열 생성
  • 비동기 열거 가능한 로컬 함수로 랜덤 알림 반환

4. 최종 서버 측 구현

app.MapGet("/notifications", (
    [FromServices] IRandomizerString randomizer,
    CancellationToken token) =>
{
    return TypedResults.ServerSentEvents(GetNotificationsAsync(randomizer, token), "notification");
    
    async IAsyncEnumerable<NotificationEvent> GetNotificationsAsync(
        IRandomizerString randomizerString,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(4000, cancellationToken);
            yield return new NotificationEvent(
                Guid.CreateVersion7(),
                randomizerString.Generate()!);
        }
    }
});

5. 클라이언트 측 구현 매우 간단한 JavaScript 코드로 구현 가능합니다:

const eventSource = new EventSource('https://localhost:7197/notifications');

eventSource.onmessage = (event) => {
      console.log('Event received:', event);
      // 이벤트 처리 로직
};

작동 원리 브라우저가 서버와 HTTP 영구 연결을 생성하고, 서버는 Content-Type: text/event-stream 헤더로 응답합니다. 이는 단방향 통신으로 서버에서 클라이언트로만 데이터를 전송할 수 있습니다.

장점

  • SignalR보다 가벼운 구현
  • 최소한의 코드로 실시간 업데이트 가능
  • 서버에서 클라이언트로의 단방향 통신에 최적화
  • 이벤트 발생과 수신 간 지연 시간 없음

이 방법은 SignalR의 복잡성 없이 클라이언트를 업데이트하는 매우 우아한 방식으로, 단순한 실시간 알림 시스템에 적합한 솔루션입니다.