← 블로그로 돌아가기

Drive 폴링으로는 에이전트 협업이 안 된다

Drive 폴링으로는 에이전트 협업이 안 된다

Google Drive는 문서를 쌓는 곳이지, 에이전트가 서로 턴을 주고받는 실시간 버스가 아니다.
협업 문서와 실행 레이어를 섞는 순간 시스템은 느려지고, 중복되고, 복구가 어려워진다.

TL;DR

  • Google Drive는 docs / clippings / snapshots / slow inbox로는 유용하지만, 실시간 에이전트 transport로는 부적합하다.
  • 실시간 협업의 source of truth는 PostgreSQL 메일박스가 맡아야 한다.
  • LISTEN/NOTIFY는 저장소가 아니라 wake-up signal이다.
  • 실제 소비자는 SSEWebSocket으로 이벤트를 받고, 폴링은 복구 수단으로만 남겨야 한다.
  • 에이전트 제품의 품질은 모델보다 턴 설계, idempotency, audit, rollback에서 갈린다.

왜 이 주제가 지금 중요하냐

에이전트 제품을 만들다 보면 금방 이런 유혹이 온다.

“어차피 Drive에 문서가 쌓이고 있으니, 여기서 폴링하면 되지 않을까?”

겉으로는 합리적이다. 이미 Google Workspace를 쓰고 있고, 문서 공유도 쉽고, 운영자와 여러 에이전트가 역할을 나누기에도 편해 보인다. 하지만 이 방식은 협업이 커질수록 문제를 만든다.

Drive는 본질적으로 문서 저장과 공유에 강하다. 반면 에이전트 시스템은 상태 전이와 이벤트 처리에 강해야 한다. 둘은 비슷해 보이지만 전혀 다르다.

문서 중심 시스템은 이렇게 움직인다.

작성 → 저장 → 공유 → 읽기 → 수정

에이전트 중심 시스템은 이렇게 움직인다.

상태 생성 → 이벤트 발행 → 소비 → 검증 → 다음 턴 생성

여기서 차이는 작아 보이지만, 제품이 커질수록 엄청 커진다.

Drive가 잘하는 일, 못하는 일

Drive가 잘하는 건 명확하다.

  • 참고 문서 저장
  • 공유 드래프트 보관
  • 스크랩한 자료 묶기
  • 스냅샷 아카이브 만들기
  • 사람이 읽고 고칠 문서 관리하기

즉 Drive는 협업 문서 레이어다.

반대로 Drive가 약한 건 이런 것들이다.

  • 이벤트 순서를 보장하는 것
  • 중복 업로드를 자연스럽게 제어하는 것
  • “누가 언제 어떤 턴을 소비했는가”를 추적하는 것
  • 실패한 턴을 다시 이어서 처리하는 것
  • 실시간 소비자에게 빠르게 wake-up을 주는 것

Drive를 transport로 쓰면 결국 폴링이 들어간다. 폴링은 나쁘지 않다. 복구용으로는 좋다. 하지만 primary path가 되면 시스템이 느려지고, 충돌하고, 재시도가 늘어난다.

그래서 Drive는 inbox가 아니라 slow inbox 정도로 두는 게 맞다.

실시간 협업의 중심은 메일박스다

이제 구조를 분리해야 한다.

1. PostgreSQL이 source of truth

에이전트가 맡은 작업, 결과, 상태, 누가 소비했는지, 재시도했는지 같은 핵심 데이터는 PostgreSQL에 먼저 써야 한다.

왜냐하면 DB는 다음을 제공하기 때문이다.

  • 트랜잭션
  • 인덱싱
  • 상태 조회
  • 복구 쿼리
  • 감사 로그
  • 중복 방지용 키 설계

즉, 메일박스는 문서 보관소가 아니라 운영 데이터베이스여야 한다.

2. LISTEN/NOTIFY는 깨우는 역할만

PostgreSQL의 LISTEN/NOTIFY는 이벤트를 저장하는 곳이 아니다. 그냥 “새 턴이 들어왔다”고 소비자에게 알려주는 종이다.

이 역할만 맡기면 된다.

  • durable storage는 DB row
  • wake-up signal은 NOTIFY
  • 실제 내용은 다시 DB 조회

이렇게 해야 알림이 유실되거나 중복되더라도 복구가 가능하다.

3. 소비자는 SSE/WebSocket으로 붙는다

실시간 소비자는 SSEWebSocket으로 이벤트 스트림에 붙는다.

이때 중요한 건 이벤트 자체보다 복구 경로다.

  • after_id 같은 커서가 있어야 한다
  • 마지막으로 본 이벤트를 기억해야 한다
  • 재연결 시 누락분을 다시 읽어야 한다

즉, 스트림은 라이브 경험을 제공하고, DB는 진실을 보관한다.

Drive inbox와 Mailbox API는 역할이 다르다

이 구분이 핵심이다.

Drive inbox는 사람이 읽는 곳이다. Mailbox API는 에이전트가 일하는 곳이다.

Drive는 이런 걸 담는다.

  • 장문 브리프
  • 스크린샷
  • 원문 요약
  • 공유 초안
  • 오퍼레이션 문서

Mailbox API는 이런 걸 담는다.

  • task 생성
  • assign 대상
  • priority
  • payload
  • idempotency key
  • consume 여부

이 둘을 섞어버리면 나중에 엉킨다.

예를 들어 Drive 문서 제목만 보고 에이전트가 작업을 시작하면, 같은 문서를 두 번 읽을 수 있다. 문서 편집 타이밍과 상태 전이 타이밍이 다르기 때문이다. 반대로 Mailbox API는 “작업을 생성했다”는 사실 자체가 명확하니, 이후 흐름을 제어하기 쉽다.

문서는 협업을 돕고, 메일박스는 실행을 보장한다.

실제로는 이런 구조가 가장 단순하다

현실적인 추천 구조는 다음과 같다.

Google Drive
  ├─ docs/          : 공유 문서, 프로토콜, 요약
  ├─ clippings/     : 원문 스크랩, 참고 자료
  └─ mailbox/       : slow inbox, 백업 inbox

PostgreSQL Mailbox API
  ├─ threads/tasks/results
  ├─ consume state
  ├─ audit log
  └─ idempotency keys

Event layer
  ├─ LISTEN/NOTIFY
  ├─ SSE stream
  └─ WebSocket stream

이 구조의 장점은 분명하다.

  • Drive가 느려도 운영이 안 멈춘다
  • 실시간 이벤트는 DB와 스트림이 처리한다
  • 문서와 실행을 분리할 수 있다
  • 복구와 재처리가 쉬워진다

이건 단순히 기술적으로 예쁜 구조가 아니다. 실제 운영에서 덜 망가지는 구조다.

왜 이게 제품 전략까지 바꾸냐

여기서 중요한 건 아키텍처 감상평이 아니다. 이 분리는 제품 전략에도 영향을 준다.

Drive 중심 제품은 종종 “공유 문서 기능”으로 보인다. 메일박스 중심 제품은 “협업 운영체계”로 보인다.

둘의 차이는 크다.

  • 전자는 저장과 보기 중심이다
  • 후자는 작업, 책임, 검증, 되돌리기 중심이다

에이전트 제품을 진짜 서비스로 키우려면, 사용자는 문서를 읽는 게 아니라 작업을 맡기고 결과를 검증해야 한다. 그러려면 다음이 필요하다.

  • 어떤 턴이 누구에게 가는지
  • 어떤 결과가 완료로 간주되는지
  • 실패했을 때 누가 다시 붙는지
  • 중복 턴을 어떻게 막는지
  • 승인 전과 후의 경계를 어떻게 나누는지

즉, 제품 경쟁력은 “얼마나 잘 써주냐”보다 “얼마나 안정적으로 턴을 굴리냐”로 이동한다.

실전 체크리스트

에이전트 협업 레이어를 만들 때는 아래 질문을 먼저 통과시켜야 한다.

# Agent Mailbox Checklist

## Storage
- 진짜 상태는 어디에 저장되는가?
- 문서와 실행 상태가 섞이지 않는가?

## Transport
- wake-up signal과 durable storage가 분리되어 있는가?
- 폴링이 primary path가 아닌가?

## Idempotency
- 같은 턴이 두 번 와도 안전한가?
- topic key / request key가 있는가?

## Audit
- 누가 언제 무엇을 소비했는지 남는가?
- 실패와 재시도가 로그로 보이는가?

## Recovery
- 커서 기반으로 누락 이벤트를 복구할 수 있는가?
- 스트림이 끊겨도 DB에서 다시 이어붙일 수 있는가?

이 체크리스트가 없으면, 시스템은 금방 “돌아가는 것처럼 보이는” 상태가 된다. 그 상태가 제일 위험하다.

결론: Drive는 협업 문서고, 메일박스는 실행 레이어다

이번 신호를 한 문장으로 압축하면 이렇다.

Google Drive는 에이전트의 보관함으로는 좋지만, 에이전트의 실행 버스로는 느리다.

그래서 여러 에이전트가 협업하는 시스템을 만들 때는 역할을 분리해야 한다.

  • Drive = 문서, 스냅샷, 참고 자료, 느린 inbox
  • PostgreSQL Mailbox = source of truth
  • NOTIFY = wake-up only
  • SSE/WebSocket = realtime consumer
  • Polling = fallback only

이 분리만 해도 시스템이 훨씬 단순해지고, 복구가 쉬워지고, 나중에 제품화하기 좋다.

AI 제품의 진짜 승부는 모델의 말솜씨가 아니라, 턴을 어디에 저장하고 어떤 방식으로 전달하느냐에서 난다. 그리고 그 차이는 생각보다 훨씬 크다.