← /projects • shipped 2023 Frontend-of-one SVG · Affine · Zustand · SSE

Kumo Factory

클라우드 인프라를 시각적으로 설계하는 노코드 빌더.

WHY I STARTED THIS
AWS 콘솔의 복잡함을 시각적 캔버스로 대체하자는 아이디어에서 시작했습니다. 제품의 성패는 '얼마나 큰 아키텍처든 끊김 없이 그릴 수 있는가' 한 가지 경험에 달려 있다고 봤고, 그 핵심을 직접 책임지고 싶었습니다.
FRAMERATE
60
fps
Pan + zoom + drag
MEMORY
100% 70%
−30%
After normalization
API CALLS
100% 50%
−50%
Selective subscriptions
SSE LATENCY
<100ms
live
Deploy → browser

"라이브러리가 캔버스 크기 한계에 부딪힐 때, 어디까지가 라이브러리 책임인가?"

DEF. 노코드 클라우드 빌더는 사용자가 수백 개 노드의 아키텍처를 한 화면에 그릴 수 있어야 했습니다. react-zoom-pan-pinch는 내부 transform 컨테이너에 한계가 있어 일정 규모를 넘으면 가장자리에서 잘리거나 좌표가 어긋났습니다. 라이브러리를 패치하느니 직접 만드는 편이 빠르고 안정적이라고 판단했습니다.

LIVE · /demo/canvas.svg viewBox: 0 0 800 500 drag · scroll to zoom
serviceVPCserviceALBserviceECS · webserviceECS · apiserviceRDSserviceS3serviceCloudFrontserviceLambdaserviceAuroraserviceRedisserviceRoute53serviceSQSserviceSNS
01

Throw out react-zoom-pan-pinch

패치 가능 범위를 넘어선 구조적 한계라고 판단. 직접 만들기로 결정.

02

SVG viewBox + 3×3 affine matrix

캔버스 자체는 무한. viewBox 좌표만 이동·확대해서 화면에 비추는 창만 움직임.

03

Pointer-anchored zoom

휠 줌은 마우스 포인터 기준으로 동작해야 자연스럽다. 비례 기반 좌표 재계산으로 world point 유지.

04

Five Zustand slices

Common · Service · Area · Line · Option. 선택적 구독으로 변경된 slice 구독자만 리렌더, 메모리 30% 절감.

05

SSE for live deploy

배포 진행 상황을 100ms 이내에 브라우저로 푸시. 이벤트 스트림을 캔버스 노드 상태에 즉시 반영.

Keep the world point under the cursor.

줌 전후로 마우스가 가리키는 좌표가 같은 world point를 가리키도록 viewBox 원점을 재계산합니다.

function zoomAtPointer(vb, factor, mouse, rect) {
  const wx = (mouse.x / rect.width)  * vb.w + vb.x;
  const wy = (mouse.y / rect.height) * vb.h + vb.y;

  return {
    x: wx - (wx - vb.x) * factor,
    y: wy - (wy - vb.y) * factor,
    w: vb.w * factor,
    h: vb.h * factor,
  };
}

A canvas without limits. A frontend that doesn't drop frames.

  • 대규모 캔버스에서 60fps 유지.
  • 5-slice store + 정규화로 메모리 30%↓, API 호출 50%↓.
  • SSE 기반 실시간 배포 시각화 — 100ms 이내 지연.