• Protocol Buffers๋Š” Google์ด ๋งŒ๋“  ์–ธ์–ด ์ค‘๋ฆฝ schema-first ์ง๋ ฌํ™” ํ”„๋ ˆ์ž„์›Œํฌ
  • .proto ๋‹จ์ผ ์ •์˜์—์„œ ๋‹ค์–ธ์–ด ์ฝ”๋“œ ์ž๋™ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • JSON๋ณด๋‹ค ์ž‘๊ณ  ๋น ๋ฅธ ๋ฐ”์ด๋„ˆ๋ฆฌ wire format
  • ํ•„๋“œ ๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜์˜ ํ•˜์œ„ ํ˜ธํ™˜์„ฑ ๋ณด์žฅ ์„ค๊ณ„

Protocol Buffers๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

  • ๋‹ค์–ธ์–ด ํ˜‘์—…: TS ์„œ๋ฒ„์™€ Python ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์•„์•ผ ํ•  ๋•Œ, ์–‘์ชฝ์ด ๊ฐ™์€ ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ–๋„๋ก ๊ฐ•์ œ
  • JSON์˜ ํ•œ๊ณ„: ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜์ด๋ผ ํฌ๊ธฐยท์†๋„ ๋ชจ๋‘ ๋น„ํšจ์œจ, ํƒ€์ž… ์•ˆ์ „์„ฑ ์—†์Œ, ์Šคํ‚ค๋งˆ ๊ฐ•์ œ๋ ฅ ์—†์Œ
  • API ์ง„ํ™”: ํ•„๋“œ ์ถ”๊ฐ€ยท์ œ๊ฑฐ ์‹œ์—๋„ ๊ตฌ๋ฒ„์ „ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊นจ์ง€์ง€ ์•Š์•„์•ผ ํ•จ
  • ํŽธ์ง‘๊ธฐ ์ง€์›: ์ž๋™ ์ƒ์„ฑ๋œ ํƒ€์ž…์œผ๋กœ IDE ์ž๋™์™„์„ฑยทํƒ€์ž… ์ฒดํฌ ๊ฐ€๋Šฅ

AS-IS โ€” JSON์œผ๋กœ ๋‹ค์–ธ์–ด ํ†ต์‹ ํ•  ๋•Œ

sequenceDiagram
    autonumber
    participant TS as TypeScript Server
    participant P as Python Client
    Note over TS,P: ์–‘์ชฝ์ด ๋ณ„๋„ ํƒ€์ž… ์ •์˜ ์œ ์ง€
    TS->>TS: TS interface๋กœ Event ํƒ€์ž… ์ •์˜
    P->>P: Pydantic BaseModel๋กœ Event ํƒ€์ž… ์ •์˜
    TS->>P: JSON ๋ฉ”์‹œ์ง€ ์ „์†ก (ํ•„๋“œ๋ช… ํ…์ŠคํŠธ ๊ทธ๋Œ€๋กœ)
    P->>P: ์ˆ˜๋™ ํŒŒ์‹ฑ, ๋Ÿฐํƒ€์ž„ ํƒ€์ž… ์ฒดํฌ
    Note over TS,P: ํ•œ์ชฝ์ด ํ•„๋“œ ์ด๋ฆ„ ๋ฐ”๊พธ๋ฉด ๊นจ์ง<br/>์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์€ ์ฝ”๋“œ ๋ฆฌ๋ทฐ์— ์˜์กด

TO-BE โ€” Protocol Buffers ์‚ฌ์šฉ

sequenceDiagram
    autonumber
    participant Proto as events.proto
    participant TS as TypeScript Server
    participant P as Python Client
    Proto->>TS: protoc๋กœ events_pb.ts ์ž๋™ ์ƒ์„ฑ
    Proto->>P: protoc๋กœ events_pb2.py ์ž๋™ ์ƒ์„ฑ
    TS->>P: binary wire format ์ „์†ก
    P->>P: ์ƒ์„ฑ๋œ ํด๋ž˜์Šค๋กœ ์ž๋™ ์—ญ์ง๋ ฌํ™”
    Note over TS,P: ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ์‹œ ์–‘์ชฝ ์ฝ”๋“œ ์ž๋™ ๊ฐฑ์‹ <br/>ํ•„๋“œ ๋ฒˆํ˜ธ๋กœ ํ•˜์œ„ ํ˜ธํ™˜ ์ž๋™ ๋ณด์žฅ

.proto ํŒŒ์ผ์˜ ๊ตฌ์กฐ

AG-UI์˜ events.proto ์ผ๋ถ€:

syntax = "proto3";
 
package ag_ui;
 
enum EventType {
  TEXT_MESSAGE_START = 0;
  TEXT_MESSAGE_CONTENT = 1;
  TEXT_MESSAGE_END = 2;
  // ... 16์ข… ์ด๋ฒคํŠธ
}
 
message TextMessageContentEvent {
  BaseEvent base_event = 1;
  string message_id = 2;
  string delta = 3;
}

ํ•ต์‹ฌ ์š”์†Œ:

  • syntax = "proto3" โ€” proto ๋ฒ„์ „ (ํ˜„์žฌ ๊ถŒ์žฅ)
  • package โ€” ๋„ค์ž„์ŠคํŽ˜์ด์Šค (์ƒ์„ฑ ์ฝ”๋“œ์˜ ๋ชจ๋“ˆ ๊ฒฝ๋กœ์— ์˜ํ–ฅ)
  • enum / message โ€” ํƒ€์ž… ์ •์˜
  • ํ•„๋“œ๋ช… = ๋ฒˆํ˜ธ โ€” ๋ฒˆํ˜ธ๊ฐ€ wire format์˜ ์‹๋ณ„์ž, ์ ˆ๋Œ€ ๋ณ€๊ฒฝ ๊ธˆ์ง€

๋‹ค์–ธ์–ด ์ง€์› (๊ณต์‹ protoc)

์–ธ์–ด์ง€์› ํ˜•ํƒœ
C++๊ณต์‹
C#๊ณต์‹
Java๊ณต์‹
Kotlin๊ณต์‹
Objective-C๊ณต์‹
PHP๊ณต์‹
Python๊ณต์‹
Ruby๊ณต์‹
DartGitHub ํ”Œ๋Ÿฌ๊ทธ์ธ
GoGitHub ํ”Œ๋Ÿฌ๊ทธ์ธ
TypeScript์„œ๋“œํŒŒํ‹ฐ (ts-proto, @bufbuild/protobuf ๋“ฑ)

โ†’ ๋™์ผ .proto ํŒŒ์ผ์—์„œ protoc๋งŒ ๋‹ค๋ฅด๊ฒŒ ๋Œ๋ฆฌ๋ฉด 8+๊ฐœ ์–ธ์–ด๋กœ ์ฝ”๋“œ ์ƒ์„ฑ ๊ฐ€๋Šฅ. TypeScript๋Š” ๊ณต์‹ ์ง€์›์ด ์—†์–ด AG-UI๋Š” ts-proto/@bufbuild/protobuf๋ฅผ ์‚ฌ์šฉ.

์ฝ”๋“œ ์ƒ์„ฑ ์›Œํฌํ”Œ๋กœ

flowchart LR
    Proto[".proto ํŒŒ์ผ"]
    Protoc["protoc ์ปดํŒŒ์ผ๋Ÿฌ"]
    PluginTS["ts-proto ํ”Œ๋Ÿฌ๊ทธ์ธ"]
    PluginPy["python-protoc ํ”Œ๋Ÿฌ๊ทธ์ธ"]
    PluginKt["kotlin ํ”Œ๋Ÿฌ๊ทธ์ธ"]
    OutTS["events_pb.ts"]
    OutPy["events_pb2.py"]
    OutKt["EventsProto.kt"]

    Proto --> Protoc
    Protoc --> PluginTS --> OutTS
    Protoc --> PluginPy --> OutPy
    Protoc --> PluginKt --> OutKt

AG-UI์˜ generate ์Šคํฌ๋ฆฝํŠธ(packages/proto/package.json):

protoc --ts_proto_out=./src/generated \
  --ts_proto_opt=esModuleInterop=true \
  -I ./src/proto ./src/proto/*.proto

ํ•„๋“œ ๋ฒˆํ˜ธ โ€” ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์˜ ๋น„๋ฐ€

message User {
  string name = 1;        // ๋ฒˆํ˜ธ 1๋ฒˆ
  int32 id = 2;           // ๋ฒˆํ˜ธ 2๋ฒˆ
  // string email = 3;    // ์ œ๊ฑฐ๋œ ํ•„๋“œ โ€” ๋ฒˆํ˜ธ ์žฌ์‚ฌ์šฉ ๊ธˆ์ง€
  string phone = 4;       // ์ƒˆ ํ•„๋“œ ์ถ”๊ฐ€
}
  • wire format์—๋Š” ํ•„๋“œ ์ด๋ฆ„์ด ์—†์Œ, ๋ฒˆํ˜ธ๋งŒ ๋“ค์–ด๊ฐ โ†’ ์ด๋ฆ„ ๋ฐ”๊ฟ”๋„ ํ˜ธํ™˜๋จ
  • ๋ฒˆํ˜ธ๋Š” ์ ˆ๋Œ€ ์žฌ์‚ฌ์šฉยท๋ณ€๊ฒฝ ๊ธˆ์ง€ โ†’ ๊ตฌ๋ฒ„์ „์ด ์ƒˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋‚˜๋ฉด ๋ชจ๋ฅด๋Š” ๋ฒˆํ˜ธ๋Š” ๋ฌด์‹œ
  • ์ƒˆ ํ•„๋“œ๋Š” optional๋กœ ์ถ”๊ฐ€ โ†’ ์˜› ์ฝ”๋“œ๋Š” ๋ชจ๋ฅด๊ณ  ์ง€๋‚˜๊ฐ€๋„ ์•ˆ์ „

JSON๊ณผ์˜ ๋น„๊ต

ํ•ญ๋ชฉJSONProtocol Buffers
ํ˜•์‹ํ…์ŠคํŠธ๋ฐ”์ด๋„ˆ๋ฆฌ
ํฌ๊ธฐํผ (ํ•„๋“œ๋ช… ํฌํ•จ)์ž‘์Œ (ํ•„๋“œ ๋ฒˆํ˜ธ๋งŒ)
์†๋„ํŒŒ์‹ฑ ๋А๋ฆผ๋งค์šฐ ๋น ๋ฆ„
ํƒ€์ž… ์•ˆ์ „์„ฑ๋Ÿฐํƒ€์ž„ ๊ฒ€์ฆ ํ•„์š”์ปดํŒŒ์ผ ์‹œ์  ๋ณด์žฅ
์Šคํ‚ค๋งˆ์„ ํƒ (JSON Schema ๋“ฑ)ํ•„์ˆ˜ (.proto)
๊ฐ€๋…์„ฑ๋†’์Œ (๋””๋ฒ„๊น… ์‰ฌ์›€)๋‚ฎ์Œ (binary)
๋‹ค์–ธ์–ด ์ฝ”๋“œ ์ƒ์„ฑ์—†์Œํ•ต์‹ฌ ๊ธฐ๋Šฅ

โ†’ AG-UI๊ฐ€ SSE(JSON ๊ธฐ๋ฐ˜)์™€ protobuf ๋‘˜ ๋‹ค ์ง€์›ํ•˜๋Š” ์ด์œ : ๋””๋ฒ„๊น… ํŽธ์˜(JSON) vs ์„ฑ๋Šฅ(proto) ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋งก๊น€.

AG-UI์—์„œ์˜ ์œ„์น˜

AG-UI๋Š” 3๊ฐœ .proto ํŒŒ์ผ์„ ์‚ฌ์šฉ:

  • events.proto โ€” 16์ข… ์ด๋ฒคํŠธ ์ •์˜
  • types.proto โ€” Message, Tool ๋“ฑ ๊ณตํ†ต ํƒ€์ž…
  • patch.proto โ€” JSON Patch ์—ฐ์‚ฐ

ํ˜„์žฌ๋Š” TS SDK์—์„œ๋งŒ ์ฝ”๋“œ ์ƒ์„ฑ์„ ๋Œ๋ฆฌ์ง€๋งŒ(Python SDK๋Š” ๋ณ„๋„ ํƒ€์ž… ์ •์˜ ์‚ฌ์šฉ), .proto ์ž์ฒด๋Š” ์–ธ์–ด ์ค‘๋ฆฝ์ด๋ฏ€๋กœ ๋ˆ„๊ตฌ๋‚˜ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ์ •์˜๋˜์–ด ์žˆ์Œ. ์ด๊ฒƒ์ด protobuf๋ฅผ ๋ณ„๋„ ํŒจํ‚ค์ง€(@ag-ui/proto)๋กœ ๋ถ„๋ฆฌํ•œ ์˜๋ฏธ.

์ฐธ๊ณ  ๋ฌธ์„œ