AI 앱을 위한 Appends: Ably AI Transport와 함께 단일 메시지로 스트리밍

발행: (2026년 2월 26일 오후 09:05 GMT+9)
10 분 소요
원문: Dev.to

Source: Dev.to

번역을 진행하려면 번역하고자 하는 본문 텍스트를 제공해 주시겠어요?
본문을 알려주시면 원본 형식과 마크다운을 그대로 유지하면서 한국어로 번역해 드리겠습니다.

Introduction

AI 앱용 Appends: Ably AI Transport로 단일 메시지에 스트리밍

Ably Blog

스트리밍 토큰은 쉽지만, 깔끔하게 재개하는 것은 쉽지 않습니다. 사용자가 응답 중간에 새로 고침을 하거나, 다른 클라이언트가 늦게 참여하거나, 모바일 연결이 10초 동안 끊기면, 갑자기 “하나의 답변”이 UI가 다시 합쳐야 하는 600개의 작은 메시지로 변합니다. 메시지 기록은 조각조각으로 나뉘게 됩니다. “지금까지의 응답”을 재구성하기 위해 별도의 저장소를 만들기 시작합니다.

이는 모델 문제가 아니라 전달 문제입니다.

그래서 우리는 Ably AI Transport(https://ably.com/ai-transport)를 위해 메시지 앱엔드를 개발했습니다. 앱엔드는 AI 출력 토큰을 생성되는 대로 단일 메시지에 스트리밍하도록 해 주어, 실시간 구독자에게는 점진적인 렌더링을 제공하고, 기록에는 깔끔하고 압축된 응답을 남깁니다.

우리가 수정하고 있는 실패 모드

일반적인 구현은 각 토큰을 별개의 메시지로 스트리밍합니다. 이는 안정적인 연결에서는 완벽하게 작동하지만, 실제 운영 환경에서는 클라이언트가 스트림 중간에 연결이 끊기고 재개됩니다: 새로 고침, 모바일 연결 끊김, 백그라운드 탭, 그리고 늦게 참여하는 경우 등.

실제 재연결 및 새로 고침이 발생하면, 계획하지 않았던 작업을 이어받게 됩니다:

  • 정렬
  • 중복 제거
  • 버퍼링
  • “최신 것이 승리” 로직
  • 히스토리와 실시간을 일치시키는 재생 규칙

구현은 가능하지만, 조용히 몇 주간의 엔지니어링 시간을 잡아먹습니다.

Diagram of token‑per‑message problem

앱엔드(append)를 사용하면 데이터 형태를 바꾸어 이를 피할 수 있습니다. 수백 개의 토큰 메시지 대신 하나의 응답 메시지가 시간이 지남에 따라 내용이 늘어납니다.

패턴: 한 번 만들고 여러 번 추가하기

Ably AI Transport에서는 초기 응답 메시지를 게시하고 서버가 할당한 시리얼을 캡처합니다. 그 시리얼에 추가합니다.

// Create the empty response message
const result = await channel.publish({ name: 'response', data: '' });
const { serials: [msgSerial] } = result;

이제 모델이 토큰을 생성할 때마다 같은 메시지에 각 조각을 추가합니다:

if (event.type === 'token') {
  channel.appendMessage({ serial: msgSerial, data: event.text });
}

클라이언트에 대한 변경 사항

구독자는 여전히 점진적인 출력을 보지만, 이를 동일한 메시지 시리얼에 대한 동작으로 인식합니다. 응답은 생성으로 시작하고, 토큰은 추가 형태로 도착하며, 때때로 클라이언트는 재동기화를 위해 전체 상태 업데이트를 받습니다(예: 재연결 후).

대부분의 UI는 이미 이 형태를 구현하고 있습니다; 추가 방식으로 인해 매우 예측 가능해집니다:

switch (message.action) {
  case 'message.append':
    renderAppend(message.serial, message.data);
    break;
  case 'message.update':
    renderReplace(message.serial, message.data);
    break;
}

중요한 차이점은 히스토리와 실시간이 더 이상 불일치하지 않게 된다는 것으로, 추가적인 클라이언트 코드를 필요로 하지 않습니다. 실시간 사용자에게는 점진적으로 렌더링하고, 저장, 검색 및 되감기를 위해 응답을 여전히 하나의 메시지로 취급합니다.

재연결 및 새로고침이 특수 사례가 아니다

짧은 연결 끊김은 하나의 경우입니다. 새로고침은 로컬 상태가 사라지기 때문에 고통스럽고, 각 토큰을 별도의 메시지로 스트리밍하면 조각을 다시 재생해야 하며 클라이언트가 동일한 응답을 재구성하기를 기대해야 합니다.

message‑per‑response 접근 방식을 사용하면 항상 현재 누적된 응답 메시지 버전이 존재하므로 하이드레이션이 간단합니다. 늦게 참여하거나 새로 고침하는 클라이언트는 최신 상태를 단일 메시지로 가져와 계속할 수 있습니다.

const channel = realtime.channels.get('ai:chat', {
  params: { rewind: '2m' }   // Rewind 2 minutes
});

이제 되감기와 히스토리가 다시 유용해집니다. 토큰 조각이 아니라 의미 있는 메시지를 되감기하기 때문입니다.

토큰 레이트 고통 없이 토큰 레이트

Models can emit tokens far faster than most realtime setups want to publish. Publishing a message per token leads to rate‑limit problems and forces you to batch in your code.

모델은 대부분의 실시간 설정이 발행하고자 하는 것보다 훨씬 빠르게 토큰을 생성할 수 있습니다. 토큰당 메시지를 발행하면 속도 제한 문제가 발생하고 코드에서 배치를 강제하게 됩니다.

Appends are designed for high‑frequency workloads and include automatic roll‑ups. Subscribers still receive progressive updates, but Ably can roll up rapid appends under the hood so you don’t have to build your own throttling layer.

Append는 고주파 작업 부하를 위해 설계되었으며 자동 롤업을 포함합니다. 구독자는 여전히 점진적인 업데이트를 받지만, Ably가 내부적으로 빠른 Append를 롤업해 주므로 직접 스로틀링 레이어를 구축할 필요가 없습니다.

If you need to tune the trade‑off between smoothness and message rate, adjust appendRollupWindow:

부드러움과 메시지 레이트 사이의 트레이드오프를 조정해야 한다면 appendRollupWindow를 조정하세요:

  • 작은 윈도우 → 더 반응성이 좋지만 메시지 레이트 사용량이 증가합니다.
  • 큰 윈도우 → 더 적극적인 배치, 메시지 수 감소.

Enabling appends

Appends require the “Message annotations, updates, appends, and deletes” channel rule for the namespace you’re using. Enabling it also means messages are persisted, which affects usage and billing.

왜 이것이 AI 출력의 더 나은 기본값인가

에이전시 AI 앱을 배포하고 있다면, 결국 세 가지가 필요합니다:

  1. 실시간 사용자를 위한 점진적 렌더링.
  2. 저장 및 검색을 위한 전체 응답의 단일하고 압축된 표현.
  3. 맞춤형 파이프라인 없이 재연결, 새로 고침 및 늦게 참여하는 경우를 견고하게 처리.

메시지 추가는 이 세 가지를 즉시 제공합니다. 🎉

at the same time:

- streaming UX  
- history that's usable  
- recovery that does not depend on luck  

Appends are how you get there without building your own "message reconstruction" subsystem. If you want the deeper mechanics (including the *message‑per‑response* pattern and rollup tuning), the [AI Transport docs](https://ably.com/docs/ai-transport) are the best place to start.

앱엔드(Appends)는 자체 “메시지 재구성” 서브시스템을 구축하지 않고도 이를 달성하는 방법입니다. 더 깊은 메커니즘(예: 응답당 메시지 패턴 및 롤업 튜닝)을 원한다면, AI Transport docs 가 시작하기에 가장 좋은 곳입니다.

0 조회
Back to Blog

관련 글

더 보기 »