본문으로 건너뛰기
5분 AI.
GITHUB TRENDING RUST WEEKLY #5 딥다이브 · 2026-10-23 분석

OpenBitFun 딥다이브
— 대화창 뒤에서 일을 이어 가는 Rust 에이전트 작업실

에이전트 앱

빠른 판단

무엇
모델·파일·터미널·승인·세션 복구를 Rust 실행 엔진과 데스크탑·CLI·원격 화면으로 묶은 에이전트 앱
이럴 때
여러 기기에서 코드·문서 작업을 이어가며 도구 실행 승인과 작업 기록·복구를 관리할 때
메시지를 보내면 파일을 읽고, 도구를 호출하고, 승인을 기다렸다가 다시 일하는 AI 작업실입니다. Rust 실행 계층 위에 React 화면과 Tauri 데스크톱이 올라가고, CLI·원격 제어·Mini App으로 확장됩니다. 이 글은 기능 목록보다 하나의 요청이 실행·상태·이벤트·권한 경계를 통과하는 과정을 따라갑니다. 저장소 GCWing/OpenBitFun · 스타 3,099 · 포크 278 · 주 언어 Rust · MIT · 2026-10-23 GitHub 기준. 코드 설명은 커밋 8c012e4 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

화면·모델·도구 사이에서 작업의 생명주기를 관리하는 프로그램

OpenBitFun은 Rust 기반 에이전트 실행 계층을 여러 사용 화면으로 제공하는 오픈소스 작업 환경입니다. 모델과 대화하는 기능에 파일·터미널·검색·승인·세션 저장·원격 연결을 묶습니다. README는 코드 작성 밖의 일반 업무와 Mini App 제작까지 제품의 범위로 설명합니다.

이 저장소에서 배울 핵심은 모델을 호출하는 방법보다, 모델이 시작한 일을 사람이 통제하며 이어 가게 만드는 방법입니다.

한 문장 비유

모델이 작업자라면, OpenBitFun은 작업대·작업 일지·공구함을 갖춘 작업실입니다

작업자는 다음 행동을 제안합니다. 작업실은 어떤 파일을 읽을 수 있는지 확인하고, 필요한 공구를 건네며, 진행 상황을 기록합니다. 작업자가 “벽을 뚫자”고 말했다고 바로 드릴을 켜면 안 되듯, 도구 요청과 실행 허가는 별도로 다뤄야 합니다.

휴대전화는 멀리서 보는 제어판에 가깝습니다. 제어판의 화면 전환과 실제 작업의 종료를 같은 사건으로 취급하지 않는 설계가 중요합니다.

1-1. 사용자가 보는 한 번의 요청, 내부에서는 여러 번의 왕복

“이 코드의 오류를 찾아줘”라는 요청은 모델 응답 한 번으로 끝나지 않을 수 있습니다. 모델이 파일 읽기를 요청하고, 실행 결과를 받은 뒤 다른 파일을 조사하며, 마지막에 답을 만듭니다. ExecutionEngine::execute_dialog_turn()과 RoundExecutor::execute_round_with_lifecycle()가 이 구분을 보여 줍니다.

사용자 요청 하나 = 대화 턴 하나
  │
  ├─ 모델 라운드 1: 조사할 파일 선택
  │    └─ 도구 실행 결과를 대화 기록에 추가
  ├─ 모델 라운드 2: 결과를 읽고 추가 조사
  │    └─ 도구 실행 결과를 대화 기록에 추가
  └─ 모델 라운드 3: 최종 설명 작성

각 단계의 진행 사실 ──> 이벤트 ──> 데스크톱 / CLI / 원격 화면
용어
에이전트 실행 환경 · Agent Harness
모델 주변에서 계획·문맥·도구·권한·중단·복구를 관리하는 장치들의 묶음입니다. 모델 자체의 가중치나 학습 알고리즘을 뜻하지 않습니다. 같은 모델도 이 주변 장치가 달라지면 작업 방식이 달라집니다.

1-2. 세 가지 이름부터 구분하기

이름쉬운 의미코드에서 찾을 단서
Session대화와 작업 상태를 묶는 오래가는 단위session_id, SessionState
Dialog Turn한 번의 요청을 처리하는 작업 단위dialog_turn_id, execute_dialog_turn()
Model Round모델을 한 차례 호출하고 결과를 처리하는 단위round_id, RoundExecutor

출발점은 src/apps/desktop/src/api/agentic_api.rs입니다. 그 안의 start_dialog_turn()은 요청을 변환해 공통 런타임에 넘깁니다. 화면에서 사용하는 명령과 실제 작업 엔진을 분리하는 첫 경계를 여기서 볼 수 있습니다.

2왜 주목받는가

트렌딩 순위와, 소스에서 읽어 낼 수 있는 관심 요인을 구분하기

2026-10-23 GitHub Trending Rust Weekly 5위에 오른 프로젝트입니다. 스타 3,099개와 포크 278개는 관심의 크기를 보여 주지만, 사용자의 만족도나 실행 속도를 직접 증명하지는 않습니다. 순위 상승의 원인을 분리해 측정한 자료는 없으므로, 아래는 현재 기능과 구현을 바탕으로 해석한 관심 요인입니다.

2-1. 실행 엔진과 완성형 작업 화면을 함께 공개한다

학습자는 Rust 비동기 코드뿐 아니라 편집기·터미널·메시지 표시가 연결되는 제품 전체를 읽을 수 있습니다. src/web-ui/package.json에는 Monaco·xterm·Tiptap·Markdown 관련 의존성이 함께 등장합니다. 채팅 화면 하나를 넘어 다양한 결과물을 다루려는 제품 구성이 의존성에도 드러납니다.

OpenBitFun의 비교 우위로 읽을 지점은 Rust라는 언어 하나가 아니라, 공통 실행 계층을 여러 작업 화면과 연결한 범위입니다.

비교할 제품 유형주로 집중하는 경험OpenBitFun에서 눈여겨볼 점
터미널 중심 코딩 도구명령 입력과 텍스트 중심 작업CLI에 더해 Tauri 데스크톱, 편집기와 별도 도구 화면이 같은 저장소에 있음
IDE 중심 AI 확장기존 편집기 안에서 코드 보조독립 앱으로 세션·원격 제어·Mini App의 제품 수명주기까지 관리
채팅형 AI 클라이언트대화와 모델 선택 중심파일·프로세스·도구 실행과 승인·취소 흐름을 함께 학습 가능
에이전트 SDK개발자가 조립할 실행 부품실행 부품과 실제 배포 앱을 함께 읽으며 추상화의 사용처를 확인 가능

이 표는 제품 유형의 관점 차이를 비교한 것입니다. 특정 경쟁 제품의 기능 부재나 우열을 판정한 표가 아닙니다. 통합 범위가 넓은 만큼 의존성과 빌드 과정도 복잡해진다는 비용이 따릅니다.

2-2. 모드와 확장 기능으로 작업 방식을 바꾸려 한다

README는 Minimal·Standard·Ultimate·Creative 네 모드를 소개합니다. 각각 빠른 직접 협업, 일상적인 다단계 작업, 복잡한 협업, 제작·맞춤화에 초점을 둔다고 설명합니다. 학습할 때는 이를 “서로 다른 모델 네 개”로 이해하지 말고, 에이전트 정의·프롬프트·도구·정책을 조합하는 제품 선택으로 보세요.

관련 코드는 src/crates/assembly/core/src/agentic/agents/definitions/modes/와 src/crates/assembly/agent-content/에서 이어집니다. MCP·Skills·Hooks·Mini App은 같은 종류의 확장이 아니며, 연결되는 경계도 다릅니다.

2-3. 원격 환경을 별도 문제로 다룬다

AGENTS.md는 원격 작업 공간, 모바일·메신저 원격 제어, 같은 계정의 기기 전환, 제출자가 연결을 끊어도 대상 호스트가 맡는 작업 전달을 각각 구분합니다. 초보자에게 유익한 질문은 “기능이 몇 개인가”보다 “파일이 있는 기기와 화면이 있는 기기가 다르면 누가 일을 해야 하는가”입니다.

읽는 관점
광고 문구를 구현 질문으로 바꾸기

“오래 일한다”는 말은 취소·재접속·문맥 압축이 어떻게 연결되는지 묻는 출발점입니다. “원격 제어”는 작업 소유자와 화면 소유자를 어디서 나누는지 묻는 출발점입니다.

2-4. 성능 주장과 확인 가능한 사실

GitHub 설명은 고성능 Rust 런타임을 내세웁니다. README의 자체 DeepSWE v1.1 평가에는 GLM-5.3-Flash 통과율 64.6%·실행 시간 중앙값 42.9분, DeepSeek-V4-Flash 통과율 56.6%·중앙값 19.6분이 적혀 있습니다. 이는 README에 게시된 자체 평가 결과이며, 독립적으로 검증된 측정값과 구분해야 합니다.

모델·도구·평가 환경이 함께 작용하므로 이 수치만으로 Rust의 효과나 다른 제품보다 빠른 정도를 계산할 수 없습니다. 소스에서 확인할 수 있는 것은 취소 토큰, 이벤트 압축, 문맥 예산처럼 성능과 지속 작업을 다루는 장치의 존재입니다.

3기술 스택 전체 지도

선언한 버전 범위·잠금 버전·실제로 맡은 역할을 함께 보기

루트 Cargo.toml은 Rust 워크스페이스 멤버 54개와 공통 버전을 관리합니다. pnpm-workspace.yaml은 React 앱·공유 패키지·디자인 시스템을 묶습니다. 의존성 선언은 버전 조건을 나타내고, 잠금 파일의 버전은 해당 스냅샷에서 선택된 구체적인 버전입니다.

용어
워크스페이스와 잠금 파일
워크스페이스는 관련 패키지를 한곳에서 관리하는 묶음입니다. 잠금 파일은 의존성 해석 결과를 기록한 명세서입니다. Rust의 version = "1.52"는 1.52.0만 고정한다는 뜻이 아니므로, 실제 선택 버전은 Cargo.lock에서 확인해야 합니다.

3-1. 백엔드: Rust가 실행과 운영체제 자원을 맡는다

기술선언값 → 잠금값이 저장소에서의 역할
Rustedition = "2021"공통 패키지 버전 1.0.7. 언어 에디션이며 컴파일러 최소 버전과는 다름
Tokio1.52 → 1.53.1비동기 실행, 프로세스·네트워크·동기화. 루트 기본 기능 비활성화
Serde1.0 → 1.0.229요청·응답·이벤트를 직렬화. serde_json = "1.0"도 공통 관리
Reqwest0.13.4 → 0.13.4모델 등 외부 HTTP 통신. 필요한 TLS·스트림 기능은 소비자가 선택
Axum0.8 → 0.8.9서버 진입점의 HTTP·WebSocket. tower-http = "0.6.11"와 조합
Tauri2.11 → 2.11.5데스크톱 창·명령·이벤트·패키징
RMCP1.7 → 1.8.0MCP 연결에 쓰는 Rust SDK. 루트에서 기본 기능을 끄고 필요한 기능 명시
ts-rs12 → 12.0.1Rust 계약에서 TypeScript 타입을 생성하는 경로에 사용
Git·터미널git2 = "0.21", portable-pty = "0.8"Git 처리와 의사 터미널. git2 잠금값은 0.21.0
CLI·TUIclap = "4.6.1", ratatui = "0.29", crossterm = "0.28"명령 인자와 터미널 화면. 이 행은 선언값

위 Rust 버전 출처는 루트 Cargo.toml과 Cargo.lock입니다. src/apps/desktop/Cargo.toml은 Tokio의 fs·process·rt-multi-thread 등을 선택하지만, 더 작은 소비자는 다른 기능 조합을 고릅니다. 같은 의존성을 쓴다고 모든 기능이 필요한 것은 아닙니다.

# Cargo.toml의 공통 정책
[workspace.dependencies]
tokio = { version = "1.52", default-features = false }

# src/crates/execution/tool-execution/Cargo.toml의 선택
tokio = { workspace = true, features = ["io-util", "rt", "sync", "time"] }

3-2. 프론트엔드: 제품 기능을 표현하는 여러 도구

영역실제 선언 버전읽으면서 배울 것
화면react·react-dom ^18.3.1대화·편집기·설정을 컴포넌트로 구성
타입·빌드typescript ~5.8.3, vite ^7.0.4타입 검사와 개발·배포 빌드의 역할 구분
상태zustand ^5.0.10, immer ^11.1.3컴포넌트 밖의 공유 상태와 변경 표현
코드 편집기monaco-editor ^0.52.2, @monaco-editor/react ^4.6.0전문 편집기 엔진과 React 연결 계층 구분
문서 편집기@tiptap/react ^3.20.4서식 있는 문서 편집을 코드 편집과 구분
터미널@xterm/xterm ^6.1.0-beta.101웹 화면에 터미널 데이터를 표시. 운영체제 프로세스 실행은 별도 계층
긴 목록react-virtuoso ^4.18.11, @tanstack/react-virtual ^3.13.23보이는 항목 중심으로 그리는 가상화
문서 표시react-markdown ^10.1.0, mermaid ^11.10.1, pdfjs-dist 5.4.624대화 결과가 텍스트·도식·문서로 확장되는 구성
국제화i18next ^25.8.0, react-i18next ^16.5.3번역 자원과 화면 코드를 나누는 경계
화면 테스트vitest ^4.1.0, jsdom ^29.0.1브라우저 화면을 다루는 단위 테스트 도구

이 표는 src/web-ui/package.json의 선언값입니다. ^와 ~를 지우고 정확한 설치 버전처럼 읽지 마세요. 모바일 웹은 별도 패키지이며, xterm 선언도 데스크톱용 Web UI와 동일하지 않습니다.

3-3. 인프라·빌드: Rust와 웹 도구만으로 끝나지 않는다

구성파일과 설정값의미
Node.js·pnpm루트 package.json: >=22.12.0, packageManager: pnpm@10.15.0웹 개발 도구의 기준. 별도 의존성 pnpm ^10.32.1과 구분
플러그인 호스트src/apps/extension-host/package.json: bun@1.3.14, SDK·plugin 1.17.18별도 Bun 패키지와 bun.lock. 루트 pnpm 설치만으로 설명되지 않는 경로
데스크톱 빌드루트 @tauri-apps/cli 2.11.4, src/apps/desktop/tauri.conf.json의 개발 주소 포트 1422Rust 크레이트·웹 API·빌드 CLI는 서로 다른 패키지
CI.github/workflows/ci.yml: Linux·macOS·Windows 검사, --locked, --frozen-lockfile잠금 파일을 지키며 플랫폼별 회귀를 검사
중계 서버 컨테이너src/apps/relay-server/Dockerfile: rust:1.96-bookworm → debian:bookworm-slim다단계 빌드. 빌드 도구와 배포 이미지를 분리
중계 서버 운영src/apps/relay-server/docker-compose.yml: 기본 포트 9700, SQLite 경로와 볼륨 지정데스크톱 앱 전체를 컨테이너에 넣는 설정이 아니라 중계 서비스용

루트 빌드 스크립트의 plugin-host:prepare는 Bun 설치·빌드를 연결하고, 데스크톱 설정은 그 결과인 extension-host.js를 리소스로 포함합니다. pnpm-lock.yaml과 Cargo.lock 외에 별도 패키지의 잠금 파일이 존재하는 이유입니다.

또한 루트 [patch.crates-io]는 eioc·tao·wry를 third_party/ 경로로 교체하고, 일부 Tauri 런타임을 Git 리비전으로 지정합니다. 버전 번호만 보고 표준 배포본과 완전히 같은 의존성 트리라고 가정할 수 없습니다.

4아키텍처 심화 분석

네 가지 설계 패턴으로 요청·상태·이벤트·도구를 읽기

4-1. 시스템 구조도: 논리 계층과 배포 형태 구분

[사용 화면 / 진입점]
 React Web UI       CLI / TUI       모바일·다른 기기의 제어 화면
      │                  │                       │
 Tauri 명령 또는 WS      │                 중계·원격 연결
      │                  │                       │
      └───────────────┬──┴───────────────────────┘
                      v
 [호스트별 어댑터 · 앱 초기화 · 제품 조립]
   src/apps/desktop · src/apps/cli · src/apps/server
   src/crates/interfaces · src/crates/assembly/core
                      │ 포트 구현 주입
                      v
 [공통 AgentRuntime 파사드]
   요청 제출 / 세션 / 취소 / 승인 / 이벤트 조회
                      │
       ┌──────────────┼────────────────┐
       v              v                v
 상태·조정·실행    문맥·대화 기록     이벤트 저널
       │              │                │
       ├─ 모델 요청 ──┴──> AI 어댑터 ──> 모델 서비스
       │
       └─ 도구 요청 ──> 목록·정책 검사 ──> 도구 실행
                                          │
                              파일 / 터미널 / Git / MCP

[계층을 잇는 계약] core-types · events · runtime-ports
[운영체제 구현]    services 및 각 호스트의 구체 구현

위 도식은 역할을 간추린 논리 구조도이며, 상자 하나가 프로세스 하나라는 뜻은 아닙니다. 현재 ExecutionEngine과 RoundExecutor의 제품 실행 코드는 여전히 src/crates/assembly/core/src/agentic/execution/에 있습니다. src/crates/execution/agent-runtime/ 폴더 하나에 모든 로직이 옮겨져 있다고 설명하면 실제 코드와 어긋납니다.

src/apps/server/src/main.rs는 내장 런타임을 쓰는 로컬 단일 사용자 호스트로 자신을 설명하며, 127.0.0.1:8080에 바인딩합니다. relay-server의 포트 9700과 역할도 다릅니다. 공통 런타임 사용은 모든 호스트가 한 프로세스를 공유한다는 보장과 다릅니다.

4-2. 패턴 ① 포트와 어댑터: 구현을 몰라도 요청할 수 있게

src/crates/execution/agent-runtime/src/runtime.rs의 AgentRuntime은 Arc<dyn AgentSubmissionPort> 같은 인터페이스를 보관합니다. 실제 파일 접근이나 화면 객체를 직접 요구하는 대신, 필요한 기능의 계약을 받습니다. AgentRuntimeBuilder::build()는 필수 제출 포트가 없으면 MissingSubmissionPort를 반환합니다.

// runtime.rs에서 발췌: 제출 동작은 주입된 구현에 위임한다.
pub async fn submit_turn(
    &self,
    request: AgentSubmissionRequest,
) -> Result<AgentSubmissionResult, RuntimeError> {
    self.submission
        .submit_message(request)
        .await
        .map_err(RuntimeError::from)
}
용어
포트 · 어댑터 · 의존성 주입
포트는 “메시지를 제출할 수 있다” 같은 약속이고, 어댑터는 그 약속을 특정 환경에서 지키는 구현입니다. 의존성 주입은 사용할 구현을 바깥에서 전달하는 방식입니다. 테스트에서는 실제 모델 대신 가짜 구현을 전달할 수 있습니다.

프론트엔드에도 대응되는 구조가 있습니다. src/web-ui/src/infrastructure/api/adapters/base.ts의 ITransportAdapter는 request()·listen()·disconnect()를 정의합니다. 같은 폴더의 index.ts에 있는 createTransportAdapter()가 Tauri 또는 WebSocket 구현을 선택합니다.

TransportSurfaceBinding은 surfaceId·generation·surfaceEpoch를 함께 기록합니다. 기기 A에 보낸 비동기 요청이 끝날 때 화면이 기기 B로 바뀌어 있을 수 있기 때문입니다. assertTransportSurface()처럼 결과를 적용할 대상 기기가 바뀌었는지 확인하는 장치도 어댑터 설계의 일부입니다.

4-3. 패턴 ② 상태 모델과 협력적 취소: 일의 수명주기를 드러내기

src/crates/execution/agent-runtime/src/session_state.rs는 세션을 Idle, Processing, Error로 모델링합니다. 처리 상태에는 턴 ID와 단계가 들어가고, 오류에는 복구 가능 여부가 들어갑니다.

// session_state.rs: 속성과 데이터가 결합된 Rust enum
pub enum SessionState {
    Idle,
    Processing {
        current_turn_id: String,
        phase: ProcessingPhase,
    },
    Error {
        error: String,
        recoverable: bool,
    },
}

ProcessingPhase는 Starting·Compacting·Thinking· Streaming·ToolCalling·ToolConfirming입니다. 모두가 매번 정해진 순서로 한 번씩 나타나는 파이프라인은 아닙니다. 도구 실행 뒤 다시 모델을 호출할 수도 있습니다.

session_state_manager.rs의 can_start_new_turn()은 대기 상태 또는 복구 가능한 오류에서만 참을 반환합니다. update_state()는 등록된 상태를 갱신한 뒤 상태 변경 이벤트를 넣습니다. 다만 이 자료형 하나가 모든 전이 규칙을 강제하는 것은 아닙니다. 조정자·스케줄러의 제어 흐름도 함께 읽어야 합니다.

실제 엔진의 execute_dialog_turn_impl()에는 라운드 반복문이 있고, 매 반복 시작에 취소 상태를 확인합니다. 바깥의 execute_dialog_turn()은 내부 결과가 오류여도 뒤이어 자신이 소유한 화면 제어 자원을 해제하고 취소 토큰을 정리합니다. 이 흐름은 일을 시작하는 코드와 끝맺는 코드를 함께 설계해야 한다는 교훈을 줍니다.

비유

취소 토큰은 전원선을 뽑는 것보다 정지 신호를 보내는 일에 가깝습니다. 실행 중인 코드가 신호를 확인하고 빠져나와야 합니다. 화면의 로딩 표시를 끄는 것만으로 작업 프로세스나 자원이 정리되지는 않습니다.

4-4. 패턴 ③ 이벤트 저널과 스냅샷: 끊겼다가 돌아온 화면 복구

src/crates/execution/agent-runtime/src/session_event_journal.rs의 SessionEventJournal은 화면에 전달할 실행 이벤트를 기록하고 재접속에 필요한 상태를 만듭니다. record()는 투영 대상 이벤트에 커서를 부여하고, events_since()는 이후 변경분을 조회합니다.

장치실제 설정·이름필요한 이유
최근 개별 이벤트MAX_REPLAYABLE_TAIL_EVENTS = 1024짧은 연결 끊김에는 빠진 이벤트만 순서대로 보충
현재 상태 투영MAX_PROJECTED_EVENTS_PER_SESSION = 2048텍스트 조각 등을 합쳐 현재 턴의 상태를 표현
종료된 투영 보존MAX_RETAINED_TERMINAL_SESSION_PROJECTIONS = 64종료 세션 투영을 무한히 쌓지 않도록 정리
프로세스 구분stream_id와 cursor재시작 전 커서를 새 프로세스의 진행도와 혼동하지 않음
화면이 마지막으로 적용한 위치: stream=A, cursor=40

같은 stream, 41번 이후 기록이 남음
  └─ events_since() ──> Delta { events, cursor }
                         └─ 빠진 변경분 적용

기록이 너무 오래됐거나 stream이 바뀜
  └─ events_since() ──> SnapshotRequired
                         └─ snapshot()으로 상태 재구성

누적 텍스트가 “안녕하세요”라는 사실만으로는 화면이 놓친 조각이 “하세요”인지 알 수 없습니다. 그래서 현재 모습을 나타내는 투영과 원래 이벤트를 보관하는 최근 기록을 따로 둡니다. 같은 파일의 a_delta_replays_each_chunk_the_projection_merged_away() 테스트가 바로 이 차이를 다룹니다.

메모리 밖 보존은 SessionEventProjectionStore 포트로 분리합니다. src/crates/assembly/core/src/service/session_projection_store.rs에는 FileSessionProjectionStore 구현이 있습니다. 저장소를 붙이는 with_store() 경로와 단순 메모리 저널을 구분해야 하며, 이를 앱 전체의 완전한 이벤트 소싱이라고 확대해 부르지는 않는 편이 정확합니다.

4-5. 패턴 ④ 레지스트리와 실행 관문: 도구가 보인다고 실행 가능한가

src/crates/execution/tool-contracts/src/framework.rs의 ToolRegistryItem은 이름·설명·입력 스키마·읽기 전용 여부 같은 도구 정보를 정의합니다. 제품의 실행 인터페이스는 src/crates/assembly/core/src/agentic/tools/framework.rs의 Tool에서 더해집니다. 목록에 필요한 계약과 구체 실행의 책임을 구분해 읽으세요.

src/crates/assembly/core/src/agentic/tools/registry.rs의 register_mcp_tools()는 MCP 도구를 동적으로 등록합니다. 같은 이름이 있으면 경고 후 덮어쓰는 경로도 있어, 플러그인을 연결할 때 이름과 소유자 정보가 중요한 이유를 보여 줍니다.

// execution_gate.rs의 검사 순서를 간추린 학습용 의사 코드
허용된_도구_목록_검사(도구_이름)?;
런타임_제한_검사(도구_이름)?;
지연_도구_명세와_카탈로그_세대_검사(도구_이름)?;
// 이후 제품 파이프라인의 검증·권한 판단·실행 단계로 이어진다.

위 세 검사를 묶는 실제 함수는 validate_tool_execution_admission()입니다. src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs가 이를 호출하고, round_executor.rs는 전역·프로젝트·에이전트 규칙과 런타임 상한으로 실행 정책을 구성합니다. GetToolSpec 관련 검사는 명세를 아직 확인하지 않은 지연 도구의 사용도 제어합니다.

모델이 도구 호출을 출력했다는 사실과, 프로그램이 그 행동을 허용한다는 판단은 서로 다른 단계여야 합니다.

경계 이해
권한 정책을 운영체제 샌드박스와 혼동하지 않기

도구 허용 목록·승인·취소는 중요한 통제 장치지만, 악성 코드를 운영체제 차원에서 완전히 격리한다는 증거는 아닙니다. docs/architecture/product-architecture.md도 Sandbox를 계획 단계로 표시합니다. 파일·프로세스 도구와 외부 확장을 읽을 때는 실제 실행 권한과 격리 경계를 따로 확인해야 합니다.

5디렉토리 구조 해부

실행 진입점부터 계약까지 내려가는 길과, 옆에 놓인 제품 도구들

아래 경로는 모두 저장소 루트 기준입니다. 트리는 주요 폴더를 추린 것이며, 작은 패키지나 플랫폼 하위 폴더까지 전부 펼치지는 않았습니다. 먼저 apps와 crates를 구분하고, 그다음 웹 화면과 공통 패키지를 읽으면 됩니다.

OpenBitFun/
├── Cargo.toml / Cargo.lock       Rust 패키지 묶음과 잠금 결과
├── package.json / pnpm-lock.yaml 웹·제품 빌드 명령과 잠금 결과
├── pnpm-workspace.yaml           웹 패키지 묶음
├── src/
│   ├── apps/
│   │   ├── desktop/              Tauri 호스트·명령·운영체제 연결
│   │   ├── cli/                  명령행·터미널 화면·호스트
│   │   ├── server/               로컬 WebSocket·App Server 진입점
│   │   ├── sdk-host/             SDK 호스트 실행 파일
│   │   ├── extension-host/       Bun 기반 확장 호스트
│   │   ├── relay-server/         기기 연결을 위한 중계 서비스
│   │   ├── miniapp-shell/        Mini App의 별도 창을 위한 셸
│   │   ├── mobile/               네이티브 모바일 관련 코드
│   │   └── data-tools/           데이터 마이그레이션 도구
│   ├── crates/
│   │   ├── interfaces/           ACP·App Server·SDK 인터페이스
│   │   ├── assembly/             제품 능력 선택과 구현 조립
│   │   ├── adapters/             AI·전송·외부 생태계 변환
│   │   ├── services/             파일·프로세스·원격 연결 등 구현
│   │   ├── execution/            런타임·스트림·도구 실행의 공통 부품
│   │   └── contracts/            타입·이벤트·포트·제품 도메인 계약
│   ├── web-ui/                   데스크톱·웹용 주 React 화면
│   ├── mobile-web/               원격 제어용 모바일 웹
│   └── shared/                   국제화·기능 목록 등 공유 계약
├── design-system/                토큰·테마·UI·디자인 실험실
├── packages/                     공유 표현 패키지와 외부 연결 패키지
├── sdk/typescript/               TypeScript SDK
├── products/                     제품 구성 정의
├── extensions/                   제품 확장 자산
├── MiniApp/                      Mini App 예제·관련 자산
├── OpenBitFun-Installer/          별도 설치 프로그램
├── deploy/                       배포 설정과 운영 스크립트
├── scripts/                      생성·검사·패키징 보조 코드
├── tests/e2e/                    제품 통합 시나리오 검사
├── docs/                         구조·기능·설계 문서
├── website/                      공식 웹사이트
├── third_party/                  수정한 외부 의존성 코드
└── .github/workflows/            CI·릴리스·플랫폼별 패키징

5-1. 폴더 이름보다 중요한 “누가 상태를 소유하는가”

계층주로 맡는 일읽을 때 할 질문
apps·interfaces사용자·프로토콜의 진입점입력을 어떤 공통 요청으로 바꾸는가?
assembly제품 구성과 구현 연결필요한 포트에 어떤 구현을 넣는가?
adapters외부 형식을 내부 계약으로 번역외부 규칙이 내부 도메인으로 새어 들어오지 않는가?
services운영체제·네트워크·저장소 처리작업은 실제로 어느 기기에서 일어나는가?
execution공통 실행 상태·이벤트·도구 부품화면 없이도 동작을 설명할 수 있는가?
contracts타입·오류·이벤트·포트 약속계약을 바꾸면 어떤 소비자가 영향을 받는가?

의도한 의존 방향은 위 계층에서 아래 계층으로 내려갑니다. 다만 제품 실행 로직 일부가 src/crates/assembly/core/에 남아 있다는 점을 함께 기억하세요. 구조 문서가 제시하는 목표와 실제 함수가 놓인 위치를 함께 보는 것이 대형 저장소를 읽는 방법입니다.

5-2. 코드 규모와 집계 범위

언어·확장자파일 수물리적 줄 수
Rust · .rs2,0331,079,373줄 · 약 108만 줄
TypeScript · .ts + .tsx4,084723,050줄 · 약 72만 줄
JavaScript · .js + .mjs + .cjs488194,567줄 · 약 19만 줄
스타일 · .css + .scss531135,001줄
Kotlin · .kt + .kts34960,162줄
Swift · .swift5517,979줄
Python · .py217,881줄

커밋 8c012e4의 Git 추적 파일을 확장자별로 집계한 값이며, 마지막 줄바꿈이 없는 행도 한 줄로 셉니다. third_party/와 심볼릭 링크는 제외하고 빈 줄·주석·테스트·생성 코드는 포함한 수치입니다. Git이 추적하는 내장 번들 자산도 포함됩니다. 따라서 “사람이 작성한 제품 로직의 줄 수”나 순수 실행문 수로 해석하면 안 됩니다.

작은 언어 파일이 있다고 그 언어가 주 백엔드라는 뜻도 아닙니다. 루트에는 pyproject.toml이나 go.mod가 없으며, 주 실행 구조는 Rust와 웹 패키지 묶음으로 설명됩니다.

6학습 포인트 (기술별)

기술 이름을 아는 단계에서, 설계 이유를 설명하는 단계로

큰 저장소는 처음부터 끝까지 읽기보다, 질문 하나를 정하고 그 답을 가진 함수와 계약만 연결해 읽을 때 배울 수 있습니다.

6-1. Rust: enum과 Result로 가능한 상태를 표현하기

SessionState를 보면 문자열 하나 대신 enum을 쓰는 이유를 알 수 있습니다. 처리 중이라면 턴 ID와 단계가 함께 있고, 오류라면 원인과 복구 가능 여부가 함께 있습니다. RuntimeBuildError와 RuntimeError에서는 조립 실패와 실행 중 실패를 별도 타입으로 나눕니다.

실습 아이디어: 대기·실행·실패 상태를 불리언 세 개로 표현하면 몇 가지 모순 조합이 가능한지 적어 보세요. 그다음 enum으로 바꿔 동시에 실행 중이면서 대기 중인 상태를 표현할 수 있는지 비교합니다.

용어
Arc와 dyn Trait
Arc는 여러 소유자가 같은 값을 공유할 때 쓰는 참조 계수 포인터입니다. dyn Trait은 구체 타입 대신 약속된 동작을 통해 객체를 사용하게 합니다. Arc<dyn AgentSubmissionPort>는 공유 가능한 제출 기능의 구현을 가리킵니다. Arc만으로 내부 데이터 변경까지 자동으로 안전해지는 것은 아닙니다.

6-2. Tokio: 비동기 작업의 취소와 정리를 같이 설계하기

execution_engine.rs에는 CancellationToken과 tokio::select!가 등장합니다. 오래 걸리는 준비 작업도 취소 요청과 함께 기다리도록 만드는 방식입니다. await를 쓴다는 사실만으로 취소나 자원 정리가 저절로 해결되지는 않습니다.

실습 아이디어: “모델 연결 대기 중 취소”와 “도구 실행 중 취소”를 나눠 순서도를 그리세요. 어느 자원이 만들어졌고 누가 정리하는지 적은 뒤, execute_dialog_turn()의 정리 경로와 대조합니다.

6-3. Tauri·TypeScript: 화면과 호스트 사이의 계약 유지하기

start_dialog_turn()은 Rust 호스트 명령이고, ITransportAdapter.request<T>()는 화면이 결과를 요청하는 공통 통로입니다. Rust 쪽 Serde 이름과 TypeScript 요청 필드가 어긋나면 컴파일되는 두 프로그램 사이에서도 통신이 실패할 수 있습니다.

실습 아이디어: StartDialogTurnRequest와 변환 함수 desktop_dialog_turn_request()를 읽고 세션 ID·워크스페이스 정보·원격 연결 정보가 어디로 이동하는지 표로 만드세요. 모든 필드가 단순 복사되는지, 호환성을 위해 남은 필드가 있는지도 확인합니다.

// base.ts의 형태를 줄인 예시: 실제 인터페이스에는 다른 메서드도 있다.
interface ITransportAdapter {
  request<T>(action: string, params?: any): Promise<T>;
  listen<T>(event: string, callback: (data: T) => void): () => void;
}

여기서 <T>는 호출자가 기대하는 타입을 표현하지만, 실제 네트워크 입력을 자동 검증해 주지는 않습니다. 정적 타입과 실행 시 검증을 구분하는 것도 좋은 학습 주제입니다. listen()의 반환값은 구독 해제 함수이므로 화면을 떠날 때의 정리까지 생각해야 합니다.

6-4. 이벤트·React: 늦게 도착한 결과의 목적지를 확인하기

src/web-ui/src/infrastructure/api/adapters/index.ts의 기기 바인딩과 src/web-ui/src/infrastructure/api/adapters/tauri-adapter.ts의 registerSharedTauriEventListener()를 함께 읽으세요. 후자는 기기별 이벤트를 분류하고, 이전 구독이나 이전 화면 범위에 속한 결과가 현재 화면으로 흘러오지 않게 확인합니다.

실습 아이디어: A 기기의 요청을 보낸 직후 B 기기로 전환하고 A의 응답이 늦게 도착하는 상황을 그려 보세요. 요청 ID만 확인할 때와 기기·화면 세대까지 확인할 때 어떤 차이가 생기는지 설명합니다. 채팅뿐 아니라 검색 자동완성·탭 전환 화면에도 적용할 수 있는 문제입니다.

6-5. LLM 문맥: 압축은 대화 전체를 버리는 일이 아니다

src/crates/assembly/core/src/agentic/session/compression/compressor.rs의 ContextCompressor는 압축 계획과 결과 변환을 다룹니다. CompressionPlan에는 요약 대상, 유지할 사용자 메시지, 최근 대화 원문, 토큰 예산이 따로 있습니다.

코드의 DEFAULT_RECENT_CONTEXT_TOKENS = 10_000, RECENT_CONTEXT_RETRY_STEP_TOKENS = 10_000, MAX_RETAINED_USER_TOKENS = 20_000은 이 압축기의 정책 상수입니다. 모델의 전체 문맥 창 크기나 모든 상황에서 항상 쓰는 최종 예산과 혼동하지 마세요.

실습 아이디어: “목표·금지 조건·도구 결과·최근 오류”가 들어 있는 가상 대화를 만들고 요약으로 남길 것과 원문을 유지할 것을 나눠 보세요. 이후 작업을 다시 시작할 수 있는지가 압축 품질의 기준입니다.

6-6. MCP·도구 정책: 메타데이터와 실행 권한을 나누기

ToolRegistryItem::is_readonly()의 기본값은 거짓이고, is_concurrency_safe()의 기본 구현은 읽기 전용 여부를 따릅니다. 도구가 수정 작업인지, 동시에 실행해도 되는지 같은 정보가 실행 정책의 재료가 됩니다. 이름이나 설명만 등록하는 단순한 함수 목록보다 책임이 많습니다.

실습 아이디어: 파일 읽기와 파일 이름 변경 도구를 상상하고, 같은 디렉토리에서 동시에 실행해도 되는 조합을 적어 보세요. 등록·노출·허용·승인·실행 결과 중 어느 단계에서 실패해야 하는지도 구분합니다.

6-7. 빌드 설계: 기능을 작게 켜고 경계를 검사하기

src/crates/execution/agent-runtime/Cargo.toml은 default = []이고 기능별로 의존성을 선택합니다. src/crates/execution/tool-execution/Cargo.toml도 문서 읽기와 웹 본문 처리를 선택 기능으로 나눕니다. 학습 포인트는 “전부 켜서 성공시키기”보다 필요한 소비자에게 필요한 기능만 연결하는 방법입니다.

실습 아이디어: native-hook-runtime 기능이 활성화하는 Tokio 세부 기능을 표시하고, 단순 계약만 읽는 소비자에게 프로세스 실행 의존성이 왜 불필요할 수 있는지 설명합니다. 구조 검사가 CI에 있는 이유도 함께 연결해 보세요.

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

완성 앱 사용·소스 빌드·원격 호스트·모델 추론을 나눠서 보기

README와 기여 안내는 Node.js·pnpm·Rust·Tauri 사전 조건을 제시하지만, 모든 기능에 통용되는 공식 최소 RAM·CPU·디스크 수치를 제시하지는 않습니다. 앱을 실행하는 컴퓨터의 요구사항과 모델을 직접 추론하는 컴퓨터의 요구사항은 별도로 판단해야 합니다.

상황확인한 요구 조건·설정해석할 때 주의할 점
배포 앱 사용README 안내 대상은 Windows·macOS·Linux지원 플랫폼 표시는 모든 운영체제 버전과 모든 기능의 동일한 검증을 뜻하지 않음
소스 빌드Node.js 22.12 이상, pnpm 10.15.0, Rust 도구 모음, Tauri 사전 조건README·CONTRIBUTING·루트 manifest 기준. Rust 2021은 최소 컴파일러 버전 표기가 아님
플러그인 호스트Bun 1.3.14를 패키지와 CI에서 지정해당 호스트 리소스 준비가 제품 빌드 경로에 포함됨
Linux 개발CI가 GTK 3·WebKitGTK·GStreamer·Tesseract 등의 개발 패키지 설치GUI·화면 캡처·OCR의 시스템 라이브러리가 Rust 도구와 별도로 필요
macOS 화면 캡처데스크톱 README: 해당 ScreenCaptureKit 경로는 macOS 12.3 이상캡처 기능의 조건이며 전체 앱의 최소 OS 버전이라고 확대하면 안 됨
macOS 배포 번들 제작데스크톱 README: 전체 Xcode 26 이상개발 실행과 배포 번들 제작의 도구 조건이 다름
모델 연결README는 모델을 설정한 뒤 시작하도록 안내선택한 모델 서비스의 연결·인증·요금과 기능 제약은 별도 확인
GPUREADME·기여 안내에 전용 GPU 필수 조건 없음외부 모델 호출과 로컬 모델 추론을 구분. 자체 추론 비용은 모델마다 다름
중계 서버별도 서비스, 기본 포트 9700, 데이터 볼륨과 SQLite 파일 설정계정·기기 연결 구성에 필요하며 모든 로컬 코드 읽기에 필요한 서비스는 아님

7-1. 메모리보다 먼저 구분할 네 가지 부하

.github/workflows/ci.yml의 Rust 빌드 작업은 CARGO_INCREMENTAL=0, CARGO_PROFILE_DEV_DEBUG=0, CARGO_PROFILE_TEST_DEBUG=0을 설정합니다. 주석은 호스팅 러너의 디스크 한도 안에 유지하기 위한 설정이라고 설명합니다. 큰 Rust 제품에서는 실행 속도뿐 아니라 개발 산출물의 크기도 관리 대상이라는 사례입니다.

7-2. 빌드 조건과 런타임 조건을 혼동하지 않기

루트의 profile.release는 opt-level = 3, lto = "thin", codegen-units = 1, strip = true를 설정합니다. 이는 컴파일·링크·배포 산출물에 관한 선택이지, 앱이 특정 용량 이하의 RAM에서 반드시 동작한다는 보장은 아닙니다.

src/apps/relay-server/Dockerfile은 CARGO_BUILD_JOBS 인자를 받아 빌드 병렬도를 낮출 수 있게 합니다. 이 컨테이너의 Rust 1.96 이미지는 해당 빌더의 선택이며, 전체 저장소의 공식 최소 Rust 버전이라고 읽으면 안 됩니다.

학습 환경
구조를 이해하는 데 모델 키나 실행 중인 앱은 필요하지 않습니다

이 글의 요청 추적·상태표·커서 복구 연습은 파일 검색과 코드 읽기로 시작할 수 있습니다. 실제 앱을 사용할 때에는 운영체제별 사전 조건과 선택한 기능의 권한을 해당 안내에서 확인하면 됩니다.

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

요청 추적부터 복구·권한 설계까지, 다섯 개의 작은 결과물

다음 과제는 소스를 읽고 기록하거나, 모의 입력만 쓰는 별도 학습 예제로 진행할 수 있습니다. 실제 모델·터미널·중계 서버 연결을 전제로 하지 않습니다. 실습의 완료 기준은 코드를 많이 바꾸는 것이 아니라, 정상 경로와 실패 경로를 같은 자료로 설명하는 것입니다.

과제 1 · 요청 흐름 읽기

메시지가 작업으로 바뀌는 경계 찾기 입문

할 일: start_dialog_turn()에서 시작해 요청 변환과 AgentRuntime::submit_dialog_turn()까지 연결하고, 제출 결과의 세션 ID를 다시 확인하는 부분을 찾습니다.

결과물: 함수 이름·입력 타입·출력 타입·책임이 있는 네 칸짜리 표와 호출 화살표.

완료 기준: 명령 응답의 “시작 성공”이 전체 작업 완료와 같은 뜻인지 설명합니다. 등록되지 않은 포트와 다른 세션 ID를 돌려준 구현이 각각 어떤 오류로 이어지는지도 적습니다.

# 저장소 루트에서 읽기 전용으로 위치 찾기
rg -n 'start_dialog_turn|desktop_dialog_turn_request' src/apps/desktop/src/api/agentic_api.rs
rg -n 'submit_dialog_turn|MissingDialogTurnPort' src/crates/execution/agent-runtime/src/runtime.rs
과제 2 · 상태 표현

새 턴을 시작할 수 있는 조건 정리 입문

할 일: SessionStateManager::can_start_new_turn()을 읽고 미등록·대기·처리·복구 가능 오류·복구 불가능 오류의 반환값을 표로 만듭니다.

결과물: 다섯 상태의 진리표와 ProcessingPhase를 한국어로 풀이한 단계 카드.

완료 기준: 미등록 상태가 대기 상태와 다르다는 점, 오류라고 항상 재시도할 수 있는 것은 아니라는 점을 설명합니다. 같은 파일의 session_state_manager_keeps_turn_start_guard_semantics()와 대조합니다.

과제 3 · 재접속 복구

이벤트가 빠진 화면을 되살리는 규칙 만들기 중급

할 일: 세션 하나·최근 기록 한도 3개인 모의 저널을 설계하고, 같은 스트림·너무 오래된 커서·다른 스트림·미래 커서를 각각 입력합니다. 한도 3은 연습을 위한 값이며 실제 코드의 한도 1,024와 구분합니다.

결과물: 입력 커서와 남은 기록, 예상 응답 Delta 또는 SnapshotRequired를 적은 사례집.

완료 기준: 문자열을 합친 현재 투영만으로 누락 이벤트를 복구할 수 없는 이유를 예제로 보입니다. tail_since()의 oldest.cursor <= cursor.saturating_add(1) 조건을 자신의 말로 설명합니다.

# 연습용 데이터: 전체 제품을 실행하지 않고 결과를 예측한다.
남은 기록 = [8, 9, 10]
같은 스트림, 커서 8  => [9, 10]을 담은 Delta
같은 스트림, 커서 6  => SnapshotRequired
다른 스트림, 커서 8  => SnapshotRequired
같은 스트림, 커서 11 => SnapshotRequired
과제 4 · 도구 실행 통제

더미 도구의 등록·노출·허용을 분리 중급

할 일: 실제 파일에 접근하지 않고 고정 문자열만 돌려주는 가상 도구를 그립니다. 허용 목록 제외, 런타임 제한, 지연 명세 미확인, 승인 대기를 서로 다른 상태로 표현합니다.

결과물: 모의 입력·거절 위치·오류 종류·부작용 유무를 담은 표와 validate_tool_execution_admission() 세 검사와의 대응표.

완료 기준: 모델에게 도구 설명을 보여 준 상태와 실행을 승인한 상태를 구분합니다. 실행 관문이 통과해도 제품 권한 정책의 별도 판단이 남는다는 점을 표시합니다.

과제 5 · 원격 환경 설계

기기 전환과 작업 소유자를 구분 고급

할 일: 기기 A의 작업을 보다가 B로 전환하는 상황에서 A의 늦은 응답·이벤트·승인 요청을 어느 상태 저장소로 보내야 하는지 설계합니다. TransportSurfaceBinding과 registerSharedTauriEventListener()를 근거로 삼습니다.

결과물: 두 기기와 화면을 분리한 시퀀스도, 화면 전환·연결 끊김·호스트 재시작의 차이표.

완료 기준: 화면을 닫는 일, 전송 연결을 끊는 일, 작업을 취소하는 일을 세 사건으로 설명합니다. 복구 때 커서 외에 기기와 스트림의 식별 정보가 필요한 이유도 적습니다.

과제 결과를 설명할 때에는 “실행해 봤다”와 “소스의 조건문으로 예상했다”를 구분해 적으세요. 특히 원격 복구와 운영체제 자동화는 코드가 존재한다는 사실만으로 모든 플랫폼에서 검증됐다고 말할 수 없습니다.

9관련 기술 심화 학습 로드맵

기초 언어부터 제품의 실패 복구까지, 여섯 주 동안 읽을 순서

한 주에 저장소 전체를 읽는 방식보다 작은 결과물을 하나씩 완성하는 순서를 권합니다. Rust를 처음 접한다면 1주차를 늘리고, 웹 개발 경험이 있다면 3주차에서 익숙한 지식과 호스트 경계를 연결해 보세요. 각 주의 결과물이 다음 주에 사용할 설명 자료가 되도록 구성했습니다.

주차핵심 개념이 저장소의 읽을 곳완성할 결과물
1주차소유권·참조·enum·Result·패턴 매칭session_state.rs, session_state_manager.rs상태별 시작 가능 여부와 오류 복구 표
2주차Trait·Arc·의존성 주입·빌더runtime.rs, runtime-ports, src/crates/execution/agent-runtime/Cargo.toml필수·선택 포트 지도와 누락 오류 예시
3주차TypeScript 제네릭·IPC·비동기 화면 갱신ITransportAdapter, start_dialog_turn(), TransportSurfaceBinding화면→호스트→런타임 요청 추적표
4주차Tokio·취소·턴과 라운드·정리execution_engine.rs, round_executor.rs모델 호출과 도구 호출 사이의 취소 시퀀스도
5주차커서·차분 복구·투영·스냅샷session_event_journal.rs, session_projection_store.rs기록 한도·재시작·미래 커서의 모의 사례집
6주차도구 스키마·권한·문맥 예산·선택 기능execution_gate.rs, tool_pipeline.rs, compressor.rs, CI도구 실행 설계서와 압축 후 작업 재개 계획

표의 짧은 파일명은 4~6절에서 설명한 전체 경로를 가리킵니다. 읽다가 낯선 타입이 나오면 모든 구현을 펼치기 전에 입력·출력·오류부터 적어 보세요. 해당 함수가 무엇을 책임지는지 알면 긴 구현에서 필요한 구간을 고르기 쉬워집니다.

9-1. 공식 자료와 실제 코드의 연결 방법

  1. Rust 공식 책: 소유권을 읽은 뒤 Arc로 공유하는 객체가 무엇인지 찾습니다.
  2. Tokio 학습 자료: 비동기 태스크를 배운 뒤 취소 신호를 어디서 기다리는지 표시합니다.
  3. Tauri 문서: 명령과 이벤트를 배운 뒤 요청 응답과 작업 진행 알림을 구분합니다.
  4. TypeScript 안내: 인터페이스를 배운 뒤 타입이 런타임 검증까지 해 주는지 다시 확인합니다.
  5. MCP 문서: 도구 연결 규약을 배운 뒤 제품의 실행 정책이 어디서 추가되는지 찾습니다.

학습을 마쳤다는 기준은 기능을 외우는 것이 아니라, 연결이 끊기거나 권한이 거절됐을 때 시스템이 어떻게 행동하는지 설명하는 것입니다.

자가 점검
다음 질문에 코드 경로를 붙여 답해 보세요

모델 호출을 한 번 더 해야 하는 이유는 무엇인가요? 화면의 연결 종료가 작업 취소와 다른 이유는 무엇인가요? 이벤트 커서는 왜 숫자 하나로 충분하지 않나요? 도구를 등록했는데도 실행이 거절될 수 있는 이유는 무엇인가요?

각 질문에 관련 함수 하나와 반례 하나를 적을 수 있다면, 자신의 작은 에이전트 앱에도 같은 설계 질문을 적용할 준비가 된 것입니다.

10핵심 키워드 사전

본문을 다시 읽을 때 곁에 두는 용어표
용어쉬운 설명
Agent Runtime요청·상태·도구·이벤트·취소를 연결하는 실행 계층. 모델 자체와 구분합니다.
Harness모델이 작업하도록 둘러싼 계획·문맥·도구·권한 장치의 묶음입니다.
Session여러 요청과 대화 기록이 이어지는 단위입니다.
Dialog Turn사용자 요청 등을 처리하는 한 작업 단위입니다. 여러 모델 라운드를 포함할 수 있습니다.
Model Round모델을 한 번 호출하고 응답·도구 요청을 처리하는 단위입니다.
Port구체 구현 없이 필요한 기능을 약속한 인터페이스입니다.
Adapter특정 운영체제·프로토콜·제품을 공통 계약에 맞춰 주는 연결 구현입니다.
파사드여러 내부 기능을 사용할 수 있도록 정리한 공통 진입점입니다.
의존성 주입객체가 구현을 직접 만드는 대신 바깥에서 받아 사용하는 방식입니다.
TraitRust에서 타입이 제공해야 할 동작을 정의하는 약속입니다.
enum가능한 경우들을 이름 붙여 표현하는 타입입니다. 각 경우에 서로 다른 데이터를 넣을 수 있습니다.
Arc여러 소유자가 같은 객체를 공유하도록 돕는 참조 계수 포인터입니다.
Send·Sync스레드 사이에서 값을 옮기거나 참조를 공유할 수 있는 성질을 나타내는 Rust의 약속입니다.
async·await완료를 기다리는 동안 실행 기회를 다른 작업에 넘길 수 있게 표현하는 문법입니다.
CancellationToken작업이 정지 요청을 전달받고 확인하도록 쓰는 취소 신호입니다.
IPC프로세스 사이의 통신입니다. 데스크톱 화면이 호스트 명령을 호출하는 경계를 이해할 때 등장합니다.
WebSocket연결을 유지하면서 양방향으로 데이터를 주고받는 통신 방식입니다.
직렬화타입이 있는 값을 JSON 같은 전달·저장 형식으로 바꾸는 일입니다.
이벤트텍스트 조각 수신·도구 진행·상태 변경처럼 이미 일어난 사실을 알리는 데이터입니다.
커서클라이언트가 이벤트를 어디까지 적용했는지 나타내는 위치 정보입니다.
stream_id커서가 어느 런타임 스트림에 속하는지 구분하는 값입니다.
투영 · Projection이벤트를 합치거나 정리해 현재 상태를 표현한 결과입니다.
스냅샷어느 시점의 상태를 한 번에 읽을 수 있게 묶은 자료입니다.
Delta이미 아는 위치 이후에 새로 생긴 변경분입니다.
레지스트리이름으로 도구·구현을 찾고 관리하는 목록입니다. 그 자체로 실행 허가를 뜻하지는 않습니다.
JSON Schema입력 데이터에 어떤 필드와 타입이 필요한지 기술하는 형식입니다.
MCP모델 애플리케이션이 외부 도구·자원에 연결할 때 사용하는 규약입니다.
지연 도구모든 상세 명세를 처음부터 보내지 않고 필요할 때 확인하도록 관리하는 도구입니다.
문맥 압축모델 입력 한도 안에서 작업을 이어 가도록 과거 내용을 요약하고 필요한 부분을 유지하는 처리입니다.
Cargo feature컴파일에 포함할 선택 기능과 관련 의존성을 구성하는 스위치입니다.
잠금 파일의존성 해석에서 선택된 구체 버전을 기록한 파일입니다.
CI변경이 들어왔을 때 빌드·검사·테스트 등을 자동으로 수행하는 과정입니다.

익숙하지 않은 단어가 많아도 모두 한꺼번에 외울 필요는 없습니다. “입력은 어디로 들어오는가, 상태는 누가 갖는가, 실패하면 어떻게 되돌아오는가”라는 질문에 필요한 용어부터 익히면 됩니다.

11참고 링크

제품 안내와 코드 근거를 나눠 읽고, 스냅샷의 한계까지 확인하기

11-1. 프로젝트 공식 안내

11-2. 본문에서 따라간 코드와 설계 문서

설계 문서가 제시하는 목표 구조와 현재 구현은 다를 수 있습니다. 현재 동작을 이해할 때에는 함수의 실제 호출 경로를 함께 살펴보세요.

11-3. 관련 기술 공식 학습 자료

11-4. 현재 상태 (2026-10-23 GitHub 기준)

항목분석 기준 정보
저장소GCWing/OpenBitFun
선정GitHub Trending Rust Weekly #5 · 2026-10-23
스타 / 포크3,099 / 278 · 2026-10-23 GitHub 기준
주 언어Rust · 화면은 TypeScript·React 중심
생성일2026-02-02
최근 push2026-10-23
최신 릴리스v1.0.7 · 2026-10-21
최근 커밋8c012e4 · 2026-10-23
Merge pull request #3535 from bobleer/bob/tab-label-action-space
manifest 버전루트 Rust·웹 패키지 모두 1.0.7. 릴리스 태그와 분석 커밋의 코드가 같다는 뜻은 아님
코드 규모Rust 약 108만 줄, TypeScript·TSX 약 72만 줄. 테스트·생성 코드 포함, third_party/ 제외
패키지 구성루트 Rust 워크스페이스 멤버 54개. 별도 Installer 등은 이 멤버 수에 포함되지 않음
라이선스핵심 코드 MIT. LICENSE의 저작권 표기: 2026 CWing. 외부 의존성·자산의 별도 조건은 유지
쓰기 전에 알아둘 한계
구현의 존재·설계 목표·실제 검증을 구분하세요

코드와 설정의 기준은 커밋 8c012e4입니다. 구현의 존재가 실행·빌드·플랫폼별 동작의 성공을 보장하지는 않습니다. README의 고성능 표현과 자체 벤치마크를 독립 검증값으로 읽지 마세요. 저장소 크기도 실행 성능이나 품질 점수는 아닙니다.

제품 아키텍처 문서는 일부 기능과 Linux 지원을 부분 구현, Sandbox와 OpenHarmony를 계획으로 구분합니다. 공통 포트가 있다는 사실만으로 모든 화면·원격 경로가 같은 수준으로 완성됐다고 볼 수 없습니다. 로컬 서버 진입점도 공개 다중 사용자 서버 API로 설명하지 않습니다.

README는 1.0.0과 기존 0.2.x 데이터가 호환되지 않는다고 명시합니다. 기존 사용자라면 안내된 마이그레이션 경로를 먼저 확인하세요. 파일·프로세스·외부 도구를 사용할 때는 승인 정책과 실제 실행 권한을 검토하고, MIT와 외부 자산의 라이선스 조건을 구분해야 합니다.