index

DeepAgents는 왜 이렇게 생겼을까?

· 6min

DeepAgents는 왜 이렇게 생겼을까?

주방의 딜레마

금요일 저녁 8시. 주문이 20개 밀려있어요. 셰프에겐 5명의 요리사가 있어요.

첫 번째 시도: “내가 한 명씩 확인하면서 요리하자.” → 너무 느렸어요. 손님들이 떠나기 시작했어요.

두 번째 시도: “각자 알아서 해.” → 빨랐지만 엉망이었어요. 스테이크가 나왔는데 소스가 아직 안 됐어요.

세 번째 시도: “각자 요리하고, ‘픽업!’ 외치면 그때 맞춰서 내보내자.” → 완벽하진 않았지만, 돌아갔어요.

이 이야기가 BSP의 전부예요.

💡 BSP (Bulk Synchronous Parallel)

**Bulk**(덩어리) + **Synchronous**(동기화) + **Parallel**(병렬)

"덩어리로 묶어서 동기화하는 병렬 처리"

1990년 하버드의 Leslie Valiant 교수가 제안한 병렬 컴퓨팅 모델이에요[[1]](#ref-1).


코드에서 질문이 생겼어요

LangChain의 DeepAgents 코드를 읽고 있었어요. Superstep, Barrier 같은 용어가 계속 나왔어요.

“왜 이렇게 설계했지? 이 용어들은 어디서 온 거야?”

파고들었어요. 그리고 1990년 논문[1]을 만났어요.


핵심: Superstep

BSP의 핵심은 Superstep이라는 단위예요.

💡 Superstep (슈퍼스텝)

**Super**(위의, 초월하는) + **Step**(단계)

여러 작은 단계를 묶은 "상위 단계"예요.

주방 비유: "각자 요리 → 픽업!" 이 한 사이클이에요.

하나의 Superstep은 세 단계로 이뤄져요:

┌─────────────────────────────────────────┐
│            하나의 Superstep              │
├─────────────────────────────────────────┤
│  1. Computation (계산)                   │
│     각자 독립적으로 일해요                │
│                                         │
│  2. Communication (통신)                 │
│     결과물을 보내요 (아직 못 받아요!)      │
│                                         │
│  3. Barrier (동기화)                     │
│     모두 도착할 때까지 기다려요            │
│     ─────────────────────               │
│     → 다음 Superstep에서 메시지를 받아요   │
└─────────────────────────────────────────┘
💡 Barrier (배리어)

**Barrier** = 장벽, 관문

모두가 도착할 때까지 기다리는 동기화 지점이에요.

주방 비유: 셰프가 "픽업!" 외치는 순간. 모든 요리가 준비될 때까지 접시가 안 나가요.

핵심 규칙:

Superstep N에서 보낸 메시지는 Superstep N+1에서만 받을 수 있어요.

이 단순한 규칙이 주는 것:

  • 데드락 불가능 — 서로 기다리는 순환이 구조적으로 안 생겨요
  • 예측 가능 — 같은 입력이면 같은 결과가 나와요

트레이드오프

방식주방 비유장점단점
완전 동기셰프가 한 접시씩 확인안전해요너무 느려요
완전 비동기각자 알아서 내보냄빨라요타이밍이 엉망이에요
BSP”픽업!” 신호에 맞춤절충안이에요기다리는 비용이 있어요

BSP는 “자주 맞추면 안전하지만 느리고, 드물게 맞추면 빠르지만 위험한” 그 사이 어딘가를 찾아요.

셰프가 “픽업!” 타이밍을 잡는 건, 본능적으로 이 트레이드오프를 최적화한 거예요.


30년 후: AI 에이전트에서 다시 만났어요

2010년 Google이 그래프 처리에 BSP를 적용했어요[2].

그리고 2024년, AI 에이전트 프레임워크에서 다시 만났어요.

flowchart LR
    subgraph "Superstep"
        A["Node A"] --> C["Channel"]
        B["Node B"] --> C
        C --> R["Reducer"]
        R --> |"Barrier"| S["State"]
    end
💡 Channel (채널)

**Channel** = 통로, 수로

노드 간 메시지가 흐르는 통로예요.

BSP에서 "메시지 전송"에 해당해요.

💡 Reducer (리듀서)

**Reduce** = 줄이다, 합치다

여러 결과를 하나로 병합하는 함수예요.

BSP의 Barrier에서 일어나는 "상태 통합"이에요.

제가 파악한 매핑:

BSP 개념LangGraph
ProcessorNode
메시지 전송Channel에 write
BarrierSuperstep 경계
수신Reducer가 병합 후 전달

DeepAgents에서 여러 도구가 병렬로 실행되고, 결과가 자동으로 병합되는 구조 — 30년 전 Valiant가 설계한 BSP[1]의 현대판이에요.


마치며

DeepAgents 코드를 읽다가 시작된 질문이 1990년 논문까지 이어졌어요.

구현체의 “왜”를 물으면, 결국 기초 아이디어를 만나요.

BSP는 그중 하나일 뿐이에요. 앞으로 더 파고들 것들:

  • Actor 모델 — Erlang의 기반
  • CSP — Go의 goroutine/channel

프레임워크는 바뀌어도, 그 뒤의 아이디어는 남아요.


참고

[1] Leslie Valiant, “A Bridging Model for Parallel Computation”, Communications of the ACM, 1990

[2] Malewicz et al., “Pregel: A System for Large-Scale Graph Processing”, SIGMOD, 2010


  • [[deepagents-스터디]]
  • [[moc-ai-agent]]