# ๐Ÿ”’ MAM ๊ฐœ์ธ ์ „์šฉ ๋ธŒ๋กœ์ปค(Private Broker) ๊ตฌ์ถ• ๋ฐ ์—ฐ๋™ ๊ฐ€์ด๋“œ (`PRIVATE_SERVER.md`) - **์ž‘์„ฑ์ผ**: 2026-08-20 - **๋ฌธ์„œ ๋ชฉ์ **: MAM(Multi-Agent Mux)์˜ ๊ณต๊ฐœ ๋ธŒ๋กœ์ปค ์˜์กด์„ฑ ๋ฐ ๋ณด์•ˆ ๊ฒฐํ•จ(A-2)์„ ํ•ด์†Œํ•˜๊ธฐ ์œ„ํ•œ ๊ฐœ์ธ ์ „์šฉ ๋ธŒ๋กœ์ปค(NATS / Mosquitto) ๊ตฌ์ถ•, ์šด์˜ ๋ฐ MAM ํด๋ผ์ด์–ธํŠธ ์—ฐ๋™ ๊ฐ€์ด๋“œ. - **์—ฐ๊ณ„ ๋ฌธ์„œ**: [`NATS_REPORT.md`](NATS_REPORT.md), [`IMPROVEMENTS.md`](IMPROVEMENTS.md) --- ## 1. ๊ฐœ์š” ๋ฐ ๋„์ž… ๋ฐฐ๊ฒฝ ํ˜„์žฌ MAM ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๊ธฐ๋ณธ ๋ฉ”์‹œ์ง• ๋ธŒ๋กœ์ปค๋Š” ๊ณต๊ฐœ ์„œ๋ฒ„(`broker.hivemq.com:1883`)๋กœ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ์ธ ์ „์šฉ ๋ธŒ๋กœ์ปค(Private Broker)๋ฅผ ๊ตฌ์ถ•ํ•˜์—ฌ ์—ฐ๊ฒฐํ•˜๋ฉด **ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด(0์ค„ ๋ณ€๊ฒฝ)** ๋ณด์•ˆ ์œ„ํ—˜์„ ์›์ฒœ ์ฐจ๋‹จํ•˜๊ณ  ๋„คํŠธ์›Œํฌ ์•ˆ์ •์„ฑ์„ ๋Œ€ํญ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ``` [MAM Orchestrator / Agents] โ”‚ โ–ผ (MQTT 3.1.1 / TLS) [Private Dedicated Broker] โ”€โ”€โ”€> ์‚ฌ์„ค๋ง/๊ฐœ์ธ ์„œ๋ฒ„ (NATS Server / Mosquitto) โ€ข ์™ธ๋ถ€ ๋ถˆ๋ฒ• ํŠธ๋ž˜ํ”ฝ 100% ์ฐจ๋‹จ (A-2 ๋ณด์•ˆ ํ•ด์†Œ) โ€ข JetStream ์˜์†์„ฑ ๋ฐ NKey/JWT ACL ์ง€์› โ€ข ์ดˆ์ €์ง€์—ฐ (<1ms) ๋ฐ ๋ฌด์ œํ•œ ๋Œ€์—ญํญ ``` --- ## 2. ํ•ด๊ฒฐ ์˜์—ญ ๋งคํŠธ๋ฆญ์Šค (๋ธŒ๋กœ์ปค ์ „ํ™˜ vs ์ฝ”๋“œ ํŒจ์น˜) ์ „์šฉ ๋ธŒ๋กœ์ปค ๊ตฌ์ถ•์œผ๋กœ ์ฆ‰์‹œ ํ•ด๊ฒฐ๋˜๋Š” ์˜์—ญ๊ณผ, ๋กœ์ปฌ ์ฝ”๋“œ ํŒจ์น˜(Track 0)๊ฐ€ ๋ณ‘ํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์˜์—ญ์˜ ๋ช…ํ™•ํ•œ ๊ตฌ๋ถ„์ž…๋‹ˆ๋‹ค. | ๊ตฌ๋ถ„ | ๋‹น๋ฉด ๊ณผ์ œ | ๊ฐœ์ธ ๋ธŒ๋กœ์ปค ๊ตฌ์ถ• ์‹œ | ๋กœ์ปฌ ์ฝ”๋“œ ํŒจ์น˜ ํ•„์š” ์—ฌ๋ถ€ (Track 0) | |---|---|:---:|:---:| | **๋ณด์•ˆ (A-2)** | ๊ณต๊ฐœ ๋ธŒ๋กœ์ปค ๋…ธ์ถœ ๋ฐ ์™ธ๋ถ€ ์•…์˜์  ์ด๋ฒคํŠธ ์ˆ˜์‹  ์œ„ํ˜‘ | ๐ŸŸข **100% ์ฆ‰์‹œ ํ•ด์†Œ** (์‚ฌ์„ค๋ง/ACL ๊ฒฉ๋ฆฌ) | Track 2์—์„œ ํ† ํฐ ๋ฐœ๊ธ‰ ๊ฐ•์ œ | | **์•ˆ์ •์„ฑ** | ๊ณต๊ฐœ ๋ธŒ๋กœ์ปค์˜ ์˜ˆ๊ณ  ์—†๋Š” ์ˆœ๋‹จ ๋ฐ ์†๋„ ์ œํ•œ(Rate-limit) | ๐ŸŸข **100% ์ฆ‰์‹œ ํ•ด์†Œ** (์ „์šฉ ๋ฆฌ์†Œ์Šค) | โ€” | | **๋‚ด๊ฒฐํ•จ์„ฑ (B-14)** | ๋ธŒ๋กœ์ปค ์ผ์‹œ ์žฅ์•  ์‹œ 65๋ถ„ ๋ฃจํ”„ ์ •์ง€(Hang) ๊ฒฐํ•จ | โš ๏ธ ๋ธŒ๋กœ์ปค ์ ๊ฒ€/์ˆœ๋‹จ ์‹œ ์—ฌ์ „ํžˆ ์œ„ํ—˜ | ๐Ÿ”ด **ํ•„์ˆ˜ (Track 0 Step 1 ์„ ํ–‰ ํŒจ์น˜)** | | **์ง€์—ฐ/์˜คํŒ (B-15)** | ๋ธŒ๋กœ์ปค ๋‹ค์šด ์‹œ 120์ดˆ ์ง€์—ฐ ๋ฐ ์ •์ƒ ์ž‘์—…์˜ ์—๋Ÿฌ ์˜คํŒ์ • | โš ๏ธ ๋ธŒ๋กœ์ปค ์ ๊ฒ€/์ˆœ๋‹จ ์‹œ ์—ฌ์ „ํžˆ ์œ„ํ—˜ | ๐Ÿ”ด **ํ•„์ˆ˜ (Track 0 Step 2 & 3 ์„ ํ–‰ ํŒจ์น˜)** | > [!IMPORTANT] > **๋ฐฉํƒ„ ์•„ํ‚คํ…์ฒ˜ ์›์น™:** > "Track 0(`B-14`, `B-15`) ํŒจ์น˜๋ฅผ ํ†ตํ•ด ๋ธŒ๋กœ์ปค๊ฐ€ ๋‹ค์šด๋˜์–ด๋„ ๋ฃจํ”„๊ฐ€ 100% ์ •์ƒ ์™„์ฃผํ•˜๋„๋ก ๋กœ์ปฌ ๋””์Šคํฌ ๋‚ด๊ฒฐํ•จ์„ฑ์„ ๋จผ์ € ํ™•๋ณดํ•˜๊ณ , ๊ฐœ์ธ ๋ธŒ๋กœ์ปค๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ A-2 ๋ณด์•ˆ๊ณผ ์„ฑ๋Šฅ์„ ์™„๊ฒฐํ•ฉ๋‹ˆ๋‹ค." --- ## 3. ์ „์šฉ ๋ธŒ๋กœ์ปค ์ถ”์ฒœ ๋ฐ ๋น„๊ต MAM ํด๋ผ์ด์–ธํŠธ๋Š” ํ‘œ์ค€ `paho-mqtt`๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, MQTT 3.1.1์„ ์ง€์›ํ•˜๋Š” ๋ชจ๋“  ๋ธŒ๋กœ์ปค์™€ 100% ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. | ๋น„๊ต ํ•ญ๋ชฉ | ๐Ÿ† `nats-server` (๊ฐ•๋ ฅ ๊ถŒ์žฅ) | `eclipse-mosquitto` (๋Œ€์•ˆ) | |---|---|---| | **์•„ํ‚คํ…์ฒ˜** | Go ๋‹จ์ผ ์ •์  ๋ฐ”์ด๋„ˆ๋ฆฌ (Zero Dependency) | C ๊ธฐ๋ฐ˜ ๊ฒฝ๋Ÿ‰ ์˜คํ”ˆ์†Œ์Šค ๋ธŒ๋กœ์ปค | | **์ฃผ์š” ํŠน์ง•** | โ€ข ๋‚ด์žฅ MQTT 3.1.1 ์ง€์› (`-m 1883`)
โ€ข JetStream ์—”์ง„ ๋‚ด์žฅ (์ด๋ฒคํŠธ ์˜์†ํ™” ๋ฐ ๋ณต๊ตฌ)
โ€ข NKey/JWT ๊ธฐ๋ฐ˜ ๊ณ„์ • ๋ฐ Subject๋ณ„ ์„ธ๋ถ„ํ™”๋œ ACL | โ€ข ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๋Š” ํ‘œ์ค€ ๊ฒฝ๋Ÿ‰ MQTT ๋ธŒ๋กœ์ปค
โ€ข ๋‚ฎ์€ ๋ฉ”๋ชจ๋ฆฌ ์ ์œ ์œจ (~10MB) | | **์ถ”์ฒœ ์šฉ๋„** | ๋ชจ๋˜ ์ธํ”„๋ผ, ํ™•์žฅ์„ฑ, ๊ฐ์‚ฌ ๋กœ๊ทธ ์˜์†ํ™” | ์ •ํ†ต ์ดˆ๊ฒฝ๋Ÿ‰ ์ž„๋ฒ ๋””๋“œ/IoT ์Šคํƒ€์ผ ํ™˜๊ฒฝ | | **๋ฐฐํฌ ๋‚œ์ด๋„** | ๐ŸŸข ๋ฐ”์ด๋„ˆ๋ฆฌ 1๊ฐœ ์‹คํ–‰ ๋˜๋Š” Docker 1์ค„ | ๐ŸŸข ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € (`apt`, `brew`) ๋˜๋Š” Docker | --- ## 4. ๊ฐœ์ธ ์„œ๋ฒ„ ๋ธŒ๋กœ์ปค ๋ฐฐํฌ ๊ฐ€์ด๋“œ ### 4.1 `nats-server` ๋ฐฐํฌ (๊ถŒ์žฅ) #### ๋ฐฉ๋ฒ• A. Docker / Docker Compose (๊ฐ€์žฅ ๊ฐ„ํŽธ) **๋‹จ์ผ Docker ๋ช…๋ น์–ด ์‹คํ–‰:** ```bash docker run -d \ --name mam-nats \ --restart unless-stopped \ -p 1883:1883 \ -p 4222:4222 \ -p 8222:8222 \ -v /var/lib/nats/data:/data \ nats:latest \ -js --sd /data -m 1883 ``` **Docker Compose (`docker-compose.yml`):** ```yaml version: '3.8' services: nats: image: nats:latest container_name: mam-nats restart: unless-stopped command: ["-js", "--sd", "/data", "-m", "1883"] ports: - "1883:1883" # MQTT 3.1.1 ํฌํŠธ - "4222:4222" # NATS ๊ธฐ๋ณธ ํฌํŠธ - "8222:8222" # HTTP ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์‹œ๋ณด๋“œ volumes: - nats-data:/data volumes: nats-data: ``` #### ๋ฐฉ๋ฒ• B. ๋„ค์ดํ‹ฐ๋ธŒ ๋ฐ”์ด๋„ˆ๋ฆฌ ์„ค์น˜ (Linux / macOS) ```bash # macOS (Homebrew) brew install nats-server nats-server -js -m 1883 # Linux (x86_64 ๋‹จ์ผ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‹ค์šด๋กœ๋“œ) curl -L https://github.com/nats-io/nats-server/releases/download/v2.10.20/nats-server-v2.10.20-linux-amd64.tar.gz | tar xz sudo mv nats-server-v2.10.20-linux-amd64/nats-server /usr/local/bin/ # ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค ๊ตฌ๋™ (JetStream + MQTT ํฌํŠธ 1883 ํ™œ์„ฑํ™”) nats-server -js --sd /var/lib/nats -m 1883 & ``` --- ### 4.2 `mosquitto` ๋ฐฐํฌ (๋Œ€์•ˆ) #### Docker ์‹คํ–‰: ```bash docker run -d \ --name mam-mosquitto \ --restart unless-stopped \ -p 1883:1883 \ -v /etc/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf \ eclipse-mosquitto:latest ``` **๊ธฐ๋ณธ `mosquitto.conf` ์„ค์ • ํŒŒ์ผ ์˜ˆ์‹œ:** ```conf listener 1883 allow_anonymous true persistence true persistence_location /mosquitto/data/ ``` --- ## 5. MAM ํด๋ผ์ด์–ธํŠธ ์—ฐ๋™ ์„ค์ • (`.mam.env`) ๊ฐœ์ธ ์„œ๋ฒ„ ๋ธŒ๋กœ์ปค๊ฐ€ ๊ตฌ๋™๋˜๋ฉด, MAM ์ €์žฅ์†Œ ๋ฃจํŠธ์˜ [`.mam.env`](file:///.mam.env) ํŒŒ์ผ์— ๊ฐœ์ธ ์„œ๋ฒ„ ์ฃผ์†Œ๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ```bash # ============================================================================== # MAM Private MQTT Broker Configuration # ============================================================================== # ๊ฐœ์ธ ์„œ๋ฒ„ IP ๋˜๋Š” ๋„๋ฉ”์ธ MAM_MQTT_HOST="192.168.1.100" # ์˜ˆ: 10.0.0.5, mqtt.my-domain.com ๋“ฑ # MQTT ๊ธฐ๋ณธ ํฌํŠธ (ํ‰๋ฌธ TCP: 1883, TLS ์•”ํ˜ธํ™”: 8883) MAM_MQTT_PORT="1883" # TLS ์•”ํ˜ธํ™” ํ™œ์„ฑํ™” ์—ฌ๋ถ€ (์‚ฌ์„ค ๋‚ด๋ถ€๋ง: false, ๊ณต์ธ๋ง ๋…ธ์ถœ ์‹œ: true) MAM_MQTT_TLS="false" # ์ธ์ฆ ์„ค์ • (์ธ์ฆ ๋ฏธ์„ค์ • ๋ธŒ๋กœ์ปค๋Š” ์ฃผ์„ ์ฒ˜๋ฆฌ ๋˜๋Š” ๋นˆ ๋ฌธ์ž์—ด ์œ ์ง€) # MAM_MQTT_USERNAME="my_agent_user" # MAM_MQTT_PASSWORD="my_secure_password" ``` --- ## 6. ์—ฐ๋™ ๋ฐ ๋™์ž‘ ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ ๊ฐœ์ธ ์„œ๋ฒ„ ๋ธŒ๋กœ์ปค๊ฐ€ ์ •์ƒ ๋™์ž‘ํ•˜๋Š”์ง€ MAM ์ž์ฒด ๋„๊ตฌ๋กœ ์ฆ‰์‹œ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ### Step 1. ๋ธŒ๋กœ์ปค ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ (๋‹จ์ผ ์ด๋ฒคํŠธ ๋ฐœํ–‰) ```bash # ์ž„์‹œ ํ…Œ์ŠคํŠธ ์ด๋ฒคํŠธ ๋ฐœํ–‰ (๋ฐ˜ํ™˜ ์ฝ”๋“œ rc=0 ๋‹จ์–ธ) .venv/bin/python .agents/skills/multi-agent-mux-delegate-job/scripts/publish_event.py \ --job test-ping-01 \ --event progress \ --detail "Private broker connection verified" ``` ### Step 2. ์ „์ฒด ํšŒ๊ท€ ํ…Œ์ŠคํŠธ ๊ฒ€์ฆ (276๊ฑด) ```bash .venv/bin/python -m pytest tests/ -q ``` *๊ธฐ์กด 276๊ฑด์˜ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ๊ฐ€ ๊ฐœ์ธ ๋ธŒ๋กœ์ปค ํ™˜๊ฒฝ์—์„œ๋„ 100% ์ •์ƒ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค.* --- ## 7. ๊ถŒ์žฅ ์‹คํ–‰ ์ˆœ์„œ ``` [Phase 1: ๋‚ด๊ฒฐํ•จ์„ฑ ํ™•๋ณด] โ”€โ”€> [Phase 2: ๊ฐœ์ธ ๋ธŒ๋กœ์ปค ๊ฐ€๋™] โ”€โ”€> [Phase 3: A-2 ๋ณด์•ˆ ์™„์ „ ์ข…๊ฒฐ] Track 0 (B-14, B-15) nats-server / mosquitto ์ง€๋ฌธ ํ† ํ”ฝ ๋ฐ ์ธ์ฆ ํ† ํฐ ๋ฐœ๊ธ‰ ๋กœ์ปฌ ๋””์Šคํฌ ํด๋ฐฑ ํŒจ์น˜ .mam.env ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์—ฐ๋™ ์™ธ๋ถ€ ๊ฐ„์„ญ 100% ์ฐจ๋‹จ ``` 1. **Phase 1 (Track 0 ์„ ํ–‰ ํŒจ์น˜)**: `publish_event.py`์™€ `job_subscriber.py`์˜ ๋กœ์ปฌ ๋””์Šคํฌ ํด๋ฐฑ(`B-14`, `B-15`)์„ ๋จผ์ € ์ˆ˜์ •ํ•˜์—ฌ ๋ธŒ๋กœ์ปค ๋‹ค์šด ์‹œ์—๋„ ๋ฃจํ”„๊ฐ€ ๋ฉˆ์ถ”์ง€ ์•Š๋Š” ๋ฐฉํƒ„ ๊ตฌ์กฐ๋ฅผ ํ™•๋ฆฝํ•ฉ๋‹ˆ๋‹ค. 2. **Phase 2 (๊ฐœ์ธ ๋ธŒ๋กœ์ปค ๊ฐ€๋™)**: ๊ฐœ์ธ ์„œ๋ฒ„์— `nats-server -js -m 1883`์„ ๋„์šฐ๊ณ  `.mam.env`์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. 3. **Phase 3 (A-2 ๋ณด์•ˆ ์™„์ „ ์ข…๊ฒฐ)**: ์›Œํฌ์ŠคํŽ˜์ด์Šค ์ง€๋ฌธ ํ† ํ”ฝ(`mam//jobs/...`) ๋ฐ ๋ฌด์กฐ๊ฑด ํ† ํฐ ๋ฐœ๊ธ‰์„ ์ ์šฉํ•˜์—ฌ ๊ณต๊ฐœ ๋ธŒ๋กœ์ปค ์œ„ํ—˜์„ ์™„์ „ํžˆ ์˜๊ตฌ ํ๊ธฐํ•ฉ๋‹ˆ๋‹ค.