TrendShift · 2026-05-23 · 13위

Multica 딥다이브 — 코딩 에이전트를 "팀원처럼" 관리하는 오픈소스 Linear 대안

"AI 에이전트를 쓰긴 쓰는데, 매번 프롬프트 복붙하고 결과 따라다니느라 정신없다"는 경험을 해본 적 있는가? Multica는 그 피로감을 정면으로 공격한다. Linear 같은 이슈 트래커의 UI에 에이전트를 정규 멤버로 등록해 — 이슈를 할당하면 알아서 코드를 쓰고, 댓글을 달고, 상태를 바꾼다. Next.js 16 + Go(Chi) + PostgreSQL pgvector로 만든 19.1k star 모노레포로, 셀프호스팅까지 한 큐에 끝낸다.

0먼저, "managed agents platform"이 뭐길래

에이전트를 부르는 방식이 "프롬프트 입력"에서 "이슈 할당"으로 바뀐다.

용어
managed agents platform (관리형 에이전트 플랫폼)
여러 명의 AI 코딩 에이전트를 마치 사람 팀원처럼 한 보드에서 관리하는 시스템. 사람 멤버에게 이슈를 던지듯 에이전트에게 이슈를 던지면, 에이전트가 자기 차례에 그 일을 받아 실행하고, 진행 상황을 댓글로 남기고, 막히면 막혔다고 보고한다. Multica는 "1인 개발자 + 5명의 AI 에이전트"라는 새로운 팀 구성을 전제로 설계됐다.
비유로 이해하기

기존 방식은 부엌에서 요리사 한 명이 칼을 들고 모든 재료를 직접 손질하는 모습이다. AI 에이전트는 매번 "이거 해줘", "저거 해줘"를 들고 와서 결과를 받아오는 도제 같다. 도제가 늘어도, 도제마다 매번 같은 설명을 반복해야 한다.

Multica는 그 부엌을 레스토랑 주방의 티켓 시스템으로 바꾼다. 주문(이슈)이 칠판에 붙으면, 각자 자기 자리에 있던 요리사(에이전트)가 자기 담당 티켓을 떼서 만들고, 완성되면 다시 칠판에 "완료"를 표시한다. 셰프(사람)는 칠판만 보면서 막힌 티켓이나 위험한 결정만 처리한다. 사람과 에이전트가 같은 보드에서 같은 언어로 일한다.

용어
agent daemon (에이전트 데몬)
사용자의 로컬 기계에서 백그라운드로 도는 multica daemon 프로세스. 머신의 PATH에서 claude, codex, copilot, opencode, hermes, gemini, pi, cursor-agent, kimi, kiro-cli 같은 CLI를 자동 탐지해서 Multica 서버에 "이 머신은 이런 에이전트를 돌릴 수 있어"라고 등록한다. 서버에서 누가 이슈를 그 에이전트에게 할당하면, 데몬이 그 작업을 받아 격리된 워크스페이스 디렉토리에서 에이전트 CLI를 띄운다.
용어
pgvector
PostgreSQL의 확장으로, 벡터 임베딩을 한 컬럼에 저장하고 코사인 유사도로 검색할 수 있게 해 준다. Multica는 표준 Postgres 17 이미지가 아니라 pgvector/pgvector:pg17를 도커 컴포즈에 박아 둔다 — 이슈, 댓글, 스킬 같은 텍스트를 벡터로 만들어 의미 검색(semantic search)을 하기 위함이다.

1프로젝트 한줄 요약

이 레포의 본질을 압축하면.

핵심 메시지

"Linear의 보드에 사람 팀원 옆자리로 AI 에이전트를 정식으로 앉히고,
이슈를 할당하면 그가 알아서 일하게 만드는 오픈소스 플랫폼."

Multica는 Next.js 16 + Go(Chi) + PostgreSQL 17 + pgvector로 만든 팀 단위 코딩 에이전트 운영 인프라다. 웹/데스크탑/모바일 세 가지 클라이언트와, 로컬에서 도는 multica daemon으로 구성된다. 데몬은 머신의 claude, codex, copilot, opencode, hermes, gemini, pi, cursor-agent 같은 CLI를 자동 탐지해 "이 머신은 이런 에이전트를 돌릴 수 있어"라고 서버에 보고한다.

핵심 컨셉은 "AI 에이전트를 1급 시민(first-class citizen)으로". 보드에 사람 멤버처럼 아바타가 뜨고, 댓글에 보라색으로 표시되며, multica issue assign --to "Lambda" 한 줄로 "사람 vs 봇"을 똑같이 할당할 수 있다. 벤더 중립적(Claude·Codex·Copilot 어느 쪽이든 동등하게), 셀프호스팅 가능(GHCR 이미지 + 도커 컴포즈), 오픈소스(라이선스 명시). 19.1k stars, 2.3k forks, 156 issues, 133 PRs — 단순한 사이드 프로젝트 규모가 아니다.

2왜 Multica가 트렌딩에 올랐나

TrendShift 13위 — "여러 코딩 에이전트를 어떻게 효율적으로 굴리지?"라는 2026년의 새로운 질문

2024~2025년이 "Claude Code, Codex, Cursor 중에 뭐가 제일 좋아?"의 시대였다면, 2026년은 다른 질문이 들어왔다 — "여러 개를 동시에, 한 사람이, 어떻게 굴리지?" 인간 한 명이 하루에 다룰 수 있는 컨텍스트 스위치 수는 제한돼 있는데, AI 에이전트는 무한히 병렬화될 수 있다. 병목이 사람 쪽으로 옮겨 왔다.

Multica의 슬로건 "Your next 10 hires won't be human"은 이 분위기를 그대로 캐치한 마케팅 카피다. "다음 10명의 직원은 사람이 아닐 것이다" — 즉, 인사 관리(HR)에 가까운 추상화를 코드 에이전트에도 적용하자는 발상이다.

경쟁 도구 대비 차별점

맥락
Linear 출신 디자인 감수성

스크린샷을 보면 Linear/Notion/Plane 계열의 미니멀한 보드 UI. shadcn/ui(BaseUI 변형) + Tailwind 4 조합으로 동시대 SaaS 사이트와 같은 톤을 유지한다. packages/ui/components.json"base-nova style"을 명시.

3기술 스택 전체 지도

백엔드(Go), 프론트엔드(Next.js·Electron·React Native), 인프라(도커·pgvector) 한눈에.

백엔드 — Go가 메인, sqlc가 SQL을 타입으로 묶는다

용어
sqlc
Go에서 가장 인기 있는 ORM 대안 도구. ORM(예: GORM)이 Go 코드로 SQL을 "생성"한다면, sqlc는 거꾸로다 — 개발자가 진짜 SQL 쿼리(server/pkg/db/queries/)를 직접 쓰면, sqlc가 그 SQL을 분석해 타입 안전한 Go 함수를 자동 생성한다. make sqlc가 그 코드 생성 명령. "SQL이 1급, Go는 그걸 호출하는 얇은 래퍼"라는 철학.
레이어스택역할
HTTP 라우터chiGo의 경량 라우터(미들웨어 체이닝). middleware.Recoverer가 panic을 500으로 변환.
DB 액세스sqlcSQL → 타입 안전한 Go 함수 자동 생성. ORM 없이 raw SQL을 직접 작성.
실시간gorilla/websocket이슈 변경/댓글 추가를 WS로 브로드캐스트. 폴링 없이 보드가 자동 갱신.
DB 엔진pgvector/pgvector:pg17PostgreSQL 17 + pgvector. 벡터 컬럼 + 코사인 거리 검색.
CLI 빌드goreleasertag 푸시 → GitHub Actions가 멀티 플랫폼 바이너리 빌드 + Homebrew tap 자동 publish.
이메일Resend인증 코드/알림 메일 전송(자체 SMTP 없이).
OAuthGoogle워크스페이스 로그인. 자기 도메인으로 redirect URI 설정 가능.
업로드 저장S3 + CloudFront 또는 backend_uploads 볼륨이슈 첨부파일·아바타. CloudFront 키페어로 서명된 URL.

프론트엔드 — pnpm + Turborepo 모노레포, 세 가지 클라이언트가 같은 코어를 공유

용어
pnpm workspaces + Turborepo
pnpm-workspace.yaml이 모노레포 안의 패키지 목록을 정의하고, Turborepo가 패키지 간 의존성을 분석해 필요한 것만 빌드/테스트한다(증분 캐시). turbo build --filter=@multica/web처럼 특정 패키지만 골라 돌릴 수 있다. Multica는 pnpm@10.28.2 핀(catalog 기능 사용)으로 모든 패키지가 같은 React 버전을 쓰도록 강제한다.
패키지/앱스택역할
apps/web/Next.js 16 (App Router) + React 19.2웹 클라이언트. next/navigation만 여기에 허용.
apps/desktop/Electron + electron-vite데스크탑 앱. React Router DOM은 여기에만.
apps/mobile/Expo SDK 55 + React Native 0.83 (iOS)모바일 — 의도적으로 메인 카탈로그와 분리(Expo의 React 버전이 6~12개월 지연).
apps/docs/(MDX) Docusaurus/Fumadocs 계열문서 사이트. 변환 컨벤션 sourcing.
packages/core/TanStack Query + Zustand헤드리스 비즈니스 로직. react-dom·localStorage 직접 사용 금지.
packages/ui/shadcn/ui (BaseUI 변형, base-nova style) + Tailwind 4원자 단위 UI 컴포넌트. @multica/core import 금지.
packages/views/React (Next/React Router 비의존)비즈니스 페이지/컴포넌트. NavigationAdapter로만 라우팅.
테스트Vitest + Playwright패키지별 Vitest. e2e/에서 Playwright로 실제 브라우저 시나리오.
아키텍처 룰
패키지 경계는 컴파일러보다 사람이 지켜야 한다

CLAUDE.md가 한 페이지를 통째로 "이 패키지는 저걸 import 하지 말라"는 규칙에 할애한다. 위반 시 컴파일 오류는 안 나지만, 모바일과 데스크탑의 호환성이 깨진다. 예: packages/views/next/navigation을 import 하는 순간, 그 컴포넌트는 데스크탑에서 더 이상 쓸 수 없게 된다.

인프라 — Docker Compose 3컨테이너로 끝

컨테이너이미지역할
postgrespgvector/pgvector:pg17이슈/유저/벡터. healthcheck로 backend가 기다림.
backendghcr.io/multica-ai/multica-backend:latestGo 서버. backend_uploads 볼륨에 첨부.
frontendghcr.io/multica-ai/multica-web:latestNext.js standalone(서버컴포넌트 포함).

도커 컴포즈 파일이 세 종류로 분리돼 있다. docker-compose.yml(개발 모드), docker-compose.selfhost.yml(GHCR 이미지로 운영), docker-compose.selfhost.build.yml(로컬에서 직접 빌드해서 운영). 각자 용도가 다르므로 잘못 띄우면 GHCR 풀이 안 되는 등의 함정에 빠질 수 있다.

4아키텍처 심화 분석

데몬-서버-프론트 3축이 어떻게 맞물려 돌아가는지 그림으로.

전체 시스템 구조도

┌──────────────────────────────────────────────────────────────────────┐
│                       사용자의 로컬 머신 (Mac/Linux/Win)             │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │  multica daemon (Go 바이너리, 백그라운드)                │       │
│  │   ├─ PATH 스캔 → claude/codex/copilot/opencode/...       │       │
│  │   ├─ poll loop (3s)   ──→  GET /tasks?status=claimed     │       │
│  │   ├─ heartbeat (15s)  ──→  PUT /runtimes/:id/heartbeat   │       │
│  │   └─ task exec        ──→  spawn(claude|codex) in        │       │
│  │                              ~/multica_workspaces/<id>/  │       │
│  └──────────────────────────────────────────────────────────┘       │
│                              │ HTTPS + WS                            │
└──────────────────────────────│───────────────────────────────────────┘
                               │
        ┌──────────────────────┴────────────────────────┐
        │                                               │
        ▼                                               ▼
┌────────────────────┐        ┌──────────────────────────────────────┐
│   Next.js 16       │        │     Go Backend (Chi + gorilla/ws)    │
│   apps/web         │◄──WS──►│  ┌────────────────────────────────┐  │
│   (Vercel/         │        │  │ HTTP handlers (REST + WS)      │  │
│    GHCR image)     │        │  │  ├─ /issues  ─ assign/comment  │  │
│                    │        │  │  ├─ /agents  ─ register/list   │  │
│                    │        │  │  ├─ /runtimes ─ heartbeat      │  │
│                    │        │  │  └─ /ws       ─ realtime fanout│  │
│                    │        │  └────────────────────────────────┘  │
│  TanStack Query    │        │  ┌────────────────────────────────┐  │
│   (server state)   │        │  │ sqlc (raw SQL → typed Go)      │  │
│  Zustand           │        │  └────────────────────────────────┘  │
│   (client state)   │        │              │                       │
└────────────────────┘        └──────────────│───────────────────────┘
        ▲                                    ▼
        │                            ┌──────────────────┐
   Electron / Expo                   │ Postgres 17 +    │
   (같은 packages/core 재사용)       │   pgvector       │
                                     │  (벡터 검색)     │
                                     └──────────────────┘

핵심 설계 패턴 1: Internal Packages — "사전 컴파일 없이 raw .ts 그대로 export"

일반적인 모노레포에서 packages/core는 빌드해서 dist/를 만들고, 그걸 다른 패키지가 import 한다. Multica는 그 단계를 통째로 생략한다. packages/core.ts 원본을 그대로 export하고, 그걸 import 한 앱(apps/web)의 번들러(Next.js의 Turbopack)가 직접 컴파일한다.

왜 이렇게 하나
HMR 0설정 + go-to-definition 즉시 작동

packages/core의 한 줄을 고치면 별도 빌드 단계 없이 즉시 apps/web에 반영된다. 또 IDE의 "go to definition"이 컴파일된 .d.ts가 아니라 진짜 소스로 점프한다 — 디버깅이 훨씬 쾌적해진다.

핵심 설계 패턴 2: 상태 분리 룰 — "서버 상태는 TanStack Query, 클라이언트 상태는 Zustand"

용어
TanStack Query (구 React Query)
서버에서 가져온 데이터(이슈 목록, 유저, 워크스페이스 등)를 캐시하고, 백그라운드에서 신선도 유지(stale-while-revalidate)를 자동으로 해 주는 라이브러리. Multica의 "서버에서 온 모든 것은 여기에만 산다"는 룰의 주인공.
용어
Zustand
아주 가벼운 클라이언트 상태 관리 라이브러리. Redux보다 보일러플레이트가 훨씬 적다. Multica는 UI 선택/필터/드래프트/모달 상태처럼 서버와 무관한 클라이언트 전용 상태에만 사용한다.

이게 왜 중요한가? 둘을 섞으면 같은 데이터의 두 가지 진실이 생긴다. 서버에서 받은 이슈를 Zustand에 복사해 두면, WS로 다른 사람이 이슈 제목을 바꿀 때 Zustand 쪽은 안 갱신된다. 다음 새로고침 전까지 사용자는 옛 제목을 본다. CLAUDE.md가 이 점을 4번 반복해서 강조한다.

핵심 설계 패턴 3: API 응답 호환성 — "데스크탑 앱은 자기보다 신버전 서버를 만난다"

실 사례
이슈 #2143, #2147, #2192 — 백엔드 응답이 살짝 바뀐 것만으로 데스크탑 앱이 흰 화면이 됐다

웹 앱은 한 줄 고쳐서 배포하면 끝나지만, 사용자 PC에 설치된 데스크탑 앱은 한참 이전 버전이다. 그 사이 백엔드는 0.2.26 → 0.3.x → 0.4.x로 굴러간다. 응답 필드 하나가 사라지거나, enum에 새 값이 추가되거나, 배열이 null로 오면 — 예전 버전의 데스크탑 클라이언트는 그대로 죽는다.

해결책은 parseWithFallback(schema, body). 모든 API 응답을 zod 스키마로 검증하고, 실패하면 명시적 fallback 값을 반환한다. UI로 예외가 던져지지 않는다. 게다가 enum에 새 값이 들어와도 switch가 그걸 모르면 그냥 generic fallback 렌더링을 한다. "드리프트는 다운그레이드, 크래시 아님"이 룰.

핵심 설계 패턴 4: 폴리모픽 assignee — 사람과 에이전트가 같은 슬롯

-- issues 테이블 (개념적으로)
CREATE TABLE issues (
  id           uuid PRIMARY KEY,
  workspace_id uuid REFERENCES workspaces,
  title        text,
  assignee_type text CHECK (assignee_type IN ('member','agent')),
  assignee_id   uuid,   -- members.id 또는 agents.id, 양쪽 다 가리킬 수 있음
  status       text,    -- 'backlog'|'todo'|'in_progress'|'in_review'|'done'|'blocked'|'cancelled'
  ...
);

이 두 필드의 조합이 Multica를 Linear에서 갈라놓는 핵심이다. UI는 assignee_type === 'agent'일 때 보라색 배경 + 로봇 아이콘으로 렌더링하고, 댓글에서도 같은 시각 차별이 유지된다. "이슈를 누가 처리하는가"라는 모델이 자연스럽게 양쪽을 포괄한다.

핵심 설계 패턴 5: 워크스페이스 격리 + Worktree 지원 — "여러 체크아웃이 한 DB 컨테이너를 공유"

Git worktree로 같은 레포의 여러 브랜치를 동시에 체크아웃해서 개발할 때, 각 워크트리마다 별도의 DB가 필요하다. Multica는 한 PostgreSQL 컨테이너 + DB 이름으로만 격리한다. make worktree-env.env.worktree를 만들어 고유한 POSTGRES_DB·PORT를 부여한다.

5디렉토리 구조 해부

루트에서 시작해서 어디에 무엇이 있는지 한 바퀴 돈다.

multica/
├─ apps/                 ← 클라이언트 앱들
│   ├─ web/              Next.js 16 (App Router) — 웹 클라이언트
│   ├─ desktop/          Electron (electron-vite) — 데스크탑 앱
│   ├─ mobile/           Expo / React Native — iOS (별도 React 버전 정책)
│   └─ docs/             공식 문서 사이트 (MDX 콘텐츠)
│
├─ packages/             ← 공유 코드 (pnpm workspace + Turborepo)
│   ├─ core/             헤드리스 비즈니스 로직 (zero react-dom)
│   │   ├─ platform/     CoreProvider · API 클라이언트 · WS 연결
│   │   ├─ api/          zod 스키마 + parseWithFallback (API 호환성 방어)
│   │   ├─ auth/         인증 도메인 (store.ts 포함)
│   │   ├─ workspace/    워크스페이스 도메인 (store.ts 포함)
│   │   └─ paths/        reserved-slugs.ts (서버 JSON에서 자동 생성)
│   ├─ ui/               shadcn/ui 컴포넌트 (BaseUI 기반, base-nova style)
│   │   ├─ components/ui/ Button, Badge, Input, ... (`pnpm ui:add`로 추가)
│   │   └─ styles/        Tailwind 디자인 토큰 / 전역 CSS
│   ├─ views/            비즈니스 페이지/컴포넌트 (Next/Router 비의존)
│   │   ├─ layout/       DashboardGuard, WorkspaceRouteLayout
│   │   ├─ platform/     DragStrip, AppLink, NavigationAdapter 인터페이스
│   │   └─ locales/      i18n 번역 (한/영/중...)
│   └─ tsconfig/         공통 TS 설정 베이스
│
├─ server/               ← Go 백엔드
│   ├─ cmd/              binary entry points (server, daemon, multica CLI)
│   ├─ internal/handler/ HTTP 핸들러 + reserved_slugs.json (단일 진실)
│   ├─ internal/util/    ParseUUID, MustParseUUID, ...
│   └─ pkg/db/queries/   raw SQL (sqlc가 여기서 Go 코드 생성)
│
├─ e2e/                  ← Playwright E2E 시나리오 (실제 백엔드 띄우고 돌림)
├─ docker/               ← 자체 빌드용 Dockerfile 변형들
├─ scripts/              ← install.sh, install.ps1, generate-reserved-slugs.mjs
│
├─ docker-compose.yml                개발 모드(로컬 빌드)
├─ docker-compose.selfhost.yml       프로덕션(GHCR 이미지)
├─ docker-compose.selfhost.build.yml 프로덕션(로컬 빌드)
├─ Dockerfile / Dockerfile.web       각각 backend / web 멀티 스테이지
│
├─ Makefile              ← make dev / make server / make sqlc 등의 단일 진입점
├─ AGENTS.md             ← AI 에이전트(Claude/Codex/...) 컨텍스트
├─ CLAUDE.md             ← Claude Code 전용 코드베이스 가이드 (위에서 다 봤음)
├─ CLI_AND_DAEMON.md     ← 데몬·CLI 사용자 매뉴얼
├─ SELF_HOSTING.md       ← 셀프호스팅 단계별 가이드
├─ SELF_HOSTING_AI.md    ← AI 에이전트가 셀프호스팅 도울 때 가이드
├─ skills-lock.json      ← Claude Code 스킬 잠금 (재현 가능 환경)
└─ .goreleaser.yml       ← CLI 릴리즈 자동화 (Homebrew tap publish 포함)
읽기 좋은 포인트
"단일 진실(Source of Truth)" 패턴이 반복된다

코딩 컨벤션 문서는 apps/docs/content/docs/developers/conventions.mdx 하나, 예약 슬러그는 server/internal/handler/reserved_slugs.json 하나, 의존성 버전은 pnpm-workspace.yamlcatalog: 한 곳. 한 정보는 한 곳에만 있고, 다른 곳은 자동 생성된다(스크립트가 검증해 CI에서 drift를 잡음).

6학습 포인트 — 기술별로 무엇을 배울 수 있는가

Multica를 코드로 따라가면 어떤 기술이 손에 들어오는가.

1) Go + Chi + sqlc — "ORM 없는 백엔드"의 모범 답안

최근 Go 진영의 트렌드는 ORM(GORM)에서 sqlc/sqlx로의 이동이다. SQL을 숨기는 대신 SQL을 1급 시민으로 다루고, Go는 그걸 호출하는 얇은 래퍼만 만든다. Multica를 따라가면:

실습 아이디어: server/internal/handler/reserved_slugs.json에 새 슬러그를 추가하고 pnpm generate:reserved-slugs가 TS 쪽을 어떻게 갱신하는지 추적.

2) Next.js 16 App Router + Electron 멀티 클라이언트

같은 React 코드가 웹과 데스크탑 양쪽에서 동작하게 만드는 게 얼마나 까다로운지 체감할 수 있다. 핵심은 NavigationAdapter로 라우팅을 추상화하는 것 — 웹은 next/navigation으로, 데스크탑은 react-router-dom으로, 같은 인터페이스를 구현한다.

3) TanStack Query + Zustand — 서버/클라이언트 상태 분리 모범

이 둘을 같이 쓰는 코드베이스는 많지만, "언제 무엇을 어디에 둘지"의 룰을 명문화한 곳은 드물다. CLAUDE.md 한 섹션이 통째로 이 룰에 할애돼 있다 — 서버에서 온 데이터는 절대 Zustand에 복사하지 않고, WS 이벤트는 스토어를 직접 쓰는 대신 쿼리 캐시를 무효화한다 등.

4) shadcn/ui + Tailwind 4 — 디자인 토큰 거버넌스

shadcn/ui는 라이브러리가 아니라 "코드를 복사해서 자기 프로젝트에 두는" 방식이다. Multica는 그걸 packages/ui/components/ui/에 모아 두고, 모든 앱이 이 한 곳에서 import 한다. pnpm ui:add badge 한 줄로 새 컴포넌트가 추가된다.

5) PostgreSQL pgvector — 의미 검색을 RDB로

벡터 DB(Pinecone, Weaviate, Qdrant)를 따로 띄우지 않고 PostgreSQL 한 컨테이너로 의미 검색을 처리하는 패턴. Multica는 이슈/댓글/스킬 같은 텍스트 데이터에 임베딩을 붙여 "이슈 비슷한 거 찾아줘" 같은 검색을 한다. 학습 목표: vector(384) 컬럼 정의, embedding <=> query_embedding 코사인 거리, HNSW 인덱스.

6) Goreleaser + GitHub Actions + Homebrew tap

다음 흐름이 자동화돼 있다:

git tag v0.x.x  →  git push --tags
                       │
                       ▼
            GitHub Actions (release.yml)
                       │
       ┌───────────────┼───────────────┐
       ▼               ▼               ▼
   Go test 통과   Goreleaser 빌드      Homebrew tap
                  (멀티 플랫폼)        업데이트
                       │
                       ▼
              GitHub Releases에 publish
                  (.tar.gz, .zip)

이 한 줄짜리 흐름을 직접 구성해 보는 게 GitOps/CI 학습의 1단계로 아주 적합하다.

7) "AI 친화 코드베이스"라는 새로운 미덕

레포 루트의 AGENTS.md, CLAUDE.md, skills-lock.json은 단순한 문서가 아니라 AI 에이전트가 이 레포에서 길을 잃지 않도록 의도적으로 배치한 가이드 파일이다. 2026년의 새 표준 — "사람용 README" + "AI용 AGENTS.md"가 짝을 이룬다. Claude Code/Codex/Cursor가 자동으로 이 파일을 우선 로드한다.

7하드웨어/시스템 요구사항

셀프호스팅과 개발 두 가지 시나리오로 정리.

개발(Contributor)용

셀프호스팅(운영) 최소 사양

에이전트 데몬용

주의
JWT_SECRET을 반드시 바꿀 것

도커 컴포즈 기본값은 change-me-in-production이다. 그대로 띄우면 토큰 위조가 가능하다. .envJWT_SECRET을 32바이트 이상 랜덤 문자열로 반드시 바꾼다.

8직접 해볼 수 있는 실습 과제

난이도별로 5개.

★☆☆☆☆ — 1단계: 클라우드로 5분 만에 첫 에이전트 굴려보기

  1. brew install multica-ai/tap/multica로 CLI 설치
  2. multica setup 한 줄 → 브라우저 로그인 → 데몬 자동 시작
  3. Claude Code가 설치돼 있다면(which claude) 자동 탐지됨
  4. 웹 대시보드에서 "New Agent" → "Lambda" 같은 이름 부여
  5. 이슈 생성 + 그 에이전트에게 할당 → 보드에서 진행 상황 실시간 관찰

★★☆☆☆ — 2단계: 셀프호스팅으로 도커 컴포즈 띄우기

  1. 레포 클론, cp .env.example .env
  2. .envJWT_SECRETopenssl rand -hex 32로 갱신
  3. docker compose -f docker-compose.selfhost.yml up -d
  4. http://localhost:3000에서 첫 워크스페이스 생성
  5. CLI를 self-host 모드로 설정: multica setup self-host

★★★☆☆ — 3단계: 두 개의 에이전트가 같은 이슈에서 협업하게 하기

  1. 같은 데몬에 Claude Code + Codex를 동시 등록(둘 다 PATH에 있게)
  2. 두 개의 에이전트 만들기 — "Lambda(Claude)", "Sigma(Codex)"
  3. 이슈 A를 Lambda에게 → Lambda가 코드 작성 → in_review로 옮김
  4. 같은 이슈를 Sigma에게 재할당 → Sigma가 코드 리뷰 → 댓글 작성
  5. 두 에이전트의 댓글이 같은 보드에 어떻게 보이는지 관찰

★★★★☆ — 4단계: Autopilot으로 매일 아침 9시 자동 트리아지

  1. multica autopilot create --title "Daily triage" --agent "Lambda" --mode create_issue
  2. multica autopilot trigger-add <id> --cron "0 9 * * 1-5" --timezone "Asia/Seoul"
  3. 이렇게 하면 평일 아침 9시(KST)에 자동으로 이슈가 생성되고 Lambda에게 할당됨
  4. Lambda는 자기 프롬프트(예: "Backlog 이슈를 훑어보고 우선순위 정렬")를 따라 작업 시작
  5. multica autopilot runs <id>로 실행 이력 추적

★★★★★ — 5단계: 자신의 회사용 셀프호스팅 인스턴스에 SSO + S3 + 도메인 붙이기

  1. Google Workspace SSO 연결 — .envGOOGLE_CLIENT_ID/SECRET/REDIRECT_URI
  2. ALLOWED_EMAIL_DOMAINS=mycompany.com으로 사내 이메일만 가입 허용
  3. 업로드 백엔드를 S3로 — S3_BUCKET, S3_REGION, CloudFront 키페어
  4. Caddy/Nginx 리버스 프록시로 https://multica.mycompany.com + 무료 Let's Encrypt
  5. 회사 모든 개발자의 머신에 multica setup self-host --server-url ...로 일괄 설정

9관련 기술 심화 학습 로드맵 — 6주 코스

"Multica를 이해할 수 있을 정도"가 되기 위한 주차별 학습 순서.

1주차 — Go 기초 + Chi 라우터

2주차 — PostgreSQL + sqlc

3주차 — Next.js 16 App Router + TanStack Query

4주차 — Zustand + shadcn/ui + Tailwind 4

5주차 — 실시간성 + WebSocket

6주차 — 도커 컴포즈 + 셀프호스팅 운영

학습 팁
Multica의 CLAUDE.md를 끝까지 정독하라

이 한 파일에 모노레포 운영 노하우의 70%가 들어 있다. 패키지 경계, 상태 분리 룰, API 호환성 룰, 핸들러의 UUID 처리 룰 등. 실무에서 한 번씩 사고가 난 뒤에야 추가된 항목들이라 진짜 가치 있다.

10핵심 키워드 사전

Multica를 읽다가 자주 부딪히는 용어 모음.

용어
Runtime (런타임)
에이전트 작업을 실행할 수 있는 환경의 추상화. 사용자 로컬 머신(데몬을 통해)이거나 클라우드 인스턴스. 각 런타임은 자기가 어떤 에이전트 CLI(claude, codex, ...)를 갖고 있는지 보고하고, Multica 서버는 그에 맞춰 작업을 라우팅한다.
용어
Skill (스킬)
에이전트가 해결한 문제를 재사용 가능한 절차로 남긴 것. "PostgreSQL 마이그레이션 만드는 법", "이 서비스 배포하는 법" 같은 것. skills-lock.json이 그 모음의 잠금 파일이다(npm의 package-lock과 비슷). 시간이 갈수록 팀 전체의 능력으로 누적됨.
용어
Issue Key (예: MUL-123)
사람이 기억하기 좋은 이슈 식별자. UUID는 길고 외우기 어려우니 {workspace 접두사}-{번호} 포맷. CLI에서 multica issue get MUL-123처럼 쓴다. 백엔드는 이 키를 받으면 loader 함수로 UUID로 변환한다(이슈 #1661의 교훈).
용어
Profile (프로필)
CLI 설정의 격리 단위. --profile staging으로 staging 서버와 별도 설정·데몬·기본 워크스페이스를 가질 수 있다. 같은 머신에서 회사용 + 개인용 Multica를 둘 다 굴릴 수 있다.
용어
Autopilot (오토파일럿)
스케줄/트리거로 자동 실행되는 에이전트 작업. 크론 표현(0 9 * * 1-5)으로 평일 9시 자동 실행 가능. create_issue 모드는 매 실행마다 새 이슈를 만들고 에이전트에게 할당한다.
용어
Metadata (이슈 메타데이터)
이슈 하나에 붙는 작은 KV 맵. 최대 50키, 8KB. 에이전트가 파이프라인 상태(pr_number=482, pipeline_status=waiting_review)를 추적할 때 쓴다. CLI에서 multica issue metadata set/get/list/delete로 조작.
용어
GC (Garbage Collection, 워크스페이스 정리)
데몬이 ~/multica_workspaces/를 주기적으로 스캔해 완료/취소된 이슈의 작업 디렉토리를 지우고, node_modules 같은 재생성 가능 산출물을 솎아내는 기능. MULTICA_GC_TTL=24h 같은 환경변수로 튜닝. 디스크가 끝없이 차오르는 걸 막는다.
용어
Heartbeat (하트비트)
데몬이 15초마다 서버로 보내는 "나 살아있어" 신호. 서버는 일정 시간 하트비트가 없으면 그 런타임을 비활성으로 표시하고, 새 작업을 라우팅하지 않는다.
용어
Optimistic Mutation (낙관적 변경)
서버 응답을 기다리지 않고 UI를 먼저 바꾸는 패턴. TanStack Query의 onMutate로 캐시를 미리 갱신 → 서버 호출 → 실패 시 롤백, 성공 시 invalidate. Multica는 "변경은 기본적으로 낙관적"이라는 룰로 사용자가 서버를 기다리지 않게 한다.
용어
Reserved slug (예약 슬러그)
워크스페이스 이름으로 쓸 수 없는 단어 목록(login, workspaces, inbox...). Multica는 이 목록을 server/internal/handler/reserved_slugs.json 한 곳에 두고, TS 쪽 코드는 generate-reserved-slugs.mjs로 자동 생성한다. CI가 drift를 검출.
손을 움직일 차례

지금 당장, 30분 안에 첫 에이전트가 일하게 만드는 가장 빠른 경로

  1. CLI 설치: brew install multica-ai/tap/multica (Mac/Linux) 또는 PowerShell의 irm | iex 1줄(Windows)
  2. 한 줄 설정: multica setup — 브라우저 로그인, 워크스페이스 자동 발견, 데몬 자동 시작이 동시에 일어남
  3. Claude Code 확인: which claude가 어떤 경로를 출력하면 데몬이 자동 탐지함. 없다면 먼저 Claude Code부터 설치
  4. 데몬 상태 확인: multica daemon status — "Lambda" 같은 런타임이 등록돼 있어야 함
  5. 첫 에이전트 생성: 웹 대시보드 → Settings → Agents → "New Agent" → 자기 런타임 + Claude Code 선택
  6. 첫 이슈 할당: 보드에서 이슈 생성 → 그 에이전트에게 할당 → 보드의 진행 상황을 실시간으로 본다
  7. 다음 단계: multica autopilot으로 정기 작업을 만들거나, --profile staging으로 다른 인스턴스를 동시 운영

11참고 링크

바로 가서 더 깊이 파고들 수 있는 곳들.

이 문서는 2026-05-23 기준으로 multica-ai/multica 레포의 README, CLAUDE.md, CLI_AND_DAEMON.md, package.json, docker-compose.selfhost.yml, 그리고 TrendShift 페이지를 직접 읽고 정리한 한국어 학습 자료다. Multica는 활발히 개발 중이므로 일부 세부사항(버전, 명령어 플래그)은 변할 수 있다.

아키텍처 결정의 "왜"가 궁금하면 무조건 CLAUDE.md의 후반부(API Response Compatibility, Backend Handler UUID Parsing Convention, Package Boundary Rules)를 정독하길 권한다. 같은 사고를 한 번이라도 겪어 본 사람이 쓴 글이라 그 가치가 다르다.