SSE와 Mercure를 활용한 SPA의 비동기 데이터 업데이트
프론트엔드 애플리케이션은 백엔드 변경 사항을 반영하기 위해 지속적인 데이터 업데이트가 필요합니다. 표준 API 호출은 응답 시점의 상태를 캡처하지만, 백엔드는 계속해서 이벤트를 처리합니다: 계좌 충전, 콘텐츠 검토, 고객 지원 답변 등. 이를 해결하기 위해 SSE 기반의 푸시 메커니즘이 사용되며, 기존 OpenAPI 명세와 통합됩니다.
이 시스템은 풀 방식(주기적 요청)과 푸시 방식(실시간 알림)을 결합합니다. SSE는 HTTP/2를 통한 단방향 이벤트 스트림을 제공하여 폴링에 비해 부하를 최소화합니다.
비동기 알림의 활용 사례
비동기 알림은 비즈니스 프로세스에서 매우 중요합니다:
- 잔액 충전: 즉시 구매를 위한 현재 상태 표시.
- 콘텐츠 검토: 검토 후 상태 업데이트.
- 고객 지원 답변: 새 티켓에 대한 즉각적인 알림.
일반적인 경우, 사용자(광고주 또는 계약자)는 요청 카운터를 추적합니다: 조치가 필요한 수, 읽지 않은 댓글 수, 배치 확인 수. 이 데이터는 API 엔드포인트 /rest/User/info(operationId: getInfo)를 통해 확인할 수 있습니다.
/rest/User/info:
get:
tags:
- User
summary: 현재 사용자 정보 반환
operationId: getInfo
responses:
200:
description: 현재 사용자 정보
content:
application/json:
schema:
type: object
properties:
id:
type: integer
format: int32
minimum: 0
locale:
type: string
enum: [ru, en]
login:
type: string
minimum: 3
maximum: 320
seoCounters:
$ref: '#/components/schemas/SeoCounters'
SeoCounters 스키마는 다음과 같은 구조를 정의합니다:
SeoCounters:
type: object
properties:
nofRequests:
type: integer
format: int32
minimum: 0
nofLinksStatusNeedApprove:
type: integer
format: int32
minimum: 0
nofLinksWithUnreadComments:
type: integer
format: int32
minimum: 0
nofChanges:
type: integer
format: int32
minimum: 0
nofPlacementCheck:
type: integer
format: int32
minimum: 0
CDC와 데이터 플랫폼 통합
user_counters 테이블의 변경 사항은 CDC(Change Data Capture)를 통해 추적됩니다. 수정 스트림은 데이터 플랫폼(기업용 ETL 시스템)으로 전송됩니다. 거기서 이벤트는 SSE 허브를 통해 UI로 푸시됩니다.
아키텍처는 헥사고날 모델을 사용합니다: OpenAPI 명세는 자동으로 REST 어댑터와 TypeScript 타입을 생성합니다. 프론트엔드의 경우 타입은 다음과 같습니다:
/* Generated by orval */
export interface SeoCounters {
nofRequests?: number;
nofLinksStatusNeedApprove?: number;
nofLinksWithUnreadComments?: number;
nofChanges?: number;
nofPlacementCheck?: number;
}
export type GetInfo200 = {
id: number;
locale: 'ru' | 'en';
login: string;
seoCounters?: SeoCounters;
};
이러한 타입은 SSE 이벤트 처리에 재사용되어 타입 안전성을 보장합니다.
애플리케이션에서 SSE 구현하기
SSE(Server-Sent Events)는 서버 푸시를 위한 표준으로, 브라우저에서 지원됩니다. EventSource는 엔드포인트에 연결됩니다:
const evtSource = new EventSource('/sse-endpoint', {
withCredentials: true,
});
evtSource.onmessage = (event) => {
const data = JSON.parse(event.data);
// 타입이 지정된 데이터로 스토어 업데이트
updateSeoCounters(data.seoCounters);
};
인증, 토픽, 확장성을 위해 Mercure가 사용됩니다—SSE 기반의 오픈소스 허브입니다. 이 허브는 JWT와 함께 REST를 통해 발행을 수락하고 구독자에게 브로드캐스트합니다.
발행 예시:
curl -d 'topic=https://example.com/books/1' \
-d 'data={"foo": "updated value"}' \
-H 'Authorization: Bearer <JWT>' \
-X POST https://hub/.well-known/mercure
JWT는 토픽에 대한 발행/구독 권한을 정의합니다. Mercure는 외부 데이터베이스와 함께 컨테이너로 배포되어 CDC 스트림과 통합됩니다.
이 접근법의 장점
- 스키마 재사용: OpenAPI 구조가 풀과 푸시에서 중복 없이 사용됩니다.
- 실시간: 변경 사항이 폴링 없이 즉시 반영됩니다.
- 확장성: Mercure 허브가 부하를 분산시킵니다.
모니터링을 위한 주요 카운터 목록:
nofRequests— 조치 요청.nofLinksStatusNeedApprove— 승인 대기 중인 링크.nofLinksWithUnreadComments— 읽지 않은 댓글.nofPlacementCheck— 배치 확인.
핵심 요약
- SSE와 Mercure는 WebSocket 오버헤드 없이 타입이 지정된 푸시 알림을 제공합니다.
- CDC는 ETL 프로세스를 위해 데이터베이스 변경 사항을 실시간으로 캡처합니다.
- OpenAPI에서 TypeScript 타입을 자동 생성하여 데이터 일관성을 보장합니다.
- 이 접근법은 수천 명의 사용자를 가진 고부하 시스템에 확장 가능합니다.
- Mercure의 JWT는 알림 토픽에 대한 접근을 관리합니다.
— Editorial Team
아직 댓글이 없습니다.