- 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 | ๊ณต์ |
| Dart | GitHub ํ๋ฌ๊ทธ์ธ |
| Go | GitHub ํ๋ฌ๊ทธ์ธ |
| 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๊ณผ์ ๋น๊ต
| ํญ๋ชฉ | JSON | Protocol 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)๋ก ๋ถ๋ฆฌํ ์๋ฏธ.