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

Konnect 딥다이브
— AI의 한마디를 안전한 회로 편집으로 바꾸는 Rust

MCP 서버

빠른 판단

무엇
구조화된 AI 요청을 KiCad 회로도·PCB 편집·설계 검사·제조 출력으로 연결하는 Rust MCP 서버
이럴 때
KiCad 프로젝트에서 부품 배치·배선·검사를 에이전트와 진행하며 변경 상태와 저장 결과를 검증할 때
입력
KiCad 프로젝트와 부품·배선·검사 요청
결과
수정한 회로도·PCB, 설계 검사 결과와 제조 파일
Konnect는 Claude 같은 AI가 KiCad 10의 회로도와 PCB를 다루도록 연결하는 Rust 기반 MCP 서버입니다. 흥미로운 지점은 도구 개수보다 명령을 검증하고, 정확한 설계를 골라, 변경 결과를 확인하는 과정입니다. Rust의 모듈 분리부터 비동기 통신, 파일 트랜잭션, 데스크톱 화면, 배포 검사까지 하나의 실제 제품으로 배웁니다. 저장소: mixelpixx/Konnect · 스타 1,375 · 포크 165 · AGPL-3.0 · GitHub 수치는 2026-10-23 기준, 코드 설명은 커밋 9488e5f 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

AI와 전자회로 설계 도구 사이에서 일하는 실행 담당자

Konnect는 AI가 보낸 구조화된 요청을 받아 KiCad 프로젝트를 읽고, 편집하고, 검사하는 도구 서버입니다. 사용자가 “저항을 추가하고 두 핀을 연결해 줘”라고 말하면 AI가 필요한 도구와 인자를 고르고, Konnect가 그 요청을 실제 파일 조작이나 KiCad 명령으로 옮깁니다.

AI가 무엇을 할지 결정하더라도, 무엇을 실제로 바꿔도 되는지는 실행 프로그램이 다시 확인해야 합니다. 이 경계를 배우는 것이 이 저장소를 읽는 가장 좋은 이유입니다. AI의 문장 생성 능력과 회로 편집의 정확성은 서로 다른 문제이기 때문입니다.

용어
PCB와 회로도
회로도는 부품의 전기적 연결을 기호와 선으로 표현한 설계도입니다. PCB는 그 연결을 실제 기판의 부품 위치, 구리 배선, 구멍과 층으로 구현한 것입니다. 회로도에서 연결이 맞아도 PCB의 간격이나 제조 조건은 별도로 확인해야 합니다.
용어
MCP (Model Context Protocol)
AI 애플리케이션이 외부 도구를 발견하고 호출하는 공통 약속입니다. 이 저장소에서는 tools/list로 도구 설명과 입력 형식을 받고, tools/call로 도구를 실행합니다. MCP 서버 자체가 언어 모델인 것은 아닙니다.
핵심 비유

AI가 설계 의도를 말하는 기사라면, Konnect는 작업 지시서를 확인하는 작업반장입니다

기사는 “이 저항을 여기로 옮겨요”라고 말합니다. 작업반장은 어느 도면인지, 좌표 단위가 맞는지, 다른 사람이 같은 도면을 열어 수정 중인지 먼저 확인합니다. 옮긴 뒤에는 실제 결과가 지시와 맞는지도 확인합니다.

KiCad는 작업대와 측정 장비에 해당합니다. Konnect는 그 작업대를 AI가 다룰 수 있게 연결하지만, 회로가 현실에서 잘 작동한다는 판단까지 대신 보증하지는 않습니다.

1-1. 한 번의 요청이 도달하는 세 갈래

하려는 일주된 실행 경로코드에서 볼 곳
회로도 편집.kicad_sch를 읽어 구조를 바꾸고 조건을 확인해 저장crates/konnect-schematic-editor/, crates/konnect-sexp/
열린 PCB 편집NNG와 Protobuf를 통해 실행 중인 KiCad 10에 요청crates/konnect-ipc/src/client.rs
검사·제조 파일 출력kicad-cli를 자식 프로세스로 호출crates/konnect-core/src/tools/cli.rs

일부 PCB 작업에는 닫힌 보드 파일을 직접 편집하는 대체 경로도 있습니다. 다만 실시간 통신이 실패했다고 항상 파일을 수정하는 것은 아닙니다. 이 구분은 4절에서 가장 중요하게 다룹니다.

1-2. 도구 호출은 이런 모양이다

다음은 sch_components 도구 묶음을 불러온 뒤 사용할 수 있는 요청 예입니다. JSON의 필드 이름은 crates/konnect-core/src/tools/sch_components.rs의 입력 스키마에 대응합니다. 경로는 실제 설계 파일을 가리켜야 합니다.

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "add_schematic_component",
    "arguments": {
      "schematic": "/designs/blink/blink.kicad_sch",
      "lib_id": "Device:R",
      "x": 100.0,
      "y": 80.0,
      "reference": "R1",
      "value": "10k"
    }
  }
}

lib_id는 부품 기호의 라이브러리 식별자이고, 좌표는 회로도 기준 mm입니다. 도구 설명에는 1.27 mm 격자로 맞춘다고 적혀 있습니다. “저항 하나”라는 자연어도 실행 단계에서는 파일, 종류, 위치, 참조명이라는 구체적인 데이터로 바뀝니다.

2왜 주목받는가

트렌딩 선정 사실과, 코드에서 읽을 수 있는 관심의 이유

2026-10-23의 GitHub Trending Rust Weekly #4로 선정된 프로젝트입니다. 같은 날 GitHub 기준 스타 1,375개, 포크 165개입니다. 아래의 관심 요인은 README와 설계 구조에 근거한 해석입니다. 스타 증가의 원인을 분석한 통계나 사용자 조사 결과로 읽어서는 안 됩니다.

2-1. 대화형 AI가 물리적인 설계 작업으로 이어진다

텍스트 편집을 넘어 부품 배치, 배선, 전기 규칙 검사, 제조용 출력까지 도구화합니다. crates/konnect-core/src/tools/sch_wiring.rs, crates/konnect-core/src/tools/pcb_routing.rs, crates/konnect-core/src/tools/manufacturing.rs를 나란히 보면 하나의 설계가 여러 단계의 산출물을 거친다는 점이 드러납니다. 이 경로들의 공통 상위 디렉토리는 crates/konnect-core/src/입니다.

관심을 끄는 지점은 대화창 자체보다, 대화의 결과가 검증 가능한 설계 변경으로 연결되는 과정입니다. 초보 개발자는 여기서 “AI 기능 추가”가 실제로는 기존 소프트웨어의 입력·출력·실패 조건을 정리하는 작업임을 배울 수 있습니다.

2-2. 앞선 구현에서 겪은 문제를 Rust 구조로 다시 푼다

README는 이 프로젝트를 KiCAD-MCP-Server의 후속 프로젝트라고 설명합니다. 전작의 TypeScript → Python 자식 프로세스 → SWIG 바인딩 경로를 줄이는 것이 재구현의 동기입니다. 전작의 구성과 유지 상태에 관한 설명은 Konnect README 기준이며, 아래 표는 성능 벤치마크가 아닙니다.

비교 축KiCad 직접 조작·CLI 조합전작: README 기준Konnect
AI와의 연결별도 연결 코드를 작성MCP 서버 제공Rust MCP 서버에 도구 카탈로그 통합
호출 경계GUI 조작 또는 명령 실행TypeScript·Python·SWIG 경유서버 내부는 Rust 함수 호출, KiCad와는 IPC·CLI 경계 유지
회로도 변경직접 저장 또는 외부 자동화kicad-skip 및 별도 로더자체 파서·편집기와 충돌 감지 저장
PCB 연동사용자가 조작 경로 선택SWIG 중심, 실험적 IPCKiCad 10 IPC 중심, 조건부 파일 대체 경로
도구 노출자동화 구현에 따라 다름라우터 방식묶음별 불러오기·해제, 호출 기록
도입 조건KiCad와 필요한 스크립트Node.js·Python 환경서버 바이너리 중심, GUI·출력 기능별 외부 조건 존재

장점은 배포 대상과 오류 경계를 줄일 수 있다는 점입니다. 다만 README의 “도구 호출은 함수 호출”은 서버 내부 경로에 관한 설명입니다. KiCad IPC, kicad-cli, 선택적인 외부 라우터까지 한 프로세스로 합쳐졌다는 뜻은 아닙니다.

2-3. 도구가 많아질 때의 AI 사용 비용을 설계한다

모든 도구 설명을 매번 AI에게 전달하면 대화 문맥을 많이 차지합니다. Konnect는 project와 config만 먼저 활성화하고 필요한 묶음을 나중에 추가합니다. README는 기본 목록 약 2K 토큰, 전체 목록 약 23K 토큰으로 설명합니다. 이 수치는 문서의 추정치이며 실제 토크나이저나 클라이언트별 측정값은 아닙니다.

비유

공구 200여 개의 사용설명서를 전부 펼치는 대신, 먼저 공구함 목차를 주고 작업에 맞는 서랍을 엽니다. 다만 서랍을 열었다는 알림을 무시하는 AI 클라이언트도 있으므로, 호환성을 위해 처음부터 모두 펼치는 예외가 필요합니다.

2-4. 소개의 숫자와 실제 범위를 구분하자

표기해석
GitHub 소개: 217개2026-10-23 GitHub 설명문에 적힌 도구 수입니다.
README: 228개·21묶음커밋 9488e5f의 README 표기입니다.
등록부: 합계 228개crates/konnect-core/src/router/registry.rs의 21개 tool_count 합계입니다. 관리 도구는 별도입니다.

도구 개수만으로 프로젝트의 완성도를 판단하기는 어렵습니다. 같은 저장소에서도 소개 문구와 등록부의 갱신 시점이 다를 수 있습니다. 학습할 때는 실제 도구 정의와 입력 스키마를 확인하는 습관이 더 유용합니다.

3기술 스택 전체 지도

핵심 서버, 선택적인 화면, 개발·배포 도구를 나누어 보기

루트 Cargo.toml의 워크스페이스에는 7개 crates/ 패키지와 xtask, 총 8개 멤버가 있습니다. Tauri 뷰어는 명시적으로 제외되어 별도로 빌드됩니다. 같은 저장소에 있다는 사실과 같은 실행 파일에 포함된다는 사실은 구분해서 읽어야 합니다.

아래 “선언”은 의존성 파일에 적힌 허용 범위이고, “잠금”은 해당 커밋의 Cargo.lock에 기록된 선택 버전입니다. 예를 들어 tokio = "1"은 정확히 1.0.0을 고정한다는 뜻이 아닙니다.

3-1. 백엔드: Rust가 맡는 실행·데이터 계층

기술선언 → 잠금역할과 소스 근거
Rust에디션 2021, 최소 1.96, 도구체인 1.96.0Cargo.toml의 rust-version, rust-toolchain.toml의 channel
Tokio1 → 1.53.1features = ["full"]. 비동기 진입점, 입출력, 채널, 잠금, 자식 프로세스
Axum0.8 → 0.8.9crates/konnect/src/transport/http.rs의 HTTP·SSE 통신 계층
Serdeserde 1 → 1.0.229
serde_json 1 → 1.0.151
JSON-RPC 자료형을 Rust 구조체와 JSON 사이에서 변환
JSON Schemajsonschema 0.58 → 0.58.2서버가 도구 입력을 Draft 2020-12 스키마로 검증
nom8 → 8.0.0crates/konnect-sexp/src/parser.rs의 S-expression 파서
NNG·Prostnng 1 → 1.0.1
prost 0.13 → 0.13.5
KiCad IPC의 메시지 운반과 Protobuf 직렬화. crates/konnect-ipc/에서 사용
Reqwest0.13 → 0.13.5부품 정보 등 외부 HTTP 연동. JSON·스트림 기능 사용
SQLiterusqlite 0.40 → 0.40.2bundled 기능으로 SQLite 포함. JLCPCB 부품 데이터 접근
TOML1.1 → 1.1.6+spec-1.1.0crates/konnect/src/config.rs의 설정 읽기
resvg·image=0.48.1 → 0.48.1
image 0.25 → 0.25.10
SVG를 PNG로 바꾸고 픽셀 차이를 계산. crates/konnect-render/
gix0.87 → 0.87.1crates/konnect-vcs/의 Git 저장소 탐색 기반. 이 커밋에서는 작은 기반 구현
topola_specctra0.1.0 → 0.1.0외부 배선 도구와 교환하는 Specctra 형식의 구문 트리·변환

이 표의 의존성 선언은 루트 Cargo.toml과 각 패키지의 Cargo.toml에서 확인할 수 있습니다. konnect-core가 도메인 기능을 조립하고, konnect가 설정·실행·통신 방식을 담당합니다.

3-2. 프론트엔드: 서버와 분리된 Tauri 뷰어

구성실제 선언·파일배울 점
Tauri 2crates/schematic-viewer/Cargo.toml: tauri = "2"
별도 잠금 파일: 2.12.0
Rust 명령과 운영체제의 웹뷰를 연결하는 데스크톱 앱
파일 감시notify = "8" → 8.2.0회로도 변경을 감지해 다시 렌더링
화면crates/schematic-viewer/frontend/index.html, 575줄HTML·CSS·일반 JavaScript로 확대·이동·시트 선택을 구현
앱 설정crates/schematic-viewer/tauri.conf.json: frontendDist = "frontend", 창 1280 × 900별도 웹 개발 서버 없이 정적 프론트엔드를 포함
렌더링 원천crates/schematic-viewer/src/main.rs::render_to_svg_in()kicad-cli sch export svg 결과를 표시

이 뷰어는 브라우저 기반 SaaS 대시보드가 아닙니다. 이 커밋에는 package.json, pyproject.toml, go.mod, Dockerfile이 없으며, 뷰어에 React나 TypeScript 빌드 파이프라인도 없습니다. 화면 기능의 학습 범위를 실제 코드에 맞추어 잡을 수 있습니다.

3-3. 플러그인과 인프라·빌드

구성확인한 설정역할
KiCad 진입점plugin/__init__.py, plugin/settings_dialog.pyKiCad 내부의 pcbnew·wx를 쓰는 Python 실행·설정 연결부
출력 형태crates/konnect/Cargo.toml: 바이너리와 cdylib·rlib독립 MCP 서버와 라이브러리 진입점이 함께 선언됨
Protobuf 생성crates/konnect-ipc/build.rs, prost-build = "0.13"protoc로 crates/konnect-ipc/proto/ 정의를 컴파일
NNG 빌드README의 cmake 요구, nng-sys 의존성NNG C 라이브러리 빌드가 포함되어 순수 Rust 도구만으로 끝나지 않음
일반 CI.github/workflows/ci.ymlLinux·Windows·macOS 검사, 테스트·문서 테스트·Clippy·서식·라이선스 검사
실제 KiCad CI.github/workflows/e2e-kicad.yml: KiCad 10.0.5주간·수동·릴리스 호출 등에서 실제 설치를 이용하는 별도 경로
릴리스.github/workflows/release.yml: Linux x86_64, Windows x86_64, macOS x86_64·ARM64독립 실행 파일과 OS별 PCM 패키지. macOS PCM은 두 아키텍처를 합침
재현 환경flake.nix, flake.lock, Cargo.lockNix 개발·빌드 환경과 Rust 의존성 고정

.github/workflows/ci.yml은 protoc@3.23.4 설치와 Python 플러그인 테스트용 3.11을 명시합니다. 패키징 검사는 Python 3.12를 사용합니다. CI의 버전은 검증 환경의 기록이며 모든 사용자에게 그 Python 버전을 별도 설치하라는 뜻은 아닙니다.

읽기 포인트
버전 고정에는 서로 다른 이유가 있다

rust-toolchain.toml은 컴파일러와 Clippy 변화로 생기는 차이를 줄입니다. resvg = "=0.48.1"은 렌더링 변화가 설계 변화처럼 보이는 것을 줄입니다. 둘 다 재현성을 위한 장치지만, 전자는 빌드 도구를, 후자는 비교 결과를 안정시키려는 선택입니다.

4아키텍처 심화 분석

명령 전달보다 중요한 네 가지 설계 패턴

4-1. 먼저 전체 요청 경로를 그려 보자

사용자: "R1을 옮기고 검사해 줘" | v AI 클라이언트: 도구 선택 + JSON 인자 생성 | +-- 표준 입출력: 한 줄에 JSON 메시지 하나 | crates/konnect/src/transport/stdio.rs | +-- HTTP: POST /mcp, GET /mcp로 SSE 수신 crates/konnect/src/transport/http.rs | v McpHandler::handle_message() / dispatch() | tools/list / tools/call | v 관리 도구 처리 또는 ToolRouter에서 도구 탐색 | 입력 스키마 검증 + 호출 기록 | v ToolDef.handler(args, context) / | \ v v v 회로도 편집 열린 PCB 편집 검사·내보내기 타입 모델 / KiCadIpcClient kicad-cli 부분 문자열 편집 Protobuf + NNG 자식 프로세스 | | | v v v 조건부 원자 저장 KiCad 10 PCB 편집기 ERC·DRC·제조 파일 | +-- 파일 감시 --> 선택적 Tauri 뷰어 도구 결과 + 실패 종류 + 수행 상태(일부 도구) --> AI가 다음 행동 결정

핵심 처리는 crates/konnect-core/src/mcp/handler.rs에 있습니다. handle_message()가 JSON을 요청 자료형으로 바꾸고, dispatch()가 MCP 메서드를 나눕니다. execute_tool()은 호출 시간과 결과 상태를 기록하고, dispatch_tool()이 관리 도구·업무 도구·오류를 구분합니다.

통신 성공, 명령 접수, 설계 변경 완료는 서로 다른 상태이므로 각각의 경계에서 확인해야 합니다. 이 한 문장을 기억하면 아래의 복잡한 코드가 왜 필요한지 이해하기 쉽습니다.

패턴 ① 어댑터 분리: 통신 방식과 업무 로직을 떼어 낸다

crates/konnect/src/main.rs는 설정을 읽고 McpHandler를 만든 뒤 Stdio·Http·Both 중 하나를 선택합니다. 표준 입출력과 HTTP는 같은 handle_message()를 호출합니다. 업무 도구는 요청이 어느 통로로 들어왔는지 몰라도 됩니다.

이를 어댑터 관점으로 읽어 보세요. 표준 입출력 어댑터는 줄 단위 JSON을 읽고 응답에 줄바꿈을 붙입니다. HTTP 어댑터는 같은 JSON 결과를 HTTP 응답으로 감쌉니다. 형식 변환은 바깥쪽에, 부품을 옮기는 규칙은 안쪽에 둡니다.

경계구체적인 처리초보자가 자주 놓치는 점
표준 입출력run_stdio()가 응답을 먼저 쓰고 대기 중인 알림을 비움stdout에 일반 로그를 쓰면 JSON 메시지와 섞임. 로깅은 stderr 사용
HTTPrun_http()가 /mcp와 /health 등록응답이 필요 없는 알림은 202 Accepted. 도구 실패는 별도의 결과 내용으로 판단
도구 실행ToolDef에 이름·설명·스키마·핸들러·보드 접근 계약을 묶음설명문만 써 두는 것으로 입력 검증이 끝나지 않음

crates/konnect-core/src/tools/mod.rs의 tool! 매크로는 비동기 핸들러를 공통 타입으로 감싸 ToolDef::new()에 넣습니다. 그 생성자는 스키마의 허용 필드를 정리하고 검증기를 한 번 컴파일합니다. dispatch_tool()은 필수 인자와 스키마를 검사한 다음에 핸들러를 호출합니다.

// ToolDef의 중요한 필드만 보여 주는 학습용 축약
struct ToolDef {
    name: &'static str,
    input_schema: Value,
    input_validator: Arc<jsonschema::Validator>,
    handler: ToolHandlerFn,
    board_access: BoardAccess,
}

// 개념적 실행 순서: 실제 오류 응답 코드는 생략
validate_required_fields(&tool.input_schema, &args)?;
tool.input_validator.validate(&args)?;
(tool.handler)(&args, context).await

이 예에서 보조 함수 이름은 흐름을 설명하기 위한 것입니다. 실제 필수 인자 검사 함수는 first_missing_required()입니다. 광고한 스키마와 실행할 때의 검증기를 같은 정의에서 만들면 문서와 동작이 어긋날 가능성을 줄일 수 있습니다.

패턴 ② 필요한 기능부터 공개: 카탈로그와 활성 상태를 분리한다

crates/konnect-core/src/router/registry.rs의 ALL_TOOLSETS는 전체 공구함 목록이고, STARTER_KIT는 ["project", "config"]입니다. ToolRouter는 전체 등록부와 현재 활성 도구를 따로 관리합니다. 활성 묶음은 HashSet, 이름별 도구는 HashMap에 담습니다.

ToolRouter::load()는 해당 묶음의 정의를 활성 맵에 넣습니다. 카탈로그는 OnceLock으로 한 번 만들고, 검증기는 Arc로 공유합니다. “나중에 불러오기”는 여기서 주로 AI에게 공개하는 목록을 확장하는 것이지, 매번 별도 플러그인 파일을 내려받거나 동적 라이브러리를 여는 것은 아닙니다.

// MCP 도구 호출의 인자 부분 예: 배선 도구 묶음 공개 요청
{
  "name": "load_toolset",
  "arguments": { "name": "sch_wiring" }
}

// 서버가 목록 갱신을 알리는 메서드
notifications/tools/list_changed

McpHandler::notify_tools_list_changed()는 HTTP의 SSE 수신자와 표준 입출력의 알림 채널 양쪽으로 변경을 전달합니다. 클라이언트가 목록을 다시 읽어야 새 입력 스키마를 알 수 있으므로, 서버 안에서 도구를 활성화하는 것만으로는 충분하지 않습니다.

항목커밋 기준 집계·기본값
업무 도구 전체21개 묶음의 등록 수 합계 228개
기본 활성 업무 도구project 7개 + config 7개 = 14개
항상 공개하는 관리 도구기본 7개. Unix 독립 서버의 표준 입출력 전용 모드에서는 reload_server 1개 추가
처음 보이는 도구 수일반적으로 21개, 위 Unix 모드에서는 22개. 전체 사전 공개 설정·클라이언트 예외에 따라 달라짐
모두 활성화한 경우업무 228개 + 관리 7개 = 235개. 위 Unix 모드에서는 236개라는 정적 집계
자동 확장 설정auto_load_toolsets = false, eager_toolsets = false가 기본값

McpHandler::adapt_to_client()는 이름이 claude-ai로 시작하는 클라이언트를 목록 캐시 예외로 취급하여 처음부터 전체 묶음을 활성화합니다. 모든 클라이언트가 동적 목록을 잘 지원한다고 가정하지 않는, 실제 호환성 설계의 사례입니다.

패턴 ③ 변경 전제를 확인하는 파일 저장

회로도 계층에는 서로 다른 두 표현이 있습니다. crates/konnect-sexp/src/parser.rs의 SexpNode는 읽기용 구문 트리이고, 같은 패키지의 crates/konnect-sexp/src/writer.rs는 지정한 문자열 구간만 고칩니다. 한편 crates/konnect-schematic-editor/src/schematic/mod.rs는 Schematic·Symbol 같은 타입으로 편집하고 다시 직렬화합니다.

crates/konnect-core/src/tools/sch_components.rs의 일반 CRUD는 타입 기반 편집기를 사용하며 핀 좌표 계산 등에는 konnect-sexp 기능을 함께 씁니다. 따라서 “모든 쓰기가 문자열 치환이다” 또는 “모든 편집이 파일 전체의 바이트를 보존한다”고 설명하면 틀립니다.

용어
왕복 보존과 원자 저장은 다른 문제다
왕복 보존은 읽고 다시 쓴 뒤에도 기존 설계 정보가 남는 성질입니다. 원자 저장은 한 파일이 중간까지만 기록된 상태로 보이지 않도록 교체하는 방식입니다. 데이터 의미 보존, 서식 보존, 동시 수정 감지, 장애 복구는 각각 따로 검토해야 합니다.

부분 편집에서 중요한 구현은 apply_edits()의 뒤쪽 바이트 위치부터 적용하는 정렬입니다. 앞에서 긴 문자열을 삽입하면 뒤쪽 위치가 밀리지만, 뒤에서 고치면 앞쪽 기준 위치는 유지되기 때문입니다.

// crates/konnect-sexp/src/writer.rs의 실제 구현
pub fn apply_edits(mut content: String, mut edits: Vec<SexpEdit>) -> String {
    edits.sort_by_key(|e| std::cmp::Reverse(e.start));
    for edit in edits {
        assert!(edit.start <= edit.end, "Edit start > end");
        assert!(edit.end <= content.len(), "Edit end out of bounds");
        content.replace_range(edit.start..edit.end, &edit.replacement);
    }
    content
}

이 함수의 인덱스는 글자 번호가 아니라 바이트 위치입니다. UTF-8 문자의 중간을 잘라서는 안 되며, 겹치는 편집 구간의 타당성도 호출 쪽에서 보장해야 합니다. 정렬 하나가 모든 입력을 안전하게 만들어 주지는 않습니다.

안전 장치실제 함수와 역할
읽기 일관성read_consistent()가 문서 잠금에 참여하여 내용을 읽음
수정 충돌 감지write_atomic_if_unchanged()가 현재 내용과 기대한 원문을 정확히 비교. 다르면 Conflict
파일 교체write_atomic_unlocked_with()가 같은 디렉토리의 임시 파일에 쓰고 flush·sync_all·rename 수행
편집기 충돌 회피쓰기 전과 교체 직전에 KiCad 문서 잠금을 확인하여 열린 설계 파일의 직접 교체를 거부
모르는 필드 보존unmodelled_children()가 타입 모델로 재구성하지 않는 하위 노드도 유지
여러 파일의 복구crates/konnect-sexp/src/transaction.rs::commit_file_transaction()이 변경 전제 확인 → 저널 저장 → 파일별 반영 → 검증 → 저널 삭제

여러 파일의 트랜잭션은 운영체제가 모든 파일을 동시에 바꾸는 기능이 아닙니다. recover_file_transactions()는 이미 새 내용인 파일은 두고, 이전 내용인 파일은 변경을 마저 적용합니다. 예상 밖으로 달라진 내용은 덮어쓰지 않고 충돌로 남깁니다. 즉 재시작 후 앞으로 복구할 수 있는 저널 방식입니다.

패턴 ④ 실행 상태의 권위: 열린 보드와 저장 파일을 혼동하지 않는다

열린 KiCad 보드에는 아직 저장하지 않은 변경이 있을 수 있습니다. 통신 장애를 “KiCad가 없다”고 단정하고 디스크 파일을 편집하면 화면과 파일이 서로 다른 설계가 됩니다. crates/konnect-core/src/tools/board_session.rs의 BoardSessionMemory는 보드를 실시간으로 관찰한 사실을 기억합니다.

관찰한 상황가능한 판단
KiCad에 도달했고 작업이 거부됨거부 이유를 반환. 파일 편집으로 우회하지 않음
KiCad에 도달하지 못함파일 대체 경로를 지원하는 도구만, 잠금·이전 관찰 등 추가 조건을 확인
이전에 실시간 보드를 봤고 잠금이 남음미저장 상태의 가능성이 있으므로 파일 대체 편집 거부
실시간 관찰 당시 있던 잠금이 사라짐authorize_file_fallback()이 정상 종료의 근거로 보고 관찰 기록을 해제할 수 있음
변경 요청 후 결과 확인이 불확실함성공·실패를 추측해 재시도하지 않고 상태를 다시 확인

실제 IPC 구현의 KiCadIpcClient::run_commit()은 begin_commit()으로 변경 묶음을 열고 작업 성공 시 push_commit()으로 반영하며, 확인된 실패에는 drop_commit()을 시도합니다. 다만 IpcOutcomeUnknown처럼 반영 여부가 불확실하면 취소 요청도 보내지 않으며, LateReply는 별도의 복구 경로를 거칩니다. 이 묶음은 KiCad의 되돌리기 단위와 연결됩니다. 마지막 응답을 받지 못한 경우처럼 반영 여부가 모호한 상황은 일반적인 사전 거부와 구별해야 합니다.

비유

은행 이체 요청의 응답이 끊겼다고 같은 이체를 다시 누르면 중복 출금될 수 있습니다. 부품 이동도 비슷합니다. “응답을 못 받음”과 “아무것도 바뀌지 않음”은 같은 사건이 아닙니다.

crates/konnect-core/src/outcome.rs에는 complete·partial·failed·uncertain 상태가 있습니다. 이 공통 결과 형식을 채택한 도구는 해당 커밋에서 4개로 한정됩니다. 저장소 전체의 모든 도구가 이미 동일한 결과 계약을 갖는다고 일반화해서는 안 됩니다.

5디렉토리 구조 해부

어디에서 시작하고, 어디까지 내려가야 하는가
Konnect/ ├── Cargo.toml / Cargo.lock 워크스페이스와 의존성 ├── rust-toolchain.toml Rust 1.96.0 ├── .cargo/config.toml cargo xtask 별칭 ├── crates/ │ ├── konnect/ 실행 파일·라이브러리 진입점 │ │ ├── src/main.rs 설정과 실행 모드 선택 │ │ ├── src/ffi.rs 외부 라이브러리 호출 경계 │ │ ├── src/transport/ 표준 입출력·HTTP │ │ └── tests/ 프로토콜·설치·실제 KiCad 검사 │ ├── konnect-core/ 업무 조립 계층 │ │ ├── src/mcp/ 요청·응답·실행 분기 │ │ ├── src/router/ 카탈로그·활성 묶음·관리 도구 │ │ ├── src/tools/ 회로도·보드·부품·제조 작업 │ │ └── tests/fixtures/ 실제 형식의 재현용 설계·보고서 │ ├── konnect-sexp/ 읽기 파서·부분 편집·저장·복구 │ ├── konnect-schematic-editor/ 타입 기반 회로도·기호 모델 │ ├── konnect-ipc/ KiCad 통신 클라이언트 │ │ ├── proto/ Protobuf 메시지 정의 │ │ └── build.rs 메시지 코드 생성 │ ├── konnect-render/ SVG 래스터화·픽셀 비교 │ ├── konnect-vcs/ Git 연동의 작은 기반 구현 │ └── schematic-viewer/ 별도 Tauri 앱 │ ├── frontend/index.html 화면 전체 │ └── src/main.rs 감시·렌더링·Tauri 명령 ├── plugin/ KiCad의 Python 실행·설정 연결부 ├── packaging/ OS별 PCM 묶기·메타데이터 검사 ├── .github/workflows/ 일반 CI·실제 KiCad CI·릴리스 ├── docs/ 설계·도구 개발·신뢰성 계약 ├── examples/ AI 클라이언트 연결 설정 예제 ├── resources/ 로고 등 배포 리소스 ├── xtask/ 문서의 도구 개수 갱신 도구 └── flake.nix / flake.lock Nix 환경

폴더 이름을 외우기보다 요청 한 개가 통과하는 파일을 연결하면 큰 저장소도 읽을 수 있습니다. 처음부터 모든 도구 구현을 읽으려 하면 비슷한 JSON 스키마와 긴 테스트에 묻히기 쉽습니다.

읽는 순서질문찾아갈 파일
1. 실행누가 서버를 시작하는가?crates/konnect/src/main.rs
2. 메시지메서드와 도구 이름은 어떻게 나누는가?crates/konnect-core/src/mcp/handler.rs
3. 등록내가 찾는 도구가 어느 묶음에 있는가?crates/konnect-core/src/router/registry.rs
4. 한 기능인자 검사 후 무엇을 바꾸는가?crates/konnect-core/src/tools/sch_components.rs
5. 저장읽은 뒤 파일이 바뀌면 어떻게 되는가?crates/konnect-sexp/src/writer.rs
6. 실패 사례작성자가 어떤 실수를 예상했는가?같은 파일의 #[cfg(test)]와 각 패키지의 tests/

5-1. 실제 줄 수로 보는 무게중심

커밋 9488e5f에서 Git이 추적하는 파일의 물리적 줄 수입니다. 빈 줄·주석·단위 테스트·통합 테스트를 모두 포함하며, 빌드 산출물은 포함하지 않습니다. 줄 수는 실행 성능이나 구현 품질의 점수가 아니라 읽을 범위를 가늠하는 지표입니다.

범위파일 수줄 수
Rust 전체147170,956
Python71,443
Protobuf 정의123,370
HTML1575 — 내부 CSS·JavaScript 포함
셸·PowerShell2283
YAML 워크플로·설정5752

Rust 중 konnect-core가 124,553줄, konnect-ipc가 16,517줄, konnect-sexp가 12,474줄입니다. 기능 구현과 실패 재현 테스트가 업무 계층에 집중되어 있습니다. 반면 konnect-vcs는 84줄의 기반 코드이므로 완성된 버전 관리 제품처럼 설명하면 안 됩니다.

# 저장소 루트에서 읽기만 하며 Rust 물리적 줄 수 재기
git ls-files -z '*.rs' | python3 -c '
import sys
from pathlib import Path
paths = [p for p in sys.stdin.buffer.read().split(b"\0") if p]
print(sum(len(Path(p.decode()).read_bytes().splitlines()) for p in paths))
'

이 방식은 인라인 테스트를 “구현 코드”와 자동으로 나누지 않습니다. 테스트 비중을 알고 싶다면 파일명뿐 아니라 #[cfg(test)] 내부까지 분석해야 합니다. 여기서는 전체 물리적 줄 수라는 일관된 기준만 사용합니다.

6학습 포인트 (기술별)

라이브러리 이름보다 설계 선택의 이유를 배운다

기술을 배웠다는 기준은 코드를 따라 쓰는 것이 아니라, 실패 사례를 하나 더 설명할 수 있게 되는 것입니다. 다음 여섯 주제는 각각 작은 읽기 과제와 독립적인 실습으로 확장할 수 있습니다.

6-1. Rust: 데이터를 함께 쓰는 비용을 드러내는 타입

McpHandler는 Arc<ToolContext>를 공유합니다. ToolRouter는 RwLock<HashMap<String, ToolDef>>로 활성 도구 맵을 보호합니다. ToolDef를 복제해도 컴파일한 검증기는 Arc로 공유하므로 검증기를 매 호출마다 새로 만드는 구조가 아닙니다.

배울 것: 소유권과 복사 비용, 읽기·쓰기 잠금의 차이, 트레이트 객체로 서로 다른 비동기 함수를 같은 칸에 담는 방법입니다. ToolHandlerFn의 Pin<Box<dyn Future...>>는 비동기 계산을 공통 반환 타입으로 감싸기 위한 표현부터 이해하면 됩니다.

작은 실습

crates/konnect-core/src/router/mod.rs의 loaded_tools_reuse_their_compiled_input_schema 테스트를 읽고, 왜 값의 동등성 대신 Arc::ptr_eq()를 확인하는지 설명해 보세요. 답은 “같은 내용을 다시 만들었다”와 “같은 검증기를 공유한다”가 다르기 때문입니다.

6-2. 비동기: 오래 기다리는 코드의 위치를 정한다

NNG 클라이언트는 동기식 API를 사용합니다. crates/konnect-core/src/tools/mod.rs::with_ipc_classified()는 이 일을 tokio::task::spawn_blocking()으로 보내 비동기 실행 스레드에서 직접 오래 기다리는 일을 줄입니다. 반면 kicad-cli는 Tokio의 자식 프로세스 API로 기다립니다.

crates/konnect-ipc/src/client.rs에는 기본 명령 수신 대기 30초, 송신 대기 5초, 층 이름 조회 전체 대기 예산 10초가 있습니다. 도구마다 필요한 제한이 다르며, 여러 작은 조회가 누적되면 전체 지연은 커집니다.

실습 아이디어: “요청 전에 연결 실패”, “명령을 보낸 뒤 시간 초과”, “KiCad가 명시적으로 거부”를 세 칸으로 나누세요. 각각을 재시도해도 되는지, 어떤 상태 확인이 필요한지 적으면 비동기 문법보다 중요한 실패 모델을 익힐 수 있습니다.

6-3. 파서와 좌표: 문법이 맞아도 도메인 의미는 틀릴 수 있다

crates/konnect-sexp/src/parser.rs의 구문 트리는 Atom·Str·List의 재귀 구조입니다. 예를 들어 (at 10 5 90)은 단순한 문자열 네 조각이 아니라 위치와 방향을 나타내는 한 노드입니다. 구문 분석 뒤에는 단위와 좌표계를 해석하는 단계가 남습니다.

// 실제 SexpNode의 세 가지 경우
pub enum SexpNode {
    Atom(String),
    Str(String),
    List(Vec<SexpNode>),
}

// 기호 로컬 좌표 → 회로도 좌표의 처리 순서
Y축 방향 전환 → 회전 → 미러 → 부품 원점만큼 이동

crates/konnect-sexp/src/geometry.rs::transform_pin()은 라이브러리의 위쪽이 양수인 Y축을 화면의 아래쪽이 양수인 Y축으로 바꾼 뒤 회전합니다. 미러는 회전 뒤에 적용합니다. 순서를 바꾸면 90도·270도 배치에서 다른 핀 위치가 나올 수 있습니다.

로컬 핀·부품 원점변환 조건기대 위치(mm, 반올림)
핀 (2.54, 0), 원점 (10, 5)0도, 미러 없음(12.54, 5.00)
동일90도, 미러 없음(10.00, 2.46)
동일90도, mirror_x = true(10.00, 7.54)

또한 crates/konnect-sexp/src/schematic.rs::extract_lib_pins_for_unit()은 Name_N_M 형식의 하위 기호에서 공통 유닛 0과 선택한 유닛의 핀만 모읍니다. 기호 바로 아래의 핀과 이 접미사가 없는 하위 기호의 핀은 항상 포함합니다. 이름의 숫자 의미를 모르면 다른 증폭기 유닛의 핀을 같은 위치에 겹쳐 해석할 수 있습니다. 자료형의 정확성과 전자회로 의미의 정확성을 함께 살펴보세요.

6-4. 스키마와 오류: AI도 검증이 필요한 클라이언트다

add_schematic_component는 schematic·lib_id·x·y를 필수로 요구하고 unit의 최솟값을 1로 둡니다. 좌표에 문자열 "100"을 보내는 것과 숫자 100을 보내는 것은 다릅니다. 입력을 조용히 기본값으로 바꾸는 대신 잘못된 필드를 알려 주어야 AI도 올바르게 복구할 수 있습니다.

배울 것: JSON이 문법적으로 파싱되는지, 입력 스키마에 맞는지, 실제 설계에서 수행 가능한지는 서로 다른 검사입니다. 예를 들어 숫자 좌표가 유효해도 대상 기호가 존재하지 않으면 작업은 성립하지 않습니다.

실습 아이디어: 필수 키 누락, 타입 오류, 범위 오류, 존재하지 않는 라이브러리, 변경 후 검증 실패를 분리해 기대 응답을 적으세요. crates/konnect-core/src/mcp/error.rs의 구조화된 오류와 crates/konnect-core/src/outcome.rs의 수행 상태를 함께 읽으면 “오류 문구”와 “실제 변경 여부”의 차이를 볼 수 있습니다.

6-5. 화면 갱신과 재현 가능한 시각 비교

crates/schematic-viewer/src/main.rs의 QUIET_WINDOW는 600 ms입니다. drain_until_quiet()는 연속 저장 이벤트를 모으고, 600 ms의 조용한 구간과 최대 대기 기준인 5초에 따라 렌더링 시점을 정합니다. is_relevant_sch_change()는 자동 저장·잠금 이름을 걸러 내고, 계층 시트 순회는 최대 깊이 20과 조상 집합으로 순환을 막습니다.

별도의 crates/konnect-render/src/lib.rs::svg_to_png()는 화면에 표시되는 텍스트 요소가 있는 SVG를 거부하고, KiCad가 글자를 경로로 내보낸 SVG를 일정한 렌더러로 처리합니다. RENDERER_ID는 resvg-0.48.1입니다. 렌더러 버전이나 글꼴이 달라 생긴 픽셀 차이를 설계 수정으로 오인하지 않으려는 선택입니다.

비유

어제와 오늘의 도면 사진을 비교하는데 카메라 초점과 조명이 바뀌면, 달라진 픽셀이 도면 때문인지 촬영 조건 때문인지 모릅니다. 시각 테스트는 먼저 “같은 카메라로 찍기”부터 해결해야 합니다.

실습 아이디어: 파일 이벤트가 0 ms, 200 ms, 500 ms에 왔을 때 600 ms의 조용한 구간이 언제 완성되는지 시간선을 그리세요. 마지막 이벤트 뒤 약 600 ms가 기준이므로 작업 시간 등을 제외하면 1,100 ms 무렵입니다. 첫 이벤트 직후부터 재는 방식과 구별해 보세요.

6-6. 검증 증거에 설계의 신원을 붙인다

crates/konnect-core/src/design_hash.rs::design_state_hash()는 설계 파일 경로를 정렬하고 줄바꿈을 LF로 정규화한 뒤 SHA-256을 계산합니다. 각 파일은 path\0content\0 형태로 구분해 합칩니다. Windows의 CRLF와 다른 운영체제의 LF 때문에 같은 설계를 다른 것으로 보는 일을 줄입니다.

.konnect/의 파생 상태는 설계 해시에서 제외합니다. 검사 결과가 설계 해시를 기록했는데 그 기록 때문에 설계 해시가 다시 바뀌면 순환 문제가 생기기 때문입니다. “어떤 설계에 대한 검사 결과인가”를 명확히 하는 원리는 문서 빌드·데이터 처리·AI 평가에도 적용할 수 있습니다.

스스로 확인할 질문

어떤 검사가 통과한 직후 부품 위치를 바꾸었다면, 이전 통과 결과를 계속 사용해도 될까요? 검사 이름과 시간만 저장해서는 부족합니다. 검사 대상의 내용 식별자까지 함께 저장해야 그 결과가 현재 설계에도 해당하는지 판단할 수 있습니다.

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

서버를 읽는 환경과 전체 PCB 작업 환경은 다르다

README에는 CPU 코어 수나 RAM의 공식 최소 수치가 명시되어 있지 않습니다. 서버 바이너리만의 요구와 KiCad GUI·부품 데이터·외부 라우터를 포함한 전체 환경을 분리해 판단해야 합니다. 다음 표는 기능별 의존 조건입니다.

사용 범위필요한 조건근거·주의점
소스 학습텍스트 편집기, Git, 줄 수 집계용 Python 등KiCad나 언어 모델을 실행하지 않아도 구조와 테스트를 읽을 수 있음
MCP 서버 연결해당 OS용 Konnect 실행 파일과 MCP 클라이언트모델 실행·요금·네트워크 조건은 사용하는 AI 서비스에 따라 별도
회로도 파일 처리설계 파일과 작업별 필요한 심벌 라이브러리파싱·직접 편집에는 KiCad GUI가 필수는 아님. 라이브러리 조회·출력은 추가 조건 확인
열린 PCB 실시간 편집KiCad 10 PCB 편집기에서 대상 보드를 열고 API 활성화KICAD_API_SOCKET·설정·자동 탐색을 통해 올바른 IPC 주소 확보
ERC·DRC·출력kicad-cli 실행 파일과 관련 라이브러리설치 위치가 검색되지 않으면 kicad_cli 경로 설정
선택적 뷰어OS 웹뷰 환경과 별도 뷰어 바이너리Linux 빌드 워크플로는 GTK 3·WebKitGTK 4.1 개발 패키지 등을 설치
부품 검색JLCPCB 데이터와 해당 저장 공간README의 약 250만 부품 카탈로그는 기능 설명. 실제 DB 크기와 메모리 사용량 수치는 별도
외부 자동 배선호환되는 Freerouting·Java 환경 등선택 기능. check_freerouting으로 엔진·호환성 조건을 구분하는 설계
소스 빌드Rust 1.96.0, protoc, CMake와 플랫폼 빌드 도구NNG의 C 빌드와 Protobuf 생성 포함. 뷰어는 별도 시스템 의존성 추가

릴리스 워크플로에 적힌 대상은 x86_64-unknown-linux-gnu, x86_64-pc-windows-msvc, x86_64-apple-darwin, aarch64-apple-darwin입니다. 이 목록이 ARM Linux 등 모든 조합의 지원을 의미하지는 않습니다. 패키징 메타데이터는 KiCad 범위를 10.0부터 10.99로 선언합니다.

GPU는 Konnect 서버가 요구하는 구성 요소로 명시되어 있지 않습니다. 이 서버는 LLM 가중치를 로컬에 올리는 추론 서버가 아닙니다. 로컬 모델을 연결하면 그 모델의 하드웨어 요구가 별도로 생기며, KiCad의 큰 보드·3D 작업도 설계 크기에 따라 자원을 사용합니다.

7-1. 설정 한 항목이 실제로 무엇을 바꾸는가

# 설정 형식을 이해하기 위한 예
transport = "stdio"
kicad_cli = "kicad-cli"
auto_load_toolsets = false
eager_toolsets = false

# transport를 "http" 또는 "both"로 바꿀 때 쓰는 기본 주소
http_address = "127.0.0.1:3000"

crates/konnect/src/config.rs::default_config_paths()는 현재 디렉토리의 konnect.toml, settings.json, 실행 파일 주변 설정, 사용자 설정 순으로 후보를 만듭니다. 기본 정책은 처음 존재하는 파일 하나를 읽는 것이며 여러 설정을 합치지 않습니다. --config는 명시적 경로를 선택합니다.

HTTP 계층은 기본적으로 루프백 주소에 묶이며 Origin이 있으면 로컬 출처인지 검사합니다. validate_origin()에서 출처 없는 네이티브 요청은 통과합니다. 이 검사를 사용자 인증이나 공개 인터넷 서비스용 접근 제어와 같은 것으로 이해하면 안 됩니다.

요구사항을 읽는 법
“단일 바이너리”가 모든 기능의 무의존성을 뜻하지는 않는다

README의 실행 파일 20~25 MB, 다운로드 약 9 MB는 문서의 안내 수치입니다. KiCad 설치, 뷰어의 웹뷰, 선택적인 Java 라우터와 부품 데이터까지 합친 설치 크기가 아닙니다. 모든 플랫폼에서 완전 정적 링크를 보장하는 실측 결과로도 해석할 수 없습니다.

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

읽기 → 예상 → 근거 찾기 순서로 진행하는 다섯 과제

실습의 결과물은 실행 화면 한 장보다, 입력과 기대 결과와 실패 조건을 설명한 작은 기록이면 좋습니다. 아래 과제는 대부분 소스 읽기와 종이 위 추적으로 시작할 수 있습니다. 구현 실험으로 확장할 때는 독립된 연습용 데이터와 프로젝트를 사용하세요.

과제 1 입문 · 30~45분

JSON 요청 하나의 여행 지도 만들기

목표: 1절의 add_schematic_component 요청이 도구 실행까지 어떻게 도착하는지 그립니다.

  1. crates/konnect/src/main.rs에서 표준 입출력 모드 선택 지점을 찾습니다.
  2. run_stdio() → handle_message() → dispatch() → execute_tool() → dispatch_tool()을 연결합니다.
  3. 도구 묶음을 아직 불러오지 않았을 때와 필수 좌표 x가 없을 때를 분기합니다.

완료 기준: 각 화살표 옆에 파일 경로를 적고, “도구가 비활성 상태”와 “활성 도구의 입력이 잘못됨”을 다른 오류로 설명할 수 있습니다. 기본 설정에서 자동 불러오기는 꺼져 있다는 점도 표시하세요.

과제 2 중급 · 1~2시간

저장 충돌을 세 장면으로 분해하기

목표: write_atomic_if_unchanged()가 필요한 이유를 설명합니다. 다음 시간선에서 A·B·C는 서로 다른 완전한 파일 내용입니다.

  1. 도구가 내용 A를 읽고 C로 바꾸려는 사이, 다른 프로그램이 B를 저장했다고 가정합니다.
  2. 현재 파일과 기대 원문을 비교하는 지점을 찾아 결과를 예측합니다.
  3. 임시 파일을 쓰던 중 종료, 파일 교체 후 종료 상황도 따로 그립니다.

완료 기준: 첫 상황에서는 B를 덮어쓰지 않고 충돌을 반환한다고 설명합니다. 임시 저장·파일 교체·교체 후 확인이 각각 무엇을 막는지, 다중 파일 저널은 왜 별개인지 구별하세요.

시간 ───────────────────────────────────────────> 도구 A 읽음 C 계산 저장 시도 다른 프로그램 B 저장 디스크 A ────────────> B ─────────> B 유지 | 기대 A와 현재 B가 달라 충돌
과제 3 중급 · 1~2시간

핀 좌표와 유닛 선택의 기대값 표 작성하기

목표: transform_pin()과 extract_lib_pins_for_unit()을 숫자 예제로 이해합니다.

  1. 원점 (10, 5), 로컬 핀 (2.54, 0)을 0·90·180·270도로 회전한 위치를 계산합니다.
  2. 90도에 mirror_x를 추가하고, 미러를 먼저 적용하면 결과가 달라지는지 비교합니다.
  3. 유닛 0·1·2의 핀이 있는 가상 라이브러리에서 유닛 1을 선택했을 때 남을 핀을 적습니다.

완료 기준: 회전·미러의 순서와 Y축 방향을 말로 설명하고, 선택 유닛 외의 핀이 섞이면 어떤 연결 오류가 생길지 설명합니다. 부동소수점 기대값 비교에는 작은 오차 허용이 필요하다는 점도 기록하세요.

과제 4 고급 · 반나절

AI가 복구할 수 있는 오류 계약 설계하기

목표: 가상의 “부품 여러 개 이동” 도구에 입력 스키마와 결과 계약을 설계합니다. 실제 저장소에 기능을 추가하지 않아도 됩니다.

  1. 보드 경로, 부품 참조명, x·y 숫자를 필수로 정하고 모르는 필드의 허용 여부를 정합니다.
  2. 모두 성공, 일부 성공, 변경 전 거부, 변경 여부 불확실의 네 상태를 정의합니다.
  3. 성공한 항목과 실패한 항목을 구분하고 어떤 항목만 재시도할 수 있는지 적습니다.

완료 기준: 각 상태에 입력 예와 결과 예를 한 쌍씩 붙입니다. crates/konnect-core/src/outcome.rs의 ADOPTED_OUTCOME_TOOLS와 비교하여 공통 형식을 전체 도구로 넓히기 전에 어떤 검증이 필요한지 설명하세요.

과제 5 고급 · 반나절~하루

설계 해시와 복구 저널의 검증 계획 만들기

목표: 운영체제 차이와 중간 종료가 있어도 확인할 수 있는 테스트 사례를 설계합니다.

  1. 같은 파일의 LF·CRLF 버전은 같은 해시인지, 내용 한 글자가 바뀌면 달라져야 하는지 적습니다.
  2. 파일 나열 순서와 상대 경로 이름이 바뀌는 경우를 구분합니다.
  3. 두 파일 중 하나만 새 내용인 저널과, 한 파일이 예상 밖의 내용인 저널의 복구 결과를 비교합니다.

완료 기준: 최소 6개 사례에 대해 변경 대상·기대 결과·보존할 증거를 표로 작성합니다. 복구가 원래 상태로 되돌리기인지, 남은 변경을 마저 적용하기인지도 명시하세요. 참고 구현은 crates/konnect-core/src/design_hash.rs와 crates/konnect-sexp/src/transaction.rs입니다.

8-1. 구현하기 전에 검색으로 사실 확인하기

# 다음은 파일을 바꾸지 않는 읽기 명령
rg -n 'STARTER_KIT|ALL_TOOLSETS' crates/konnect-core/src/router/registry.rs
rg -n 'dispatch_tool|first_missing_required' crates/konnect-core/src/mcp/handler.rs
rg -n 'write_atomic_if_unchanged|Conflict' crates/konnect-sexp/src/writer.rs
rg -n 'recover_file_transactions' crates/konnect-sexp/src/transaction.rs
rg -n 'transform_pin|mirror_x' crates/konnect-sexp/src/geometry.rs

검색 결과 한 줄만 보고 결론 내리지 말고 함수 전체와 호출 지점까지 읽으세요. 특히 오류가 반환되는 시점이 변경 전인지 후인지 확인하면 재시도 정책을 더 정확하게 정할 수 있습니다.

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

6주 동안 한 요청을 이해하는 깊이를 늘려 간다

주차는 학습 순서의 예시입니다. Rust가 처음이면 1주차를 더 길게 잡고, 전자회로 경험이 없다면 저항·기호·넷·풋프린트의 차이를 먼저 익히세요. 매주 새로운 기능을 더하기보다, 같은 요청의 입력·실행·저장·검증을 차례로 깊게 이해해 보세요.

주차학습 주제읽을 코드완료 산출물
1주차Rust 구조체·열거형·Option·Result·소유권crates/konnect-core/src/mcp/protocol.rs, crates/konnect-sexp/src/parser.rsJSON 요청과 Rust 자료형을 대응시킨 표
2주차JSON-RPC·MCP·입력 스키마·핸들러crates/konnect-core/src/mcp/handler.rs, crates/konnect-core/src/tools/mod.rs과제 1의 요청 경로와 입력 오류 사례 5개
3주차구문 트리·문자열 편집·좌표계·유닛crates/konnect-sexp/src/geometry.rs, crates/konnect-sexp/src/schematic.rs과제 3의 좌표·핀 선택 기대값 표
4주차잠금·낙관적 충돌 검사·원자 저장·저널crates/konnect-sexp/src/writer.rs, crates/konnect-sexp/src/transaction.rs과제 2의 시간선과 장애 복구 행렬
5주차Tokio·NNG·Protobuf·실시간/파일 상태 경계crates/konnect-ipc/src/client.rs, crates/konnect-core/src/tools/board_session.rs접속 불가·거부·불확실을 구별한 재시도 규칙
6주차파일 감시·시각 비교·통합 테스트·배포crates/schematic-viewer/src/main.rs, .github/workflows/실습 결과를 묶은 짧은 설계 검토서

9-1. 테스트를 읽을 때는 검증 환경도 같이 읽는다

.github/workflows/ci.yml은 cargo test --workspace --locked --lib --tests와 문서 테스트를 분리합니다. 뷰어는 워크스페이스 밖이므로 별도 작업에서 검사합니다. “워크스페이스 전체 테스트”라는 말이 저장소의 모든 코드 검사를 뜻하지 않는 사례입니다.

crates/konnect-core/tests/conformance_test.rs는 KiCad가 만든 데모 회로도를 기준으로 읽기·쓰기 동작을 확인하는 테스트 모음입니다. KiCad 데모가 없으면 건너뛸 수 있으므로, 테스트 파일이 존재한다는 사실만으로 실제 KiCad 검증이 수행되었다고 판단해서는 안 됩니다.

.github/workflows/e2e-kicad.yml은 KiCad 10.0.5를 설치한 Windows 환경에서 설계 생성·배선·ERC·Gerber·DRC 경로를 다루도록 구성되어 있습니다. 릴리스 워크플로도 이 별도 검증을 호출합니다. 이는 워크플로의 의도와 설정에 대한 설명이며 특정 실행의 통과 기록을 뜻하지 않습니다.

9-2. 작은 도구 하나로 다시 설명해 보기

"부품 하나 추가"를 이해했다고 말하려면 입력: 필수 키, 타입, 좌표 단위, 라이브러리 식별자 | 검증: 대상 파일, 기호 존재, 계층·유닛 정보 | 편집: 모르는 필드와 다른 기호를 보존 | 저장: 원문 비교, 잠금 확인, 원자 교체 | 확인: 저장된 결과와 요청의 관계를 관찰 | 복구: 거부·부분 수행·불확실을 구별하여 다음 행동 결정

이 흐름을 자신의 작은 파일 변환기에도 적용해 보세요. 전자회로 전용 지식은 달라도, 입력 계약과 안전한 저장과 검증 증거를 나누는 방법은 그대로 가져갈 수 있습니다.

10핵심 키워드 사전

이 저장소를 읽다가 다시 찾아볼 개념들
용어쉬운 설명
KiCad회로도와 PCB를 설계하는 전자설계 도구입니다. Konnect가 대신 구현한 것이 아니라 연결해서 사용하는 대상입니다.
심벌회로도에서 부품을 나타내는 기호입니다. 핀과 전기적 의미를 표현합니다.
풋프린트PCB 위에 부품을 실장하기 위한 패드·외곽 등의 형상입니다. 심벌과 역할이 다릅니다.
참조명R1·C2처럼 설계에서 부품을 구별하는 이름입니다. 라이브러리의 부품 종류 이름과 구별합니다.
넷전기적으로 같은 연결에 속한 핀·패드의 묶음입니다. 화면에서 선이 가까워 보이는 것과 실제 연결은 다릅니다.
유닛한 부품 기호를 여러 기능 블록으로 나눈 단위입니다. 선택한 블록과 공통 핀을 올바르게 골라야 합니다.
ERC / DRCERC는 회로도의 전기 규칙, DRC는 PCB의 간격·배선 같은 설계 규칙을 검사합니다. 검사 통과가 모든 실물 성능을 보증하지는 않습니다.
Gerber제조업체에 기판의 구리·마스크 등 층 정보를 전달하는 대표적인 출력 형식입니다.
BOM / 위치 파일BOM은 부품 목록이며 위치 파일은 조립 장비가 쓸 부품 위치·방향 정보입니다. 제조 출력에는 둘 다 중요합니다.
MCPAI 클라이언트가 도구 목록과 입력 형식을 얻고 실행 결과를 받는 통신 약속입니다.
JSON-RPCJSON 안에 메서드·인자·요청 식별자를 넣어 호출하고 응답하는 방식입니다.
JSON SchemaJSON에 어떤 필드와 자료형과 범위를 허용하는지 적는 규칙입니다. Konnect는 서버에서도 이를 검사합니다.
도구 묶음sch_wiring처럼 관련 도구를 모은 단위입니다. 전체 카탈로그와 현재 활성 상태는 다릅니다.
표준 입출력프로세스의 입력·출력 통로입니다. 이 서버는 한 줄씩 JSON을 주고받으므로 일반 로그를 출력 통로에 섞으면 안 됩니다.
SSE서버가 연결된 클라이언트로 이벤트를 흘려보내는 HTTP 방식입니다. 여기서는 도구 목록 변경 같은 알림을 보냅니다.
IPC같은 컴퓨터의 프로그램들이 통신하는 방식입니다. Konnect와 KiCad 사이의 실시간 명령 통로입니다.
NNG프로세스 사이에서 메시지를 운반하는 라이브러리입니다. KiCad IPC는 요청·응답 패턴을 사용합니다.
Protobuf / ProstProtobuf는 구조화된 메시지를 표현·직렬화하는 형식이고 Prost는 이를 Rust에서 쓰기 위한 도구입니다.
크레이트 / 워크스페이스크레이트는 Rust의 컴파일 단위이며 이 저장소의 Cargo 패키지는 크레이트를 구성합니다. 워크스페이스는 여러 패키지를 함께 관리합니다.
Arc여러 소유자가 같은 값을 공유하도록 수명을 관리하는 참조 계수 타입입니다. 내용 변경을 자동으로 보호하지는 않습니다.
RwLock여러 읽기 또는 하나의 쓰기가 들어가도록 접근을 조정하는 잠금입니다. 여기서는 활성 도구 맵 등에 사용합니다.
spawn_blocking동기식으로 오래 걸릴 수 있는 일을 별도의 작업 스레드에서 수행하도록 넘기는 Tokio 기능입니다.
S-expression / AST괄호로 중첩한 문서 형식과 그 문서를 나무 구조로 해석한 표현입니다. KiCad 파일 구조를 이해하는 출발점입니다.
원자 교체완성한 임시 파일로 기존 파일을 교체하여 반만 기록된 파일이 보이는 위험을 줄이는 방식입니다.
낙관적 충돌 검사계산하는 동안 오래 잠그는 대신, 저장 직전에 처음 읽은 내용과 여전히 같은지 확인하는 방법입니다.
선행 기록 저널실제 파일을 바꾸기 전에 변경 계획을 먼저 기록하여 중간 종료 뒤에도 복구를 판단하게 하는 장치입니다.
멱등성같은 작업을 반복해도 추가 변화가 생기지 않는 성질입니다. 복구에서 이미 반영된 파일을 다시 건드리지 않는 것이 한 사례입니다.
실행 상태의 권위지금 믿어야 할 설계가 열린 편집기 상태인지 저장된 파일인지 결정하는 기준입니다.
설계 해시파일 내용과 경로로 계산한 식별자입니다. 검사 결과가 어느 설계 버전에 대한 것인지 연결합니다.
결정적 렌더링같은 입력을 같은 조건에서 그리면 같은 결과가 나오게 하는 것입니다. 픽셀 차이 비교의 전제입니다.
디바운스짧은 시간에 반복되는 이벤트를 모아 적절한 때 한 번 처리하는 방식입니다. 파일 저장 도중의 연속 이벤트에 유용합니다.
Tauri / PCMTauri는 웹뷰와 Rust를 연결하는 데스크톱 앱 도구이고, PCM은 KiCad의 플러그인·콘텐츠 관리자입니다.
Specctra DSN / SES외부 배선 도구로 설계 정보를 내보내고 결과를 받아오는 교환 형식입니다. 구문 파싱과 안전한 설계 반영은 별도 단계입니다.

이 용어를 모두 외운 뒤 시작할 필요는 없습니다. 먼저 “도구 요청 → 파일 또는 IPC 변경 → 검증 결과”를 설명해 보고, 막히는 단어만 이 표로 돌아와 확인하면 됩니다.

11참고 링크

공식 문서와 고정된 코드 근거를 함께 읽기

11-1. 저장소와 설계 문서

11-2. 핵심 구현 바로가기

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

현재 상태 (2026-10-23 확인)

GitHub 상태 수치는 2026-10-23 기준입니다. 코드 내부의 수치와 동작은 커밋 9488e5f에 고정되어 있습니다. 최근 push 날짜와 분석 대상 커밋 날짜는 서로 다른 범위를 나타냅니다.

항목상태
트렌딩 선정GitHub Trending Rust Weekly #4 · 2026-10-23
스타 / 포크1,375 / 165
주 언어Rust
저장소 생성일2026-07-05
GitHub 최근 push2026-10-22
최신 릴리스v0.13.0 · 2026-10-02
분석 대상 최근 커밋9488e5f · 2026-10-05
Merge pull request #835 from neusse/neusse/fix-464-default-unit-pin-layout
소스의 패키지 버전워크스페이스와 별도 뷰어 모두 0.13.0
코드 규모Rust 147파일·170,956줄 / Python 7파일·1,443줄 / Protobuf 12파일·3,370줄 / HTML 1파일·575줄
집계 기준Git 추적 파일의 물리적 줄 수. 테스트·주석·빈 줄 포함. HTML 안의 CSS·JavaScript는 HTML에 포함
도구 수GitHub 소개 217개 / README와 등록부 업무 도구 합계 228개·21묶음 / 관리 도구 별도
KiCad 범위PCM 메타데이터 10.0~10.99 선언 / 실제 KiCad 검증 워크플로는 10.0.5 고정
개발 단계README는 beta, PCM 버전 메타데이터는 stable로 표기
라이선스GitHub AGPL-3.0 / Cargo SPDX 표기 AGPL-3.0-only / 별도 상업용 안내 존재
쓰기 전에 알아둘 한계
설계 파일을 바꾸는 도구에는 결과를 확인하는 사람이 필요하다

시점: 10월 22일 push까지의 모든 변경을 이 문서가 설명하는 것은 아닙니다. 코드 근거는 10월 5일의 커밋에 고정되어 있습니다. 얕은 이력만으로 전체 커밋 수나 기여자 활동을 추정할 수도 없습니다.

완성도: README의 beta와 패키징의 stable 표기는 일치하지 않습니다. 공통 수행 상태 형식도 일부 도구부터 적용 중입니다. konnect-vcs에 기반 코드가 있다는 이유만으로 전체 Git 체크포인트 기능이 완성되었다고 판단해서는 안 됩니다.

검증 범위: 소스와 CI 설정은 설계 의도와 검증 방법의 근거입니다. 실제 설치 성공, 모든 도구의 실행 성공, 성능 수치, 특정 보드의 제조 적합성을 자동으로 입증하지는 않습니다. README의 실행 파일 크기·카탈로그 규모·토큰 수는 문서의 안내 수치입니다.

변경과 검사: 저장 파일과 열린 보드가 다를 수 있고, 일부 작업은 부분 수행이나 불확실 상태를 구분해야 합니다. 복구 가능한 복사본으로 시작하고 결과를 확인하세요. ERC·DRC와 설계 검토 도구가 전원·열·신호 품질 등 모든 공학적 판단을 대신하지는 않습니다.

데이터 경계: 로컬 MCP 서버라고 해서 설계 정보가 어떤 외부 서비스에도 전달되지 않는다는 뜻은 아닙니다. AI 클라이언트·모델 서비스·부품 조회 경로를 함께 확인해야 합니다. 라이선스 적용 조건은 연결된 원문과 상업용 안내를 기준으로 확인하세요.