No description
Find a file
2026-06-20 16:28:02 +09:00
.claude chore: update roadmap structure and project files 2026-06-17 13:03:08 +09:00
.tmp perf(dart): WS burst 수신 회귀를 해소한다 2026-06-07 20:42:33 +09:00
.vscode Update launch.json 2026-04-05 20:55:10 +09:00
agent-ops sync: agent-ops from agentic-framework v1.1.152 2026-06-20 16:28:02 +09:00
agent-roadmap update README, roadmap, and stability-baseline milestone 2026-06-19 10:30:44 +09:00
agent-task/archive/2026 add: validation archive records (20260619 final_full_validation) 2026-06-19 09:22:40 +09:00
dart fix: update communicator implementations and move task docs to archive 2026-06-17 07:27:31 +09:00
examples/go-module-consumer 기능: 브라우저 WebSocket 진입점을 추가한다 2026-05-20 07:30:53 +09:00
go fix: update communicator implementations and move task docs to archive 2026-06-17 07:27:31 +09:00
kotlin fix: update communicator implementations (Kotlin, Python, TypeScript) and archive task docs 2026-06-17 07:41:05 +09:00
proto feat: protocol evolution compatibility implementation 2026-06-16 06:56:15 +09:00
python fix: update communicator implementations (Kotlin, Python, TypeScript) and archive task docs 2026-06-17 07:41:05 +09:00
tools feat: protocol evolution compatibility implementation 2026-06-16 06:56:15 +09:00
typescript fix: update communicator implementations (Kotlin, Python, TypeScript) and archive task docs 2026-06-17 07:41:05 +09:00
.aiexclude sync: agent-ops from agentic-framework v1.1.75 2026-05-27 13:49:56 +09:00
.clineignore sync: agent-ops from agentic-framework v1.1.75 2026-05-27 13:49:56 +09:00
.clinerules sync: agent-ops from agentic-framework v1.1.152 2026-06-20 16:28:02 +09:00
.codex Update protocol and add WebSocket protobuf client/server implementations 2026-04-05 20:44:37 +09:00
.cursorignore sync: agent-ops from agentic-framework v1.1.75 2026-05-27 13:49:56 +09:00
.cursorrules sync: agent-ops from agentic-framework v1.1.152 2026-06-20 16:28:02 +09:00
.geminiignore sync: agent-ops from agentic-framework v1.1.75 2026-05-27 13:49:56 +09:00
.gitignore chore: update roadmap structure and project files 2026-06-17 13:03:08 +09:00
AGENTS.md sync: agent-ops from agentic-framework v1.1.152 2026-06-20 16:28:02 +09:00
CLAUDE.md sync: agent-ops from agentic-framework v1.1.152 2026-06-20 16:28:02 +09:00
GEMINI.md sync: agent-ops from agentic-framework v1.1.152 2026-06-20 16:28:02 +09:00
opencode.json sync: agent-ops from agentic-framework v1.1.141 2026-06-16 20:57:41 +09:00
PORTING_GUIDE.md update docs and archive task files 2026-06-17 07:10:04 +09:00
PROTOCOL.md update roadmap and documentation 2026-06-18 10:34:55 +09:00
README.md update README, roadmap, and stability-baseline milestone 2026-06-19 10:30:44 +09:00
VERSIONING.md update docs and archive task files 2026-06-17 07:10:04 +09:00

Proto Socket

Proto Socket은 여러 언어와 플랫폼 사이에서 양방향 통신을 하기 위한 바이너리 소켓 프로토콜 라이브러리다.

Protocol Buffers 직렬화, TCP 4바이트 빅엔디안 길이 프리픽스 프레이밍, WebSocket 바이너리 프레임, 타입 기반 메시지 라우팅, 요청-응답 상관관계, 내장 하트비트를 제공한다.


현재 상태

현재 프로토콜 0.1의 사용 가능 호환 구현은 Dart, Go, Kotlin, Python, TypeScript다.

이 프로젝트는 안정화와 유지보수 단계에 있다. 현재 릴리즈 표준은 이 저장소를 Git ref/tag 기준으로 소비하는 방식이며, package registry 배포는 현재 목표가 아니다. C#과 Swift는 계획된 대상이지만, 실제 수요가 생기기 전까지 구현을 미룬다.

프로토콜이나 구현을 바꿀 때는 아래 내부 로컬 검증 매트릭스를 안정성 gate로 사용한다. 현재 주 사용 방식은 Git 기반 소비이므로, CI/CD runner 연결은 기본 운영 모델이 아니며 이 프로젝트 규모와 배포 방식에서는 설계상 과하다. Coverage는 라인 수치가 아니라 프로토콜 계약의 모든 필수 시나리오가 매트릭스에 포함되어 PASS인지로 판단한다.

bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all

검증 스냅샷

다른 프로젝트나 에이전트가 도입 여부를 빠르게 판단할 때는 아래 표 자체를 현재 공개 snapshot으로 본다. 원본 실행 기록은 agent-test/runs/ 아래의 로컬 산출물이라 저장소에는 포함하지 않는다. 절대 throughput/latency는 local host와 runtime 상태에 의존하므로, 회귀 판단은 같은 host/runtime/profile에서 생성한 결과끼리 비교한다.

항목 최신 근거 결과 해석
기능 호환성 로컬 기록 20260618-072542-proto-socket-full-matrix.md, ref 59511b9 PASS proto sync, 동일 언어 테스트, 20개 native cross-language 방향, Dart.web/Dart.web(WSS) client coverage가 모두 통과했다.
성능/안정성 quick 재검증 로컬 기록 20260618-003346-proto-socket-performance-quick.md, ref 1a91f49 PASS same-language, cross-language, TypeScript gateway quick profile이 모두 통과했다. baseline 비교가 없어 regression 판정은 SKIPPED다.
성능/안정성 full baseline 후보 로컬 기록 20260614-123328-proto-socket-performance-full.md, ref 29ea189 PASS full profile 기준 same-language, cross-language, TypeScript gateway 성능/안정성 측정이 모두 통과했다.
최신 full 안정성 hard gate 로컬 기록 20260618-144710-proto-socket-stress-full.md, 20260618-205424-proto-socket-stress-full-cross.md, 20260618-210208-proto-socket-stress-full.md, ref 50ef8b2 PASS same-language, cross-language, TypeScript gateway full stress에서 timeout, nonce mismatch, response type mismatch, FIFO violation, pending leak가 모두 0이다.
최신 full 성능 회귀 비교 로컬 기록 20260618-144710-proto-socket-performance-full.md, ref 50ef8b2 WARN baseline 대비 throughput 20% 이상 하락 또는 p99 25% 이상 악화 row가 96개 있었다. 기능/호환성/안정성 실패가 아니라 local host/runtime 상태에 민감한 성능 비교 경고로 보고, 완료 차단 항목으로 보지 않는다.

성능 full 기록의 대표 수치는 다음과 같다.

대표 결과
30분 sustained Dart TCP 40k rps, TypeScript TCP 33k rps, Kotlin TCP 27k rps, Go TCP 15.6k rps, Python TCP 12.2k rps 수준
1024 clients 병렬 Go TCP 209k rps/p99 133ms, Kotlin TCP 70k rps/p99 219ms, TypeScript TCP 47k rps/p99 76ms
1MB payload Python TCP 463 rps/p99 17ms, Go TCP 415 rps/p99 20ms, Kotlin TCP 351 rps/p99 46ms
TypeScript gateway in-process gateway는 TCP/WS p99 1.7-3.2ms 수준, worker_threads gateway는 p99 190-203ms 수준이라 저지연 기본값으로 보지 않는다.

도입 판단은 "얇은 protocol-first 소켓 프레임워크로 충분히 실용적"으로 둔다. 다만 Kotlin WebSocket과 Python high-concurrency row는 다른 구현보다 tail latency가 크므로, 초저지연/초고동시성 제품에서는 해당 언어와 transport 조합을 별도로 재측정한다. 최신 full 성능 회귀 비교의 WARN은 correctness 또는 stability failure가 아니라 같은 host/runtime/profile의 상태 차이에 따라 흔들릴 수 있는 참고 경고다. 성능 회귀 없음까지 제품 gate로 확정해야 하는 경우에는 idle 상태의 같은 host에서 run_performance.sh --full --baseline <이전 performance record>를 반복 실행해 재현성을 본다.

2026-06-19 완료 판단

2026-06-19 기준으로 Proto Socket은 프로토콜 0.1과 현재 사용 가능 언어 5종(Dart, Go, Kotlin, Python, TypeScript)에 대해 완료 상태로 둔다. 완료 근거는 최신 전체 기능 매트릭스 PASS, 최신 full 안정성 hard gate PASS, 기존 full baseline PASS, README/PROTOCOL/VERSIONING/PORTING_GUIDE 정합성 점검이다. 최신 full 성능 회귀 비교의 WARN은 환경 의존 성능 비교 경고이며 기능/호환성/안정성 완료 판단을 막지 않는다.

이후 작업은 유지보수 모드로 제한한다. 허용 범위는 bug fix, 문서 정정, 테스트 runner 보강, 호환성을 유지하는 작은 구현 수정이다. C#/Swift 같은 새 언어 확장, package registry 배포, protocol/API 변경은 실제 소비 수요와 명시적 재개 요청이 있을 때 별도 작업으로 다시 연다.

프로토콜 또는 공개 API 변경은 호환성 작업으로 다룬다. 관련 문서를 갱신하고, 필요한 경우 protobuf binding을 재생성하며, 전체 검증 매트릭스가 통과해야 한다.

런타임 포트와 테스트 포트

Proto Socket은 라이브러리이며 frontend/backend runtime service port를 소유하지 않는다. 애플리케이션 서버가 사용할 host/port는 소비자가 정한다.

README의 9090 예시는 소비자 애플리케이션용 샘플 포트이며 test matrix reserved 대역이 아니다. 저장소의 cross-language/cross-runtime runner는 충돌을 줄이기 위해 29090-29899 local port 대역을 테스트 전용 workspace 예외로 사용한다.

Dart.web 검증은 local Chrome이 없을 때 runner가 구성된 SSH remote browser host에서 실행할 수 있다. WSS 검증은 테스트용 self-signed certificate의 SPKI를 허용하는 Chrome wrapper를 사용하며, tracked 문서에는 credential, token, private endpoint 값을 기록하지 않는다.


설계 원칙

  • core transport layer는 얇고 안정적으로 유지한다.
  • 언어 간 통신에 필요한 최소 공통 기반만 제공한다.
  • framing, serialization, routing, request-response correlation, heartbeat를 표준화한다.
  • Protocol Buffers를 핵심 프로토콜 의존성으로 둔다. 다른 런타임 의존성은 native-first, 좁은 범위, 기능에 비례한 수준으로 유지한다.
  • 애플리케이션 의미를 프로토콜 core에 넣지 않는다.
  • auth, session, agent workflow, chat, game logic 같은 도메인 관심사는 상위 레이어 구현의 책임이다.
  • 수신 처리 계약(inbound queue 순서, receive coordinator, backpressure, close/drain/cancel 정책)은 PROTOCOL.mdReceive Ordering and Backpressure 섹션에 정의하고, 새 언어 구현 기준은 PORTING_GUIDE.md반드시 유지해야 하는 구조 표를 따른다.

프로토콜

전체 wire format 명세는 PROTOCOL.md를 본다.

[4-byte big-endian length] [PacketBase protobuf bytes]

WebSocket/WSS transport에서는 각 binary frame이 TCP length header 없이 PacketBase protobuf payload 하나를 담는다.

프로토콜 호환성은 언어별 package version과 분리해서 추적한다. 자세한 정책은 VERSIONING.md를 본다. 패키지를 아직 registry에 배포하지 않더라도, 저장소에 포함된 구현은 문서화된 프로토콜 계약을 지켜야 한다.


구현체

언어    상태     경로            사용처          
Dart    사용 가능  dart/       Flutter, Dart server   
Kotlin   사용 가능  kotlin/     Android, JVM       
Go     사용 가능  go/         Server, tooling, scripting
TypeScript 사용 가능  typescript/ Browser, Node.js     
Python   사용 가능  python/     Server, tooling, scripting
C#     계획 / 보류 csharp/          Unity, .NET        
Swift    계획 / 보류 swift/          iOS, macOS        

새 언어 구현은 PORTING_GUIDE.mdagent-ops/skills/project/add-proto-socket-crosstest-language/templates/의 템플릿에서 시작한다. 동일 언어 테스트와 크로스 언어 테스트가 통과한 뒤에만 구현 상태를 사용 가능으로 표시한다.

현재 구현 상태는 이 README를 공개 snapshot으로 본다. 현재 작업 맥락은 agent-roadmap/current.md에서 선택하고, 큰 로드맵 방향은 agent-roadmap/ROADMAP.md에 둔다.


주요 명령

목적 명령 비고
전체 로컬 검증 bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all proto sync, 동일 언어 테스트, 사용 가능 구현의 크로스 언어 검증을 실행한다.
성능/안정성 full 측정 bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --full same-language, cross-language, TypeScript gateway 성능과 stability hard gate를 측정한다.
성능 baseline 비교 bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --quick --baseline agent-test/runs/<baseline-record>.md 같은 host/runtime/profile의 이전 기록과 throughput/p99 회귀 후보를 비교한다.
Proto schema sync 확인 tools/check_proto_sync.sh 언어별 proto copy가 허용된 언어 옵션을 제외하고 proto/message_common.proto와 일치하는지 확인한다.
Protobuf binding 재생성 tools/generate_proto.sh canonical proto schema를 바꾼 뒤 실행한다.
Dart 테스트 cd dart && dart pub get && dart test && dart compile js test/browser_ws_import_compile.dart -o /tmp/proto_socket_browser_ws_import_compile.js Dart VM/IO 테스트와 web import compile 확인
Go 테스트 cd go && go test ./... Go 동일 언어 검증
Kotlin 테스트 cd kotlin && ./gradlew test Kotlin 동일 언어 검증
Python 테스트 cd python && python3 -m pytest -q Python 동일 언어 검증
TypeScript 확인 cd typescript && npm run check && npm test TypeScript type check와 테스트

저장소 구조

경로 역할
proto/ canonical protobuf schema 원본
dart/ Dart / Flutter 구현체와 테스트
go/ Go 구현체, 테스트, Go 주도 crosstest
kotlin/ Kotlin / JVM 구현체와 crosstest
python/ Python 구현체와 crosstest
typescript/ TypeScript 구현체와 crosstest
tools/ proto 생성과 sync helper
examples/ 소비자 지향 예제
agent-ops/ 프로젝트 규칙, 로드맵, 반복 agent workflow

빠른 시작: Dart

import 'package:proto_socket/proto_socket.dart';

// 1. message_common.proto에 메시지를 정의하고 protoc로 생성한다.

// 2. client를 구현한다.
class MyClient extends ProtobufClient {
  MyClient(Socket socket) : super(socket, 30, 10, {
    MyMessage.getDefault().info_.qualifiedMessageName: MyMessage.fromBuffer,
  });
}

// 3. server를 구현한다.
class MyServer extends ProtobufServer {
  // 9090 is an application example port, not a proto-socket reserved test port.
  MyServer() : super('0.0.0.0', 9090, (socket) => MyClient(socket));

  @override
  void onClientConnected(ProtobufClient client) {
    client.addListener<MyMessage>((msg) => print('Received: ${msg}'));
  }
}

// 4. server를 시작한다.
final server = MyServer();
await server.start();

// 5. 연결하고 메시지를 보낸다.
final socket = await Socket.connect('localhost', 9090);
final client = MyClient(socket);
await client.send(MyMessage()..text = 'hello');

메시지 타입 추가

canonical proto인 proto/message_common.proto를 수정한 뒤, 저장소에 포함된 모든 binding을 재생성한다.

tools/generate_proto.sh
tools/check_proto_sync.sh

Go와 Kotlin proto copy에는 option go_package, Java package/class option 같은 언어별 옵션만 추가로 허용한다. 메시지 schema가 proto/message_common.proto와 달라지면 tools/check_proto_sync.sh가 diff와 함께 실패한다.


빠른 시작: Go

package main

import (
	"context"
	"net"
	"time"

	"google.golang.org/protobuf/proto"

	protoSocket "git.toki-labs.com/toki/proto-socket/go"
	"git.toki-labs.com/toki/proto-socket/go/packets"
)

func parserMap() protoSocket.ParserMap {
	return protoSocket.ParserMap{
		protoSocket.TypeNameOf(&packets.TestData{}): func(b []byte) (proto.Message, error) {
			m := &packets.TestData{}
			return m, proto.Unmarshal(b, m)
		},
	}
}

func main() {
	ctx := context.Background()

	// 9090 is an application example port, not a proto-socket reserved test port.
	server := protoSocket.NewTcpServer("127.0.0.1", 9090, func(conn net.Conn) *protoSocket.TcpClient {
		return protoSocket.NewTcpClient(conn, 30, 10, parserMap())
	})
	server.OnClientConnected = func(client *protoSocket.TcpClient) {
		protoSocket.AddRequestListenerTyped[*packets.TestData, *packets.TestData](
			&client.Communicator,
			func(req *packets.TestData) (*packets.TestData, error) {
				return &packets.TestData{Index: req.GetIndex(), Message: "echo: " + req.GetMessage()}, nil
			},
		)
	}
	if err := server.Start(ctx); err != nil {
		panic(err)
	}
	defer server.Stop()

	client, err := protoSocket.DialTcp(ctx, "127.0.0.1", 9090, 30, 10, parserMap())
	if err != nil {
		panic(err)
	}
	defer client.Close()

	res, err := protoSocket.SendRequestTyped[*packets.TestData, *packets.TestData](
		&client.Communicator,
		&packets.TestData{Index: 1, Message: "hello"},
		2*time.Second,
	)
	if err != nil {
		panic(err)
	}
	println(res.GetMessage())
}

Go 구현체는 다음 표면도 제공한다.

  • TCP: NewTcpServer, DialTcp, NewTcpServerTLS, DialTcpTLS
  • WebSocket: NewWsServer, NewWsServerWithOptions, DialWs, NewWsServerTLS, NewWsServerTLSWithOptions, DialWss
  • Shared helpers: Send, SendRequest, AddListenerTyped, AddRequestListenerTyped, Broadcast

다른 저장소에서 이 모듈을 사용하는 복사 가능한 scaffold가 필요하면 examples/go-module-consumer/를 본다.


테스트 실행

개발과 문제 재현을 위한 로컬 명령은 이 문서에 정리한다. 반복 가능한 저장소 로컬 검증 진입점은 다음 명령이다.

bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all

이 명령은 proto schema sync, 동일 언어 테스트, 크로스 언어 검증을 실행하고, 실패가 있으면 재현 명령과 함께 PASS/FAIL 표를 출력한다. 더 작은 범위만 확인하려면 --proto, --unit, --cross를 사용한다.

외부 CI runner 연동은 이 저장소의 기본 운영 목표가 아니다. 현재 주 사용 방식은 Git 기반 소비와 내부 로컬 매트릭스 결과 확인이며, 이 범위에서는 별도 CI/CD runner 연결을 요구하지 않는다.

Proto schema sync:

tools/check_proto_sync.sh

동일 언어 검증:

cd dart
dart pub get
dart test
dart compile js test/browser_ws_import_compile.dart -o /tmp/proto_socket_browser_ws_import_compile.js
cd go
go test ./...
cd kotlin
./gradlew test
cd python
python3 -m pytest -q
cd typescript
npm run check
npm test

크로스 언어 검증:

cd go
go run ./crosstest/go_dart.go
go run ./crosstest/go_kotlin.go
go run ./crosstest/go_python.go
go run ./crosstest/go_typescript.go
cd dart
dart run crosstest/dart_go.dart
dart run crosstest/dart_kotlin.dart
dart run crosstest/dart_python.dart
dart run crosstest/dart_typescript.dart
cd kotlin
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinDartKt
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinGoKt
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinPythonKt
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinTypescriptKt
cd python
python3 crosstest/python_dart.py
python3 crosstest/python_go.py
python3 crosstest/python_kotlin.py
python3 crosstest/python_typescript.py
cd typescript
./node_modules/.bin/tsx crosstest/typescript_dart.ts
./node_modules/.bin/tsx crosstest/typescript_go.ts
./node_modules/.bin/tsx crosstest/typescript_kotlin.ts
./node_modules/.bin/tsx crosstest/typescript_python.ts

Dart.io와 Dart.web E2E 매트릭스

위 표의 Dart 열은 Dart VM/IO client를 뜻한다. Dart.web은 별도 축이다. 브라우저 WS/WSS client만 가능하며, 브라우저에서는 TCP와 server 역할이 불가능하므로 해당 cell은 N/A다. Dart.web WSS는 테스트용 self-signed certificate의 SPKI를 허용하는 Chrome 실행 wrapper로 local/remote 브라우저 검증에 포함한다.

Server Dart.io TCP Dart.io WS Dart.io TLS TCP Dart.io WSS Dart.web WS Dart.web WSS Dart.web TCP
Dart.io Covered Covered Covered Covered Covered Covered N/A
Go Covered Covered Covered Covered Covered Covered N/A
Kotlin Covered Covered Covered Covered Covered Covered N/A
Python Covered Covered Covered Covered Covered Covered N/A
TypeScript Covered Covered Covered Covered Covered Covered N/A

각 Dart.web cell은 server-language runner가 WS와 WSS server를 함께 띄우고, matching browser test file에 대해 dart test -p chrome을 실행하며, WS send-push/request-response와 WSS send-push/request-response 4개 시나리오를 검증한다.

cd dart && dart run crosstest/dart_web.dart
cd go && go run ./crosstest/go_dart_web.go
cd kotlin && ./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinDartWebKt
cd python && python3 crosstest/python_dart_web.py
cd typescript && ./node_modules/.bin/tsx crosstest/typescript_dart_web.ts

작업 맥락

코드나 프로토콜을 변경하기 전에 agent-ops/rules/project/rules.md의 프로젝트 규칙과 해당 경로의 domain rule을 확인한다. 활성 로드맵 창은 agent-roadmap/current.md에 있다.

안정화 경계는 다음과 같다.

  • 명시적인 호환성 작업 요청이 없으면 프로토콜 0.1 동작을 안정적으로 유지한다.
  • 유지보수 모드 작업에는 bug fix, 문서 정정, 테스트 강화, 호환성을 유지하는 구현 수정이 포함될 수 있다.
  • C#/Swift, package registry release, protocol/API 변경 작업은 구체적인 소비자 수요, 호환성 계획, 전체 검증 매트릭스 통과 조건이 있을 때 별도 작업으로 재개한다. 현재 릴리즈 표준은 Git ref/tag 기준이다.
  • 상위 ../oto workflow가 결정되기 전까지 이 저장소에서 외부 CI/CD runner를 직접 연결하지 않는다.