Skip to content

DEVELOPMENT

playground edited this page May 31, 2026 · 2 revisions

개발 환경 가이드

로컬에서 SPOT·실 카메라·실 태블릿 없이 코드를 작성·검증하는 절차. CI 통과 + 사무실 미러 환경 검증을 거쳐 전시장에 배포한다.


0. Phase 0 — 환경 준비 체크리스트

SPOT·실 카메라·실 태블릿 없이 로컬에서 풀 스택을 처음 띄우기까지 순서대로 점검하는 부트스트랩 체크리스트. 각 항목의 상세 절차는 아래 해당 섹션을 따른다. 이 체크리스트의 종착점 = §6 Phase 0 게이트(mosquitto + bridge + fake-frigate → vision/zone/enter 발행 확인).

표기: [ ] 갖추거나 만들 것 · [?] 확인·점검할 것.

0.1 사전 도구 설치 (→ §1)

  • Docker 24.0+ + Compose v2 (docker compose version)
  • Python 3.12 + uv, Node.js 20 LTS (uv --version / node -v)
  • mosquitto-clients (mosquitto_sub/mosquitto_pub — 버스 라이브 테일용)
  • (옵션) NVIDIA GPU 또는 USB Coral — vision/Frigate 검증 시에만

0.2 레포 부트스트랩 (→ §2)

  • 모노레포 clone + pre-commit install
  • Python 서비스 uv sync --dev (orchestrator·bridge·mcp-robot-adapter)
  • Node 서비스 npm ci (mcp-tablet-gateway·apps/tablet)

0.3 시크릿·환경변수 (.env.dev)

  • DEV_MODE=true — tablet-gateway 고정 토큰 DEV_TOKEN 허용 (§4.3)
  • fake-spot 자격 bosdyn:bosdyn 명시 (§8 트러블슈팅)
  • ANTHROPIC_API_KEY — Phase 0에는 불필요, Phase 1(orchestrator) 진입 시 필요
  • [?] .env.dev.gitignore에 포함됐는지 — 시크릿 커밋 금지

0.4 MQTT broker (mosquitto) 기동 (→ §3)

  • docker-compose.dev.yml로 mosquitto 기동
  • passwd 파일 권한·uid (chown 1883:1883 passwd, §8)
  • ACL 로드 — 각 서비스 계정이 필요한 토픽만 사용하도록 (SERVICES.md §1)
  • [?] mosquitto_sub -h localhost -t '#' -v 로 연결 확인

0.5 Home Assistant 기동 (→ §3)

  • HA 컨테이너 기동 + configuration.yaml 기본값 로드
  • HA의 MQTT integration이 mosquitto에 연결됐는지 (Settings → Devices & Services)
  • recorder(SQLite) 동작 확인 — HA가 상태 저장 계층임
  • [?] http://localhost:8123 Developer Tools → States 접근 가능

0.6 Mock 하니스 (→ §4)

  • ROBOT_ADAPTER=mock 으로 mcp-robot-adapter 기동 — MockAdapter (§4.1)
  • tests/tools/fake-frigate.py 실행 가능 확인 (§4.2)
  • fake-spot gRPC 시뮬레이터 — Phase 1 진입 시 (§3 compose)
  • tests/tools/fake-tablet.html WSS 연결 — Phase 3 진입 시 (§4.3)

0.7 Phase 0 게이트 통과 (→ §6)

  • tests/integration/run-phase-0.sh — mosquitto + bridge + fake-frigate 부팅
  • [?] fake-frigate frigate/events 발행 → bridge가 vision/zone/enter로 변환·발행하는지 라이브 테일 확인
  • [?] CloudEvents envelope·traceparent가 메시지에 정상 부착됐는지 (MQTT_SCHEMA.md §1)

완료 기준: 로컬에서 mosquitto·HA·bridge가 떠 있고, fake-frigate 이벤트 한 건이 vision/zone/enter로 변환되어 버스에 흐르는 것을 mosquitto_sub로 확인할 수 있다.


1. 권장 개발 환경

항목 권장 사양
OS Ubuntu 22.04 / macOS 14+ / WSL2 Ubuntu
RAM 16GB 이상
CPU 4 코어 이상
GPU(Graphics Processing Unit, 그래픽 처리 장치) (옵션) Frigate/vision 검증 시 NVIDIA GPU 또는 USB Coral
Docker 24.0+ + Compose v2
Python 3.12
Node.js 20 LTS

2. 모노레포 클론 및 부트스트랩

git clone https://github.com/OWNER/zerone.git
cd zerone

# pre-commit 훅 설치
pip install pre-commit
pre-commit install

# Python 서비스 dev 의존성
cd services/orchestrator && uv sync --dev && cd ../..
cd services/bridge && uv sync --dev && cd ../..
cd services/mcp-robot-adapter && uv sync --dev && cd ../..

# Node.js 서비스
cd services/mcp-tablet-gateway && npm ci && cd ../..

# 태블릿 앱
cd apps/tablet && npm ci && cd ../..

3. 로컬 dev compose

deploy/docker-compose.yml은 운영용 핀(pin) 이미지를 사용한다. 개발 시에는 deploy/docker-compose.dev.yml overlay로 다음을 변경:

  • 자체 서비스를 image: 대신 build: 로 로컬 빌드.
  • 외부 카메라·로봇 자리에 mock 컨테이너 배치.
  • 환경변수에 LOG_LEVEL=debug.
  • 포트를 모두 localhost에 노출 (디버깅 편의).
# deploy/docker-compose.dev.yml
services:
  bridge:
    build: ../services/bridge
    image: zerone/bridge:dev
    environment:
      - LOG_LEVEL=debug

  orchestrator:
    build: ../services/orchestrator
    image: zerone/orchestrator:dev
    environment:
      - LOG_LEVEL=debug
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}

  mcp-robot-adapter:
    build: ../services/mcp-robot-adapter
    image: zerone/mcp-robot-adapter:dev
    environment:
      - ROBOT_ADAPTER=mock        # 핵심: 실 SPOT 대신 mock
      - LOG_LEVEL=debug

  mcp-tablet-gateway:
    build: ../services/mcp-tablet-gateway
    image: zerone/mcp-tablet-gateway:dev

  # mock 카메라 (Frigate 대체 또는 RTSP 시뮬레이션)
  fake-rtsp:
    image: linuxserver/ffmpeg:latest
    command: >
      -re -stream_loop -1 -i /assets/sample.mp4
      -c copy -f rtsp rtsp://0.0.0.0:8554/live
    volumes: [../tests/fixtures/video:/assets:ro]
    ports: ["8554:8554"]

  # mock SPOT (gRPC 시뮬레이터)
  fake-spot:
    build: ../tests/mocks/fake-spot
    ports: ["50051:50051"]

기동:

cd deploy
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build

4. Mock 어댑터 가이드

4.1 Mock SPOT 어댑터 — MockAdapter

mcp-robot-adapterROBOT_ADAPTER=mock 환경변수로 활성화. 다음 동작을 시뮬레이션:

capability 동작
goto 0.5 m/s 가정으로 위치 보간, 1Hz robot/{id}/state publish
follow 가상 사용자 위치를 일정 거리 유지
stop 즉시 stop, current_action=null
look_at yaw 변경, 1초 후 completed ack
gesture 2초 후 completed
# services/mcp-robot-adapter/src/adapter/adapters/mock.py (요지)
class MockAdapter(RobotAdapter):
    def __init__(self, robot_id: str):
        self.robot_id = robot_id
        self.pose = {"x": 0, "y": 0, "yaw": 0, "zone_id": "cafe"}
        self.battery = 100
        self.current_action = None

    async def execute(self, capability, params):
        if capability == "goto":
            asyncio.create_task(self._simulate_goto(params))
        ...
        return {"command_id": ulid.new().str, "status": "accepted"}

4.2 Mock Frigate 이벤트

실제 RTSP(Real Time Streaming Protocol, 실시간 스트리밍 프로토콜) 없이 frigate/events를 발행하는 작은 스크립트:

# tests/tools/fake-frigate.py
import json, paho.mqtt.client as mqtt, time, ulid

events = [
    {"type": "new", "after": {"id": ulid.new().str, "camera": "cafe_cam_01",
                              "label": "person", "score": 0.95,
                              "current_zones": ["cafe_zone"],
                              "entered_zones": ["cafe_zone"]}},
    # 5초 후 park 이동
    {"type": "update", "after": {"camera": "park_cam_01", ...}},
]

c = mqtt.Client(); c.connect("localhost", 1883)
for e in events:
    c.publish("frigate/events", json.dumps(e), qos=1)
    time.sleep(5)

실행:

python tests/tools/fake-frigate.py

4.3 Mock 태블릿 클라이언트

브라우저 기반 간단 WSS(WebSocket Secure, 보안 웹소켓) 클라이언트:

<!-- tests/tools/fake-tablet.html -->
<script>
  const ws = new WebSocket("ws://localhost:8080?token=DEV_TOKEN");
  ws.onmessage = (e) => console.log("RX:", JSON.parse(e.data));
  function selectOption(id) {
    ws.send(JSON.stringify({intent_type: "option_select", payload: {option_id: id}}));
  }
</script>
<button onclick="selectOption('drink_recommend')">커피 추천</button>

페어링 우회를 위해 mcp-tablet-gatewayDEV_MODE=true 환경변수 시 고정 토큰 DEV_TOKEN로 로그인 허용.


5. 단위 테스트

Python (orchestrator, bridge, mcp-robot-adapter)

cd services/orchestrator
uv run pytest -v --cov=src

# 가드레일 fuzz 테스트
uv run pytest tests/test_guardrail.py::test_reject_invalid_velocity -v

Node.js (mcp-tablet-gateway)

cd services/mcp-tablet-gateway
npm test

React Native (tablet-app)

cd apps/tablet
npm test
npm run e2e:ios   # detox iOS

6. 통합 테스트 — Phase 게이트

각 Phase 진입 전 검증할 시나리오. 모두 mock으로 가능. (로컬 환경을 처음 세우는 단계별 준비는 §0 참조.)

Phase 통합 테스트
0 mosquitto + bridge + fake-frigate → vision/zone/enter 발행 확인
1 + orchestrator + fake-spot → Claude tool call → MockAdapter 동작
2 + 실 SPOT (사무실 미러) — fake-frigate 유지
3 + tablet-app + fake-tablet HTML → 옵션 선택 round-trip
4 4 zone × 2 robot 동시 시나리오 (혼잡 시뮬레이션)
5 LLM(Large Language Model, 대규모 언어 모델) 단절 시 폴백 시나리오 4종 모두 발동

자동화: tests/integration/run-phase-N.sh 스크립트로 mock 환경 부팅 + 시나리오 실행 + assert.


7. 코드 품질 게이트 (CI 통과 기준)

검사 도구 기준
Python lint ruff check 0 violation
Python type mypy --strict 0 error
Python test pytest + coverage 통과 + coverage > 70%
TS lint eslint 0 error
TS type tsc --noEmit 0 error
TS test vitest / jest 통과
컨테이너 vuln Trivy CRITICAL/HIGH 0 (또는 명시적 ignore)
pre-commit trailing whitespace, large file 등 통과

8. 자주 막히는 지점 (Troubleshooting)

증상 원인 / 해결
orchestratorhost.docker.internal:8123 접근 실패 extra_hosts 누락 — compose에 host-gateway 매핑 확인
mosquitto에 connection refused passwd 파일 권한·uid 확인 (chown 1883:1883 passwd)
Frigate가 RTSP에서 stream 못 받음 ffprobe rtsp://... 로 컨테이너 밖에서 먼저 검증
bridgevision/zone/enter 발행 안 함 frigate/events 라이브 테일 확인 → ReID(Re-identification, 보행자 재식별) registry 매칭 실패 가능 (mock 토큰 사용 권장)
Claude tool call이 무한 반복 guardrail에서 거부 → orchestrator가 빈 응답으로 재시도 → 시스템 프롬프트에 "거부 시 종료" 명시
SPOT 시뮬레이터 인증 실패 bosdyn-client는 simulator의 bosdyn:bosdyn 기본 자격 사용 — .env.dev에 명시

9. 사무실 미러 환경 (Phase 2 진입)

전시장 진입 전 검증할 미니 환경:

  • 카메라 1대 (페어링·테스트용)
  • SPOT 1대 (사무실 평지)
  • 태블릿 1대
  • mosquitto/HA/orchestrator/bridge/robot-adapter/tablet-gateway 풀 스택

전시장 환경과의 차이를 tests/integration/MIRROR_DIFFS.md에 기록 → 차이가 위험을 만들지 않는지 검토.


10. 디버깅 도구

용도 도구
MQTT(Message Queuing Telemetry Transport, 메시지 큐 텔레메트리 전송 프로토콜) 라이브 테일 mosquitto_sub -h localhost -t '#' -v
trace_id 추적 Loki query `{service="orchestrator"}
Claude 호출 분석 LangSmith (선택) 또는 LOG_LEVEL=debug 시 stdout
HA entity 상태 http://localhost:8123 Developer Tools → States
컨테이너 ↔ 호스트 통신 nc -zv host.docker.internal 8123

Clone this wiki locally