excalidraw는 React 기반 손그림 스타일 화이트보드 라이브러리로, 저장소는 npm에 @excalidraw/excalidraw로 배포되는 핵심 패키지와 실제 서비스(excalidraw.com)인 excalidraw-app을 같은 워크스페이스 모노레포에 묶어둔 구조다. 실측 기준 텍스트 파일 1,271개·328,022줄 중 tsx 304개·99,051줄과 ts 335개·95,380줄을 합치면 194,431줄로 전체의 약 59.3%를 차지하고, 나머지는 snap(24개·54,389줄, 스냅샷 테스트), sfd(1개·12,222줄, 폰트 소스), scss(82개·10,141줄), mdx(33개·3,661줄, 문서) 순이다. 루트 package.json은 dependencies가 0개이고 devDependencies만 34개인데, 클론해 확인하면 이건 워크스페이스 전체를 아우르는 private 모노레포 매니페스트라서 실제 런타임 의존성은 각 packages/* 하위 매니페스트에 흩어져 있다는 뜻이다.
패키지는 역할별로 나뉘어 있다. packages/element는 도형·바인딩·프랙셔널 인덱싱 같은 엘리먼트 모델을, packages/excalidraw는 캔버스 렌더링과 씬 직렬화·암복호화를, packages/fractional-indexing은 순서 인덱스 생성 알고리즘을, packages/math는 기하 연산을 각각 담당한다. excalidraw-app은 이 패키지들을 조립해 실시간 협업(collab/Portal)과 Firebase 저장(data/firebase.ts), Socket.IO 연결을 붙인 완성형 웹앱이다.
메타 정보(meta.hasAgentDocs: true)대로 저장소 루트에 CLAUDE.md와 AGENTS.md가 함께 있고, 클론해 읽어보면 두 문서 모두 위 모노레포 구조와 yarn test:typecheck·yarn test:update 같은 개발 커맨드를 요약해둔 내용이라 AI 에이전트가 이 리포에서 바로 작업을 시작할 수 있게 정리돼 있다.
하이라이트
엘리먼트 순서를 프랙셔널 인덱싱으로 캐싱.packages/element/src/fractionalIndex.ts는 배열 순서를 그대로 신뢰하지 않고 프랙셔널 인덱스를 진실의 소스로 둔 뒤, 배열은 캐시로만 쓰는 설계를 주석으로 명시한다.
``ts export class InvalidFractionalIndexError extends Error { public code = "ELEMENT_HAS_INVALID_INDEX" as const; } ``
다중 사용자 환경에서 정렬 충돌 없이 z-index나 리스트 순서를 병합해야 하는 기능이라면, 이 파일의 캐시·재계산 분리 패턴이 바로 참고가 된다. topExtensions에 ts 335개·95,380줄이 잡힌 것도 이런 세밀한 도메인 로직 파일이 많다는 걸 뒷받침한다.
서버가 콘텐츠를 못 보는 협업 저장.packages/excalidraw/data/encryption.ts는 window.crypto.subtle로 AES-GCM 키를 생성·내보내고, excalidraw-app/data/firebase.ts는 encryptData/decryptData로 감싼 씬 데이터만 Firestore에 쓴다.
키가 서버로 전송되지 않고 클라이언트 간에만 공유되는 구조라, 협업 링크 자체가 복호화 키 역할을 한다. 종단간 암호화가 필요한 협업 기능을 처음부터 설계해야 한다면 이 두 파일이 실전 참고가 된다.
스냅샷 테스트로 회귀를 조인다.snap 확장자만 24개 파일·54,389줄로, 전체 텍스트(328,022줄)의 6분의 1이 넘는다. 테스트 파일 168개(meta가 아닌 tree.testFiles 실측)와 합쳐 보면, 캔버스 렌더링처럼 시각적 회귀가 발생하기 쉬운 영역을 스냅샷으로 촘촘히 잡아두는 팀 문화가 수치로 드러난다.
주의점
라이선스는 MIT(meta.license 실측과 클론한 LICENSE 파일 본문 일치)로 상업적 이용에 제약이 거의 없다. 다만 commitCount가 정확히 1,000으로 shallow clone(depth 1000) 상한과 맞물려 있어, 실제 커밋 히스토리와 commitsLast90d(90일 내 78건)를 뺀 전체 활동량은 이 실측보다 더 많을 수 있다는 점을 감안해야 한다(note 필드 명시).
excalidraw-app의 실시간 협업 기능은 Firebase(Firestore·Storage)와 Socket.IO 서버를 직접 붙이는 구조라, @excalidraw/excalidraw 패키지만 임베드해 쓸 때는 이 협업·암호화 코드가 그대로 딸려오지 않는다. 협업 기능까지 참고하려면 라이브러리가 아니라 excalidraw-app 쪽 코드를 봐야 한다는 점, 그리고 AES-GCM 키 배포(URL 공유)를 자체 서비스에 옮겨 쓸 경우 링크 유출이 곧 데이터 노출로 이어지는 구조라는 점은 도입 전에 별도로 검토할 부분이다.
실측 정보
분석 기준 커밋
e1bb9ff8 (shallow, depth 1000)
90일 내 커밋 수
78건
기여자 수
152명
원격 태그 수
21개
텍스트 파일 / 총 라인
1,271개 / 328,022줄
TSX+TS 파일 / 라인
639개 / 194,431줄 (전체 LOC의 약 59.3%)
테스트 파일 / CI 워크플로우
168개 / 11개
적용점
P0 · 비용 낮음packages/element/src/fractionalIndex.ts의 InvalidFractionalIndexError와 재정렬 로직을 읽으면, 배열 순서를 프랙셔널 인덱스로 캐싱하고 필요할 때만 재계산하는 패턴을 그대로 가져다 쓸 수 있다. 드래그 정렬·다중 사용자 순서 동기화가 필요한 기능에 바로 적용 가능하다.
P1 · 비용 중간packages/excalidraw/data/encryption.ts(AES-GCM, window.crypto.subtle)와 excalidraw-app/data/firebase.ts를 같이 읽으면 '서버는 암호문만 저장하고 복호화 키는 URL fragment로만 공유'하는 종단간 암호화 협업 설계를 배울 수 있다. 협업 문서 저장소를 만들 때 참고 가치가 크다.
P2 · 비용 높음자체 손글씨 폰트(ComicShanns, sfd 소스 1파일 12,222줄)까지 리포에 포함된 폰트 파이프라인을 벤치마킹하려면 별도 폰트 빌드 도구 체인을 봐야 한다. 이번 실측 범위 밖이다.
◆ 도입 후보
실측 수치가 가리키는 건 규모보다 정돈됨이다. 루트 package.json의 dependencies가 0개이고 devDependencies만 34개인 건 이 리포가 배포용 라이브러리(@excalidraw/excalidraw)와 workspace 패키지들을 묶는 private 모노레포라는 뜻이고, 실제로 클론해보면 packages/ 아래가 common·element·excalidraw·fractional-indexing·laser-pointer·math·utils로 역할별로 쪼개져 있다. topExtensions에서 snap 확장자가 24개 파일에 54,389줄로 3위에 오른 것도 눈에 띈다. 텍스트 총량(328,022줄)의 6분의 1이 스냅샷 테스트라는 뜻이라, 리팩터링 시 회귀를 스냅샷으로 강하게 잡아두는 팀 문화가 수치로 드러난다. sfd 확장자가 파일 1개·12,222줄로 잡힌 것도 흥미로운 실측인데, 클론해 확인하니 이건 코드가 아니라 손글씨 폰트 'Comic Shanns'의 FontForge 소스 파일이다(수치는 JSON, 파일 정체는 클론 확인) — 화이트보드 특유의 손그림 느낌을 자체 폰트로 구현했다는 신호다. commitCount가 정확히 1,000으로 shallow clone 상한과 일치해 실제 히스토리는 이보다 길다는 점, hasAgentDocs가 true로 잡힌 대로 CLAUDE.md·AGENTS.md가 모노레포 구조를 문서화해두고 있다는 점도 확인했다(문서 존재는 실측 JSON meta.hasAgentDocs 근거, 내용은 클론 확인). 라이선스는 MIT로 상업 이용 제약이 낮다. 코드를 읽어보면 엘리먼트 순서를 프랙셔널 인덱싱으로, 실시간 협업 페이로드를 클라이언트 측 AES-GCM 암호화로 처리하는 구조가 실제로 구현돼 있어, 화이트보드류 캔버스나 종단간 암호화가 필요한 협업 기능을 설계할 때 참고할 실전 사례로 충분하다.
원문 README
아래는 excalidraw/excalidraw 저장소의 README 원문입니다(GitHub 렌더, 수집 시점 기준). 저작권은 원 프로젝트에 있으며 원 저장소의 라이선스를 따릅니다. GitHub에서 보기
An open source virtual hand-drawn style whiteboard.
Collaborative and end-to-end encrypted.
Create beautiful hand-drawn like diagrams, wireframes, or whatever you like.
Features
The Excalidraw editor (npm package) supports:
💯 Free & open-source.
🎨 Infinite, canvas-based whiteboard.
✍️ Hand-drawn like style.
🌓 Dark mode.
🏗️ Customizable.
📷 Image support.
😀 Shape libraries support.
🌐 Localization (i18n) support.
🖼️ Export to PNG, SVG & clipboard.
💾 Open format - export drawings as an .excalidraw json file.
⚒️ Wide range of tools - rectangle, circle, diamond, arrow, line, free-draw, eraser...
➡️ Arrow-binding & labeled arrows.
🔙 Undo / Redo.
🔍 Zoom and panning support.
Excalidraw.com
The app hosted at excalidraw.com is a minimal showcase of what you can build with Excalidraw. Its source code is part of this repository as well, and the app features:
📡 PWA support (works offline).
🤼 Real-time collaboration.
🔒 End-to-end encryption.
💾 Local-first support (autosaves to the browser).
🔗 Shareable links (export to a readonly link you can share with others).
We'll be adding these features as drop-in plugins for the npm package in the future.
Quick start
Note: following instructions are for installing the Excalidraw npm package when integrating Excalidraw into your own app. To run the repository locally for development, please refer to our Development Guide.