Excalidraw 스킬
0단계: 인터페이스 선택
동일한 라이브 캔버스를 구동하는 세 가지 인터페이스가 있습니다. 자신에게 가장 먼저 해당하는 것을 선택하세요.
- MCP 도구 — 툴 목록에
excalidraw/*도구(예:batch_create_elements)가 있다면 이를 우선 사용하세요: 결과가 컨텍스트에 직접 전달되고, 스크린샷이 디스크를 거치지 않고 이미지로 반환됩니다. - CLI (MCP 도구가 없을 때 기본값):
별도 설정이 필요 없습니다 — 캔버스를 조작하는 모든 명령은npx -y mcp-excalidraw-server <command>http://127.0.0.1:3000에서 캔버스 서버를 자동으로 시작합니다 (첫 번째npx실행 시 패키지를 다운로드). CLI가 전역으로 설치된 경우(npm i -g mcp-excalidraw-server), 더 짧은 별칭excalidraw-canvas <command>를 사용할 수 있습니다. - REST API (최후의 수단, 예: 애플리케이션 코드에서 사용):
http://127.0.0.1:3000의 HTTP 엔드포인트 — 페이로드는references/cheatsheet.md를 참조하세요. 서버가 이미 실행 중이어야 합니다.
캔버스 URL은 EXPRESS_SERVER_URL에서 가져옵니다(기본값 http://127.0.0.1:3000). 사용자에게 브라우저에서 해당 URL을 열도록 알리세요 — 스크린샷, 이미지 내보내기, Mermaid 변환 및 뷰포트 제어에는 열린 탭이 필요합니다(없으면 CLI가 종료 코드 4와 함께 종료됩니다).
CLI 빠른 참조
결과는 stdout에 JSON으로 출력됩니다 — 단, describe(일반 텍스트)와 --out을 생략한 원시 콘텐츠 출력(export 장면 JSON, screenshot --format svg)은 예외입니다. 진단 정보는 stderr로 출력됩니다. 종료 코드: 0 정상, 1 오류, 2 사용법 오류, 3 캔버스 연결 불가, 4 브라우저 탭 필요.
| 작업 | 명령어 |
|---|---|
| 서버 시작 / 중지 / 확인 | start, stop, status |
| 요소 생성 (일괄) | add elements.json 또는 echo '[...]' | add 또는 add --one '{...}' |
| 한 번에 다중 작업 패치 | apply patch.json — {"create":[...],"update":[{"id":"a","set":{...}}],"delete":[...]} |
| 하나 읽기 / 여러 개 쿼리 | get <id>, query [--type t] [--bbox x0,y0,x1,y1] [--filter k=v] [--filter-json '{...}'] |
| 업데이트 / 삭제 | update <id> --set '{...}', delete <id> [...] |
| 장면 이해 | describe (일반 텍스트 요약: ID, 위치, 레이블, 연결) |
| 장면 보기 | screenshot [--out f.png] (--out 없이 PNG → JSON에 임시 파일 경로; --out 없이 SVG → 원시 SVG) |
| 레이아웃 작업 | arrange align|distribute|group|ungroup|lock|unlock|duplicate --ids a,b,c [--to left|horizontal|...] |
| 장면 파일 | export [--out scene.excalidraw], `import [scene.excalidraw |
| Mermaid → 캔버스 | `mermaid [diagram.mmd |
| 스냅샷 | snapshot save|list|restore <name> |
| 공유 링크 | share (암호화 업로드 → excalidraw.com URL) |
| 캔버스 지우기 | clear --yes |
| 이 스킬 설치 / 업그레이드 | install-skill --dir <skills-root> (에이전트가 프로젝트/전역 루트 선택) |
요소 형식 (CLI 및 MCP)
CLI와 MCP 도구는 동일한 에이전트 친화적 형식을 허용하며 자동으로 정규화합니다:
- 레이블: 모든 도형에
"text": "My Label"을 넣으면 Excalidraw의 바인딩 레이블 형식으로 변환됩니다. - 화살표 바인딩:
"startElementId": "a"/"endElementId": "b"— 화살표가 요소 가장자리로 자동 경로를 찾습니다. - fontFamily: 문자열 이름(
"helvetica","cascadia","excalifont", ...) 또는 문자열 숫자"1"–"8"를 전달합니다. - points:
[[x,y], ...]튜플과[{"x":..,"y":..}]객체 모두 허용됩니다. - 패치 업데이트:
apply에서 업데이트 항목은 직접 필드({"id":"a","x":120}) 또는set객체({"id":"a","set":{"x":120}})를 사용할 수 있습니다. 하나의 업데이트 항목에서 두 형식을 혼합하지 마세요.
원시 REST는 더 엄격합니다: 레이블은 "label": {"text": "..."} 형식이어야 하고, 바인딩은 "start": {"id": "..."} / "end": {"id": "..."} 형식이어야 합니다. API에 직접 POST 요청을 보낼 때만 이 점을 신경 쓰세요.
좌표 시스템
캔버스는 2D 좌표 그리드를 사용합니다: (0, 0)이 원점이며, x는 오른쪽으로 증가, y는 아래쪽으로 증가합니다. JSON을 작성하기 전에 레이아웃을 계획하세요.
일반 간격 지침:
- 계층 간 세로 간격: 80–120px (화살표 레이블이 겹치지 않을 정도)
- 형제 요소 간 가로 간격: 최소 40–60px; 레이블이 있는 화살표는 120px+ 할당
- 도형 너비:
max(160, 레이블문자수 * 12)(레이블을 한 줄로 유지하기 위해) - 도형 높이: 한 줄 레이블 60px, 두 줄 레이블 80px
- 배경/영역 패딩: 포함된 요소 주변 모든 방향 50px
전문적인 외관을 위한 스타일링:
- 도형에
"fillStyle": "solid"를 사용하면 깔끔한 평면 채움이 적용됩니다 (기본값은 스케치된 해치 패턴입니다) - 파스텔
backgroundColor채움을 더 어두운strokeColor와 짝지으세요 (색상표는 치트시트 참조) - 영역 테두리와 비동기 화살표에
"strokeStyle": "dashed"를 사용하면 "경계 / 배경"으로 읽힙니다
레이아웃 안티패턴 (복잡한 다이어그램에 중요)
다음은 읽기 어려운 다이어그램을 만드는 가장 흔한 실수입니다. 모두 피하세요.
1. 큰 배경 영역 사각형에 label.text (또는 text)를 사용하지 마세요
배경 사각형에 레이블을 넣으면 Excalidraw는 해당 도형의 정중앙에 바인딩된 텍스트 요소를 만듭니다 — 서비스 상자가 배치될 바로 그 위치입니다. 텍스트가 영역 안의 모든 것과 겹치고 위치를 변경할 수 없습니다.
잘못된 예:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "text": "VPC (10.0.0.0/16)"}
올바른 예 — 영역 상단에 고정된 독립 텍스트 요소 사용:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "backgroundColor": "#e3f2fd"},
{"id": "vpc-label", "type": "text", "x": 70, "y": 60, "width": 300, "height": 30, "text": "VPC (10.0.0.0/16)", "fontSize": 18}
독립 텍스트 요소는 영역의 상단 모서리에 위치하며 내부에 배치된 요소와 간섭하지 않습니다.
2. 복잡한 다이어그램에서 영역을 가로지르는 화살표를 피하세요
한 레이아웃 영역의 요소에서 먼 영역의 요소로 가는 화살표는 그 사이의 모든 것을 가로지르는 긴 대각선을 그리게 됩니다. 다중 영역 인프라 다이어그램에서는 읽을 수 없는 스파게티 엉킴이 발생합니다.
설계 규칙: 화살표는 동일한 영역 또는 계층 내에 유지하세요. 영역 간 관계를 표시하려면 주석 텍스트를 사용하거나 영역 가장자리가 인접하도록 분리하고(사이에 요소 없음), 가장자리를 따라 화살표를 배치하세요.
반드시 영역을 가로질러 연결해야 하는 경우, 다른 영역의 중간을 통과하지 말고 둘레를 따라가는 꺾인 화살표를 사용하세요.
3. 화살표 레이블은 드물게 사용하세요
화살표 레이블은 화살표의 중간 지점에 배치됩니다. 짧은 화살표에서는 양쪽 끝의 도형과 겹칩니다. 복잡한 다이어그램에서는 주변 요소와 충돌합니다.
- 관계 이름이 정말로 필수적인 경우에만 화살표 레이블을 추가하세요(예: 프로토콜, 포트 번호, 데이터 방향).
- 모든 화살표에 레이블을 추가한다면 재고하세요 — 일반적으로 명확성보다는 시각적 잡음을 추가합니다.
- 화살표 레이블은 12자 이내로 유지하세요. 밀집된 다이어그램에서는 완전히 생략하는 것이 좋습니다.
품질: 왜 중요한가 (그리고 확인하는 방법)
Excalidraw 다이어그램은 시각적 커뮤니케이션입니다. 텍스트가 잘리거나, 요소가 겹치거나, 화살표가 관련 없는 도형을 가로지르면 다이어그램이 혼란스럽고 비전문적으로 보입니다. 다이어그램을 그리는 목적 자체가 무너집니다. 따라서 요소를 추가할 때마다 확인하세요.
품질 체크리스트
add / apply / batch_create_elements 후 스크린샷을 찍고 다음을 확인하세요:
- 텍스트 잘림 — 모든 레이블 텍스트가 완전히 보입니까? 텍스트가 잘렸다면 도형이 너무 작은 것입니다.
width및/또는height를 늘리세요. - 겹침 — 어떤 도형이 동일한 공간을 공유하고 있습니까? 배경 영역은 자식 요소를 패딩을 포함하여 완전히 감싸야 합니다.
- 화살표 교차 — 화살표가 관련 없는 요소를 가로지르나요? 그렇다면 곡선 또는 꺾인 화살표를 사용하여 주변으로 경로를 변경하세요(화살표 경로 지정 참조).
- 화살표-레이블 겹침 — 화살표 레이블은 중간 지점에 있습니다. 도형과 겹친다면 레이블을 줄이거나 화살표 경로를 조정하세요.
- 간격 — 요소 간 최소 40px 간격. 비좁은 레이아웃은 읽기 어렵습니다.
- 가독성 — 본문 텍스트는 글꼴 크기 ≥ 16, 제목은 ≥ 20.
- 영역 레이블 배치 — 배경 영역 사각형에
text/label.text를 사용했다면 영역 레이블이 영역 중앙에 위치하여 내부의 모든 것과 겹칠 것입니다. 해결 방법: 바인딩된 텍스트 요소를 삭제하고 영역 상단에 독립 텍스트 요소를 추가하세요(위의 레이아웃 안티패턴 참조).
문제를 발견하면: 멈추고, 수정하고, 다시 스크린샷을 찍은 후 계속하세요. 문제를 무시하지 말고 "[문제]가 보입니다, 수정 중입니다"라고 말하세요. 모든 체크를 통과한 후에만 진행하세요.
워크플로: 새 다이어그램 그리기
Mermaid vs 직접 생성 — 언제 무엇을 사용할까?
mermaid / create_from_mermaid를 사용하세요 — 사용자가 이미 Mermaid 다이어그램을 가지고 있거나, 구조가 표준 Mermaid 구문을 사용하는 순서도/시퀀스/ER 다이어그램에 깔끔하게 매핑되는 경우. 빠르고 변환을 자동으로 처리하지만 정확한 레이아웃 제어력은 떨어집니다.
요소를 직접 생성하세요 — 정밀한 레이아웃 제어가 필요하거나, 다이어그램 유형이 Mermaid에 잘 매핑되지 않거나(예: 사용자 정의 아키텍처, 주석이 달린 클라우드 다이어그램), 특정 좌표 그리드에 요소를 배치하려는 경우.
단계 (CLI 기준; MCP 도구는 1:1 대응 — 치트시트 참조)
- 좌표 그리드를 계획하세요 — JSON을 작성하기 전에 계층과 x-위치를 매핑하세요. (MCP 모드: 색상/크기 정보는
read_diagram_guide호출; 동일한 지침은references/cheatsheet.md에 있습니다.) - 선택 사항: 새로 시작
npx -y mcp-excalidraw-server clear --yes - 도형과 화살표를 한 번에 생성하세요. 사용자 정의
id필드(예:"id": "auth-svc")는 나중에 업데이트하기 쉽게 만듭니다:(npx -y mcp-excalidraw-server add - <<'EOF' [ {"id": "lb", "type": "rectangle", "x": 300, "y": 50, "width": 180, "height": 60, "text": "Load Balancer"}, {"id": "svc-a", "type": "rectangle", "x": 100, "y": 200, "width": 160, "height": 60, "text": "Web Server 1"}, {"id": "svc-b", "type": "rectangle", "x": 450, "y": 200, "width": 160, "height": 60, "text": "Web Server 2"}, {"id": "db", "type": "rectangle", "x": 275, "y": 350, "width": 210, "height": 60, "text": "PostgreSQL"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "lb", "endElementId": "svc-a"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "lb", "endElementId": "svc-b"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-a", "endElementId": "db"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-b", "endElementId": "db"} ] EOF-위치 인수는 선택 사항 — 파일 인수가 없으면add는 stdin을 읽습니다.) max(160, 레이블길이 * 12)를 사용하여 도형 너비를 설정하세요.screenshot→ 파일 보기 → 품질 체크리스트 실행 → 다음 배치 전에 문제 수정.
화살표 경로 지정 — 겹침 방지
직선 화살표는 복잡한 다이어그램에서 요소를 가로지를 수 있습니다. 필요할 때 곡선 또는 꺾인 화살표를 사용하세요:
곡선 화살표 (장애물 위로 부드러운 호):
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [50, -40], [200, 0]],
"roundness": {"type": 2}
}
중간 웨이포인트 [50, -40]가 화살표를 위로 들어 올립니다. roundness: {type: 2}는 부드럽게 만듭니다.
꺾인 화살표 (직각 / L자형 경로):
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [0, -50], [200, -50], [200, 0]],
"elbowed": true
}
언제 무엇을 사용할까:
- 방사형 (하나의 출발지 → 여러 대상): 웨이포인트가 있는 곡선 화살표로 겹침 방지
- 교차 레인 (측면 패널 연결): 위로, 가로로, 아래로 가는 꺾인 화살표
- 긴 수평 연결: 약간의 수직 오프셋이 있는 곡선 화살표
규칙: 화살표가 관련 없는 도형을 통과한다면, 주변으로 경로를 변경하기 위해 웨이포인트를 추가하세요.
워크플로: 반복 정제
describe와 screenshot을 함께 사용하는 것이 이 스킬의 핵심입니다.
describe(MCP에서는describe_scene) → 구조화된 텍스트: 요소 ID, 유형, 위치, 레이블, 연결. 프로그래밍 방식 업데이트 전에 캔버스에 무엇이 있는지 알기 위해 사용하세요(ID 찾기, 경계 상자 이해).screenshot(MCP에서는get_canvas_screenshot) → 실제 렌더링된 캔버스의 PNG. 시각적 품질 확인을 위해 사용하세요 — 사용자가 보는 것(텍스트 잘림, 겹침, 화살표 경로 포함)을 정확히 보여줍니다. CLI는 저장된 파일 경로를 JSON으로 출력합니다; 해당 파일을 읽거나 보세요.
피드백 루프:
요소 추가
→ 스크린샷 → 보기 → "auth-svc에서 텍스트 잘림"
→ auth-svc 업데이트 --set '{"width": 220}' → 스크린샷 → "auth-svc와 rate-limiter 사이에 겹침"
→ rate-limiter 업데이트 --set '{"x": 520}' → 스크린샷 → "모든 체크 통과"
→ 계속 진행
워크플로: 기존 다이어그램 정제
describe로 현재 상태 파악 — 요소 ID와 위치를 기록하세요.id또는 레이블 텍스트로 요소 식별(x/y 좌표는 변하므로 사용하지 마세요).update <id> --set '{...}'로 크기/색상/위치 변경;delete <id>로 제거; 또는 모든 것을 하나의apply패치로 묶으세요. 끝점을 이동하거나 크기를 조정하면 바인딩된 화살표가 자동으로 다시 경로를 찾습니다 — 삭제하고 다시 생성할 필요가 없습니다.screenshot으로 변경 사항이 올바른지 확인하세요.- 업데이트 실패 시:
get <id>로 ID 존재 확인; 잠금 상태면arrange unlock --ids <id>로 잠금 해제.
워크플로: Mermaid 변환
echo 'graph TD
A[Client] --> B[API]
B --> C[(DB)]' | npx -y mcp-excalidraw-server mermaid
열린 브라우저 탭이 필요합니다(변환이 프론트엔드에서 실행됨; 종료 코드 4는 캔버스 URL을 열라는 의미). 이후 screenshot으로 레이아웃을 확인하세요. 자동 레이아웃이 좋지 않다면(노드가 좁고, 가장자리가 교차), describe로 문제 요소를 찾고 update로 위치를 조정하세요.
워크플로: 파일 I/O
- 장면 내보내기:
export --out diagram.excalidraw(--out없음 → stdout에 JSON) - 장면 가져오기:
import diagram.excalidraw(추가) 또는import diagram.excalidraw --replace - 이미지:
screenshot --out diagram.png/screenshot --format svg --out diagram.svg(브라우저 탭 필요) - 공유 링크:
share— 장면을 암호화하고 공유 가능한 exc...