Skip to content

명시 배선 — import한 것만 싣는다

browserDeps()는 프리셋이다 — 한 줄로 서는 대신, 프리셋이 참조하는 것은 옵션과 무관하게 전부 번들에 실린다. pointer: false를 줘도 크기가 같은 이유다(실측 53.90 vs 53.91 KB min): 번들러는 "실행되나"를 못 보고 "참조하나"만 본다. 옵션은 동작을 끄는 문이지 바이트를 빼는 문이 아니다.

바이트를 빼는 문은 이것이다 — createPlotDeps에 조각을 직접 넘긴다:

ts
/**
 * 명시 배선의 실물 — explicit-wiring.md가 이 파일을 그대로 임베드하고,
 * `pnpm --filter charts-docs type-check`가 컴파일을 지킨다.
 *
 * 프리셋(browserDeps)과의 차이는 하나다: **여기서 import한 것만 번들에
 * 실린다.** 포인터·구분자·그라디언트 페인터를 import하지 않았으므로
 * 번들러가 실을 방법이 없다 — 런타임 플래그가 아니라 참조 부재가 문이다.
 */
import {
  candleSeries,
  createCanvasRenderer,
  createCanvasTextMeasurer,
  createPlotDeps,
  frameScheduler,
} from "@finchart/core";
import {
  createDomAxisLabels,
  createDomLayers,
  cssReader,
  PlotBuilder,
} from "@finchart/dom";

const deps = (container: HTMLElement) =>
  createPlotDeps({
    createLayers: (width, height) => createDomLayers(container, width, height),
    createRenderer: createCanvasRenderer,
    createStyleReader: () => cssReader(container),
    createTextMeasurer: createCanvasTextMeasurer,
    createAxisLabels: createDomAxisLabels,
    createScheduler: frameScheduler(),
    // 상호작용이 필요해지면 그때 import한다 — 붙이는 순간부터 값을 낸다:
    // interactions: pointerInteractions(container),
    // pane을 나눠 쓰게 되면: createDividers: createDomDividers,
  });

const plot = PlotBuilder.create(deps, candleSeries())
  .addDataPoints([
    { x: 0, open: 100, high: 108, low: 98, close: 106 },
    { x: 1, open: 106, high: 112, low: 104, close: 109 },
    { x: 2, open: 109, high: 111, low: 101, close: 103 },
  ])
  .setSize(800, 400)
  .build(document.getElementById("chart")!);

export { plot };

같은 캔들 차트가 45.1 KB min · 13.9 KB brotli로 선다 — 프리셋 (53.9 KB min · 15.9 KB brotli) 대비 −8.8 KB min (2026-08-16 실측, esbuild + brotli). 빠진 것은 정확히 import하지 않은 것들이다:

안 실린 것min필요해지면
포인터 어휘 전부6,171 Binteractions: pointerInteractions(container)
pane 구분자 드래그1,452 BcreateDividers: createDomDividers
그라디언트 페인터931 BcreateCanvasRenderer(surface, { painters: { [LINEAR_GRADIENT]: paintLinearGradient } })
프리셋 배선 자체~600 B

그라디언트는 페인터 없이도 깨지지 않는다 — area의 fillBottom이나 charts/linear-gradient 스타일은 첫 stop의 단색으로 강등된다(폴백 계약). 그라디언트가 보고 싶어지면 위의 painters 한 줄이 문이다.

그래도 남는 것 — 그리고 남는 이유

명시 배선까지 내려가도 두 개는 남는다. 크기가 작아서 봐주는 것이 아니라, 각각 계약이 근거다:

  • M4 데시메이션 기본 (~1 KB) — createPlotDeps의 기본 정책이다. 파생 시리즈(지표)가 붙는 순간 100k 점이 여기 기대 선다. 이것을 빼면 "지표를 붙였더니 느려졌다"가 기본 동작이 된다 — 성능 예산 (성능 가이드)이 이 기본값 위에 서 있다. 자기 정책이 있으면 createDecimation으로 갈아 끼운다.
  • 축 드래그 소비자 (900 B) — plot의 입력 계약(X2)의 일부다. 입력 스택은 headless에서도 1급이라(routeInput으로 합성 입력을 넣는다 — 차트를 테스트한다), 브라우저 배선이 아니라 plot 자신에 산다.

이 목록이 자라면 그것은 버그다 — 동승자는 문(import 단위) 또는 근거(계약 명문) 중 하나를 가져야 하고, "작아서 괜찮다"는 근거가 아니다 (PRINCIPLES 27).

언제 무엇을 쓰나

  • 프리셋 — 시작할 때, 프로토타입, 상호작용 다 쓰는 트레이딩 화면. 60초가 서고, 그라디언트·구분자·핀치가 그냥 된다.
  • 명시 배선 — 임베드 위젯, 정적 차트, 바이트가 예산인 곳. 필요한 조각을 필요해질 때 import한다 — 위 표가 가격표다.

둘은 같은 PlotDeps 계약의 두 조립법이라 언제든 갈아탈 수 있다 — 프리셋으로 시작해 명시 배선으로 내려가는 데 컴포넌트 코드는 안 바뀐다 (PlotBuilder.create(deps, …)deps만 간다).