아키텍처
Maekon은 **Hexagonal Architecture (Ports & Adapters)**를 따릅니다. 코어(maekon-core)가 모든 trait 와 도메인 모델을 정의하고, 다른 모든 crate 는 그 port 들을 구현하는 어댑터(adapter) 입니다.
워크스페이스 구조
clients/maekon-client/
├── src-tauri/ # Tauri v2 메인 바이너리 (패키지: maekon-app)
└── crates/
├── maekon-core # 95개 port trait + 34개 도메인 모델 + error code
├── maekon-network # JWT 인증, HTTP/SSE, gRPC, 배치 업로드
├── maekon-storage # SQLite (WAL) + 31개 마이그레이션 버전
├── maekon-monitor # 시스템 메트릭, 활성 윈도우, idle 감지
├── maekon-vision # 화면 캡처, 델타 인코딩, OCR, PII 필터
├── maekon-suggestion # SSE/gRPC 수신, 우선순위 큐, 피드백
├── maekon-automation # 정책 기반 명령 실행 + 감사 로그
├── maekon-analysis # LLM 세그먼트 요약, 벡터 RAG
├── maekon-embedding # INT8 양자화, 유사도 검색
├── maekon-audio # cpal 캡처 + Whisper STT
├── maekon-web # 로컬 Axum 대시보드 + React 프론트엔드
├── maekon-api-contracts # 공용 API 타입
├── maekon-sandbox-worker # 외부 프로세스 액션 실행기
└── maekon-lint # 워크스페이스 린트 도구 (스탠드얼론)
의존성 규칙
maekon-core ← 모든 어댑터 (단방향)
어댑터는 서로를 의존하지 않습니다. 모든 crate 간 통신은 maekon-core 에 정의된 trait 를 통해서만 이뤄집니다. 이것이 핵심 불변(invariant) 입니다 — ADR-001 §1 참조.
핵심 불변 조건
- 모든 port trait 는
&self사용 (&mut self아님). 가변 상태가 필요한 구현체는 내부 가변성(Mutex,RwLock,parking_lot)으로 해결합니다. - 모든 port 에
#[async_trait]—Arc<dyn Trait>DI 를 위해 필수입니다. - 수동 mock 구현 —
#[cfg(test)] mod tests안에 작성하며,mockall은 사용하지 않습니다. - 에러 전략: 라이브러리는
thiserror, 바이너리는anyhow. 모든 외부 에러는#[from]으로 wrap. - 모든
CoreErrorvariant 에 error code 필드 (ADR-019) — wire-format 계약이 41개 코드로 고정되어 있습니다.