Skip to content

용어 사전

이 프로젝트에서 쓰는 말의 뜻만 모았다. 누가 소유하고, 단위가 무엇이고, 코드 어디에 있는가까지 적는다 — 같은 단어를 다른 뜻으로 쓰기 시작하면 좌표 버그가 조용히 생긴다.

구조와 의존 방향은 architecture.md에 있다.


좌표

도메인 (domain)

데이터 단위로 표현한 값 구간 [min, max]. "2024년 1월~3월", "가격 120~180" 같은 것. 화면 크기와 무관하다.

pan/zoom은 x 도메인을 옮기고, y 도메인은 시리즈가 차지하는 값 범위에 맞춘다.

ts
scale.getDomain() // [120, 180]

범위 (range)

화면 픽셀로 표현한 구간 [start, end]. 도메인이 실제로 어디에 그려질지다.

start > end인 역방향을 허용한다. 화면 y는 아래로 증가하므로 값 축은 [bottom, top]으로 설정해야 큰 값이 위에 온다. 이 반전을 스케일이 들고 있는다 — 그래야 차트와 축이 같은 좌표를 본다.

ts
yScale.setRange(area.bottom, area.top) // [460, 32]

domain은 데이터, range는 픽셀. 이 문서에서 "범위"라는 말이 픽셀이 아닌 뜻으로 쓰이는 곳은 Range { min, max } 타입뿐이다(아래 값 범위).

스케일 (Scale)

도메인 ↔ 범위의 단방향 매핑. scale(value)가 데이터 → 픽셀, invert(px)가 픽셀 → 데이터다.

pan/zoom에서 도메인이 계속 바뀌므로 가변 객체다. 구현은 LinearScale, LogScale (scale/).

x 매핑 (XMapping)

데이터의 x가 화면 어디에 놓이는가. 시리즈·장식이 x에 대해 아는 전부다. 스케일은 이 아래에서 도메인↔픽셀만 하고, "도메인이 시간인가 봉 번호인가"는 매핑이 정한다 → ADR-0021

  • continuousX — 기본. 도메인이 곧 x라 빈 구간은 화면에서도 빈 자리다.
  • barIndexX — 봉 번호 좌표계. 봉은 x 간격과 무관하게 이웃과 한 칸이라 주말·휴장이 공백으로 벌어지지 않는다. 과거를 prepend하면 음수 인덱스로 확장된다 — 기존 봉의 인덱스가 안 변해 보던 창이 그대로다.

도메인은 매핑의 공간이지만 밖으로 나가는 것은 전부 x다 — 이벤트, 십자선, 뷰포트, 눈금 라벨.

보는 상태 (ChartState)

사용자가 pan·zoom·드래그로 만들었고 새로고침 뒤에도 돌아오기를 기대하는 것 전부를 한 값으로 — { xDomain, panes: [{ flex, autoScale, valueDomain?, invert? }] } → ADR-0022

데이터도, 시리즈 구성도, 스타일도, 커서 위치(입력 에코)도 아니다. getState()로 읽고 stateChange로 듣고 applyState()로 되먹인다 — 코어는 거울이고, controlled 모양은 React 래퍼가 조립한다.

뷰포트 (Viewport)

지금 화면이 보고 있는 데이터 구간과 캔버스 크기를 함께 담은 값.

ts
{ startX, endX, width, height }

startX/endX데이터의 x이고 width/height는 CSS 픽셀이다. 데이터 매니저가 이걸 받아 잘라낼 구간과 남길 점 개수를 정한다. 봉 번호 좌표계에서도 x다 — 도메인(인덱스)은 Plot이 매핑으로 되돌려서 넘긴다. 화면이 x와 다른 공간이면 솎기가 버킷을 나눌 좌표(screenXOf)가 함께 실린다.

그림 영역 (PlotArea)

패딩을 뺀 실제 그림 직사각형 { left, right, top, bottom }. 화면 좌표(px).

plotAreaOf(size, padding)이 만든다 (primitives/geometry.ts).

슬라이스 (slice)

그림 영역을 pane 개수만큼 가로로 자른 조각. 각 pane이 자기 슬라이스를 setArea로 받아 값 축의 range만 갱신한다 (도메인은 그대로).

패딩 (Padding)

캔버스 가장자리와 그림 영역 사이 여백. 축 라벨이 놓이는 자리다.

CSS 픽셀 / 물리 픽셀

CSS 1px은 화소 하나가 아니다. 레티나는 CSS 1px을 물리 화소 2×2개로 그린다. 그 배수가 DPR(devicePixelRatio)이다.

코드가 다루는 좌표는 전부 CSS 픽셀이다. 물리 픽셀이 나타나는 곳은 canvas.width/height(백킹 스토어) 하나뿐이고, 배율은 컨텍스트 변환이 혼자 진다 → ADR-0003


데이터

데이터 점 (data point)

x를 가진 최소 단위(BaseDataPoint). xnumber | string | Date다.

타입값 필드쓰임
LineDataPointy라인·area·baseline
OHLCopen/high/low/close(volume?)캔들·OHLC 바
HistogramPointy(color?)히스토그램(거래량·MACD)

ynumber | null이다 — null값 없음이다(아래). HistogramPoint.color가 점마다 있는 이유는 등락이 스타일이 아니라 데이터의 사실이고, 그 사실을 아는 것은 점을 만드는 쪽뿐이기 때문이다.

원본 (source) / 보이는 데이터 (visible data)

  • 원본한 등록이 가진 배열 전체다(addSeries({ data }) 또는 handle.setData). 무대가 아니라 등록의 것이라 시리즈마다 다를 수 있다 — BTC와 ETH를 한 무대에 그리는 것이 그래서 된다. x 오름차순이어야 한다 — 자르기가 이진 탐색이고, 어기면 DataError가 난다 → ADR-0008
  • 보이는 데이터는 뷰포트로 자르고 데시메이션까지 거친 결과다.

파생 시리즈의 derive원본을 받는다. 이동평균처럼 앞을 되돌아보는 지표가 화면 왼쪽 끝에서 끊기지 않으려면 그래야 한다.

접근자 (CoordinateAccessor)

점에서 배치용 숫자를 꺼내는 방법. getX(point), getY(point).

같은 OHLC라도 x 범위를 잴 땐 x, y 위치를 잡을 땐 close가 필요하다. 꺼내는 규칙을 점 타입에서 분리해 둔 것이다 (data/accessors.ts).

데시메이션 (decimation)

화면 폭보다 점이 많을 때 솎아내는 것. 픽셀 하나에 여러 점을 겹쳐 그리는 낭비를 막는다.

전략방식
M4Decimation픽셀 컬럼마다 first·last·min·max 넷기본
OhlcAggregation캔들을 고르지 않고 합친다candleSeries()가 들고 온다
LttbDecimation삼각형 넓이가 큰 점을 남겨 모양을 보존한다
SimpleDecimation일정 간격으로 건너뛴다

버킷당 한 점만 남기는 전략(계단·LTTB)은 극값을 잃는다 — 같은 버킷에 위아래 스파이크가 있으면 하나는 반드시 진다. 그래서 기본이 M4다 → ADR-0012

집계 (aggregation)

솎아내기가 원본 점 중 일부를 고르는 것이라면, 집계는 여러 점을 하나로 합친다. 캔들이 그래야 하는 쪽이다 — 한 봉을 고르면 나머지의 고가·저가가 사라지므로, 1분봉 다섯을 5분봉 하나로 접듯 open=첫 것, high=max, low=min, close=마지막 것으로 합친다.

층 (tier)

절반씩 줄여 미리 쌓아 둔 데이터. 줌아웃 상태에서 팬할 때 창 전체가 아니라 층 하나만 훑으면 되게 한다. tiered 옵션으로 켜며 기본은 꺼져 있다 — 메모리가 최대 두 배고 데이터가 바뀔 때마다 버려지기 때문이다.

값 범위 (Range)

{ min, max } 한 쌍. 도메인·픽셀 어느 쪽도 아닌 그냥 구간이다. x 범위(getXRange)와 시리즈의 값 범위(valueExtent)가 이 타입을 쓴다.

valueExtent

시리즈가 y축에서 차지하는 구간. 라인은 점 하나라 min === max지만 캔들은 low~high를 차지한다. 숫자 하나로 표현할 수 없어서 Range다.

pane의 valueExtent는 소속 시리즈들의 합집합이다. 잴 것이 없으면 null 이고, 그 자리에 {0,0}을 내면 아직 데이터가 안 온 시리즈가 값 축을 0으로 끌어 내린다.

값 없음 (whitespace)

y: null. 자리는 있고 값이 없다.

점을 아예 빼는 것과 다르다 — 빼면 x가 이어져 선이 그 구간을 가로지른다. 지표의 warmup(MA(20)의 앞 19개)과 어떤 시리즈에만 있는 봉이 같은 것이다.

세 곳이 같이 안다: 선은 거기서 끊기고, valueExtent는 세지 않고, 솎기는 삼키지 않는다 → ADR-0020

x는 비울 수 없다. 어디에 둘지 모르는 점은 구멍으로도 못 그리므로 파싱 실패는 DataError로 던진다.

계산 노드 (computation) / 출처 (Source)

출처read(): T[] 하나짜리 계약이다. 그릴 점이 어디서 오는지를 값으로 넘기는 자리 — 시리즈 손잡이도, 계산 노드의 갈래도 출처다.

계산 노드는 입력 출처들을 받아 갈래 여럿을 내는 계산이다. MACD처럼 한 계산이 여러 그림을 먹일 때 계산을 한 번만 돌린다. 만드는 것은 자유 함수 computation({ inputs, calc })이고 무대에 등록하지 않는다.

당김이다. 갈래를 읽을 때 입력 배열의 신원이 그대로면 지난 결과를 그대로 준다 — 구독을 배선할 것이 없고, 아무도 안 그리는 갈래는 값을 만들어 두기만 한다.

derive는 입력 하나·출력 하나짜리 설탕으로 남는다.

리핏 (fit)

도메인을 데이터에 다시 맞추는 것. fitDomains(), fitValueDomain().

x를 리핏하는 것은 셋뿐이다 — 첫 데이터 도착 한 번, 명령형 handle.setData, fitDomains(). 증분 추가(handle.prepend/append)도, 선언형 data 갱신도 리핏하지 않는다: 과거를 불러올수록 화면이 줌아웃되고, 나중에 얹은 시리즈 때문에 보던 창이 합집합으로 튀기 때문이다 → ADR-0001


그리는 것

시리즈 (Series)

데이터를 어떤 모양으로 그릴지만 아는 것. 책임은 둘뿐이다.

ts
valueExtent(data): Range   // y를 얼마나 차지하는가
draw(renderer, context)    // 어떻게 그리는가

선택 속성 둘(decimation·coordinates)이 더 있다 — "점 타입을 아는 쪽이 정책을 말한다"의 자리다.

그리드·축·pan/zoom·레이어는 Plot의 것이라 시리즈는 모른다. 내장 구현은 여섯이다: LineSeries·CandleSeries·HistogramSeries·AreaSeries·BaselineSeries· BarSeries (series/).

파생 시리즈 (derived series)

원본에서 계산해 낸 값을 그리는 시리즈. 이동평균, RSI 같은 지표다.

ts
pane.addSeries({ series, derive: (source) => points, coordinates })

결과는 원본 배열의 참조로 캐시한다. 캐시가 없으면 렌더마다 다시 계산된다.

원본과 파생 결과의 점 타입은 등록 안에 갇힌다. Pane은 그 타입을 모르고 등록이 할 줄 아는 것(valueExtent·draw)만 부른다. 그래서 getSeries()가 돌려주는 것은 SeriesId(= unknown)다 — 밖에서 하는 일이 === 비교뿐이라 그만큼만 준다.

pane에 점 타입 매개변수가 없는 이유가 이것이다. BTC(OHLC)와 ETH(라인)를 한 pane에 나란히 담을 수 있다. 타입이 필요한 곳은 데이터를 넣고 읽는 자리뿐이고, 그건 addSeries가 돌려준 손잡이에 남는다.

장식 (Decoration)

무대에 그리지만 데이터의 표현은 아닌 것. 크로스헤어 선, 현재가 라인, 구간 음영, 워터마크, 그리드.

Series와 가르는 기준은 하나다 — 값 축 리핏에 참여하지 않는다. 목표가 라인을 시리즈로 등록하면 valueExtent가 y를 끌어당겨 가격이 납작해진다.

ts
pane.addDecoration(d, { zIndex })   // y가 필요한 것
plot.addDecoration(d, { zIndex })   // 무대 전체를 쓰는 것

겹치는 순서는 zIndex 하나로 정해진다. 시리즈가 그려지는 자리가 SERIES_Z (= 0)이고 장식은 그 앞뒤로 끼어든다 — BELOW_SERIES(−1000, 그리드가 여기)와 ABOVE_SERIES(1000, 생략하면 여기)가 이름 붙은 두 자리다. 같은 z끼리는 등록 순서다 → ADR-0010

확장 (extension)

무대 위에 얹는 것 전부의 총칭use()에 꽂는 플러그인(crosshair· tooltip·legend·syncX·paneMaximize·드로잉 툴·지표)과 등록에 꽂는 장식 팩토리(priceLine·markers·span·watermark)를 아우른다 (ADR-0026 "확장은 포장된다"). 소비하는 것은 능력 인터페이스와 플러그인 계약뿐이다.

사는 곳이 자격을 가르지 않는다 — 코어 내장 확장은 core/src/extensions/, 외부 확장은 @finchart/tools·@finchart/indicators지만 같은 계약 위에 있다. 차이는 기본 제공 여부뿐. 무대가 스스로 설치하는 것만 확장이 아니다 — 그 기준으로 무대의 것은 grid 하나다(plot/grid.ts).

플러그인·확장·패키지는 경쟁하는 분류가 아니라 서로 다른 세 축이다 — 같은 crosshair가 플러그인이고(형식), 내장 확장이고(관계), 코어와 함께 배포된다(배포). 새 확장의 자리는 세 질문으로 정해진다 → ADR-0036

낱말묻는 질문반대말
플러그인형식어떻게 설치·해제되나장식 팩토리
확장관계무대의 부품인가, 위인가무대의 부품
패키지배포코어와 같이 설치되나코어 내장

내장/외장의 판별 질문은 **"이 기능의 이웃이 계속 생기는가"**다 — 자라는 목록(지표 17+·드로잉 12+)은 별도 패키지, 무대의 어휘로 닫히는 낱개 기능(십자선·현재가선·동기화)은 내장.

플러그인 (Plugin)

확장의 두 형식 중 설치·해제가 있는 쪽. Plugin<Host, Api>는 호스트를 받아 dispose 있는 API를 돌려주는 함수고, plot.use()에 꽂는다. pluginApi(api, dispose)로 짓는다 — 스프레드로 합치면 disposed 접근자가 값으로 복사돼 영영 false로 굳는다 (ADR-0026, 생명주기는 ADR-0029).

가르는 판별문: 입력·이벤트 구독·해제할 것이 있으면 플러그인(crosshair· tooltip·legend·syncX·paneMaximize·drawingTools·attach* 지표), 그리기만 하면 장식 팩토리(priceLine·markers·span·watermark — addDecoration에 꽂고 remove를 돌려받는다).

호스트는 Plot 통짜가 아니라 필요한 능력의 교집합으로 요구한다 — DecorationHost & RenderRequester처럼. 함수 매개변수는 반공변이라 덜 요구하는 플러그인이 더 주는 호스트를 그대로 받는다.

Pane

값 축 하나를 공유하는 시리즈들의 묶음. 이 라이브러리에서 겹쳐 그리기와 별도 영역을 같은 개념으로 다루는 단위다 → ADR-0002

  • 같은 pane에 넣으면 → 겹쳐 그려진다 (나중에 넣은 것이 위)
  • 다른 pane에 넣으면 → 위아래로 나뉜 영역에 그려진다

x는 Plot이, y는 Pane이 소유한다. pan/zoom은 x에만 걸리므로 pane이 몇 개든 저절로 같이 움직인다.

plot.mainPane은 항상 있다. pane을 따로 만들지 않으면 모든 시리즈가 여기 들어간다.

Plot

무대. 캔버스·레이어·x축·상호작용·pane 목록을 소유하고, 데이터와 시리즈는 갈아끼워진다. 무대에 올려둔 것(보고 있는 구간, 오버레이 DOM)은 갈아끼움에도 살아남는다 → plot-contract.md

축 (Axis)

스케일의 도메인과 range를 읽어 눈금 목록을 계산하는 것. 그리지는 않는다.

눈금 밀도는 픽셀에서 나온다. 사람이 읽을 수 있는 간격(가로 80px, 세로 40px)을 확보하도록 1·2·5 × 10ⁿ 중에서 고른다. 그래서 짧은 pane은 눈금이 저절로 성겨진다.

눈금 (Tick)

{ value, position, label } — 데이터 값, 픽셀 위치, 표시 문자열.

그리드선 (GridLine)

눈금 위치에 긋는 보조선. 눈금과 같은 계산 결과에서 나온다. 각자 계산하면 언젠가 어긋난다.

구분자 (divider)

pane 사이에 놓인 DOM 손잡이. 끌어서 높이를 바꾼다. 캔버스가 아니라 DOM인 이유는 커서 모양과 히트 영역을 브라우저에 맡기고, 캔버스를 다시 그려도 끌던 손잡이가 사라지지 않게 하기 위해서다.

xDomainChange

보고 있는 x 구간이 바뀌었음을 알리는 이벤트. pan · zoom · 리핏에서 돌고, 값이 실제로 달라질 때만 돈다.

ts
{ startX, endX, dataRange }

dataRange는 무대가 가진 데이터의 x 범위(시리즈들의 합집합)라, 끝에 얼마나 가까운지를 페이로드만으로 잴 수 있다. 증분 추가는 도메인을 안 건드리므로 조용하다 — 그래서 핸들러 안에서 과거를 이어 붙여도 재귀하지 않는다 → ADR-0009

크로스헤어 (crosshair)

커서 위치를 의미로 바꿔 알리는 이벤트. 좌표만 넘기지 않는다.

ts
{ position, x, pane, value }

x는 pane과 무관하게 같고(x축이 하나뿐), value는 커서가 올라간 그 pane의 스케일로 읽는다. 여백이면 panevaluenull이다.


레이어와 렌더

레이어 (ChartLayers)

컨테이너 안에 겹쳐 세운 두 층.

정체담는 것
데이터 캔버스<canvas>시리즈, 그리드
오버레이<div>축 라벨, 구분자, annotation

오버레이는 기본적으로 포인터 이벤트를 통과시킨다. 캔버스를 다시 그려도 오버레이 DOM은 살아남는다.

그리기 대상 (DrawTarget)

원시 셋 — drawLine/drawShape/drawText. 시리즈가 렌더러에 대해 아는 전부다.

구상 렌더러가 아니라 이것을 요구하므로 시리즈는 명령이 어떻게 쌓이고 언제 재생되는지 모른다. 그리드는 그중 drawLine 하나만 요구한다(GridTarget) → ADR-0006

넷째 자리 drawCustom?선택이고 확장의 것이다 — 서드파티가 자기 원시를 내는 문이라, 셋은 그대로 두고 새 그리기는 전부 여기로 간다. 부를 때는 반드시 자유 함수 drawCustom(target, draw)를 거친다: 그 메서드가 없는 표면에서 옵셔널 체이닝이 조용히 아무것도 안 그리는 길로 빠지기 때문이다 → ADR-0028

렌더러 (Renderer / CanvasRenderer)

DrawTargetclear()·commit()을 더한 것. Plot이 아는 전부다. 프레임 경계를 다루므로 시리즈에게는 보이지 않는다.

CanvasRenderer가 기본 구현이고, 호출 즉시 그리지 않는다.getCommands() 같은 검사 창구는 구현의 것이지 계약이 아니다.

명령 (DrawCommand)

그리기 호출을 쌓아 둔 기록 — drawLine·drawShape·drawText·custom, 그리고 자리를 나눠 주는 쪽만 쓰는 clip. commit()에서 clearRect 후 순서대로 2D context에 재생한다.

type으로 갈리는 태그드 유니온이다. 재생부의 switch가 전수 검사를 받으므로 명령을 더하면 컴파일이 깨진다.

  • clear()쌓인 명령을 버리는 것이지 화면을 지우는 게 아니다.
  • 화면이 실제로 지워지는 시점은 commit()이다.

덕분에 부분 상태가 화면에 보이지 않고, 2D context 없이 "무엇을 그리려 했는가"를 테스트할 수 있다 → rendering.md

스케줄러 (RenderScheduler)

언제 그릴지를 정하는 것. Plot은 "다시 그려야 한다"만 알리고 시점은 모른다.

예약이 이미 있으면 다시 요청해도 아무 일도 없다 — 합치는 것이 스케줄러의 일이라 같은 프레임의 요청은 그림 하나가 된다.

구현언제
frameScheduler다음 프레임에 한 번 (프리셋 기본값)
immediateScheduler요청 즉시
manualScheduler테스트가 flush()할 때

상태는 여전히 동기로 바뀐다. 늦춰지는 것은 캔버스에 그리는 일뿐이다 → ADR-0004


레이아웃

용어
flexpane의 높이 비율. 상대값이라 창 크기가 바뀌어도 비율이 남는다
minHeightpane 높이의 바닥(px). 기본 40
paneGappane 사이 간격(px)
valuePadding값 도메인 위아래 여유 비율. 기본 0.1

바닥에 닿은 pane은 고정되고 남은 공간을 나머지가 다시 나눈다. 바닥 합이 전체를 넘으면 다 같이 비례 축소한다 (plot/layout.ts).


조작

용어
panx 도메인을 옆으로 민다. 오른쪽으로 끌면 이전 구간을 본다
zoom한 점을 고정한 채 x 도메인을 넓히거나 좁힌다
InteractionTarget조작을 적용하는 쪽. Plot이 구현한다
InteractionHandler입력을 조작 의도로 옮기는 쪽. PointerInteractions

픽셀 진입점(panByPixels, zoomAtPixel)이 Plot에 있는 이유는 픽셀↔도메인 환산에 스케일이 필요한데, 그건 Plot만 알기 때문이다. 핸들러가 스케일을 알게 되면 입력 층이 좌표계까지 떠안는다.


던지는 것

가르는 기준은 "어디서 났나"가 아니라 "소비자가 할 수 있는 일이 있나"다. 잡을 수 없는 것을 잡을 수 있는 것과 같은 타입으로 두면, 데이터 오류를 삼키려던 catch가 프로그래머 버그까지 조용히 삼킨다.

무엇언제소비자가 할 수 있는 일
DataError바깥에서 들어온 이 계약을 어겼다 — x 정렬(ADR-0008), x 파싱, 구멍의 자리잡는다. 서버 응답은 런타임에 실제로 어긋난다
ContractError호출부가 API를 계약과 다르게 썼다 — 지울 수 없는 pane, 양수 아닌 확대 배율, 중복 시리즈 id, 데이터를 소유하지 않는 등록없다. 코드를 고쳐야 하는 버그다
RenderError배선이 맞지 않아 그릴 수 없다 — headless 레이어에 DOM 라벨, context 없는 표면에 캔버스 렌더러, 픽셀 없는 무대에서 스크린샷없다. 협력자 조합을 고쳐야 한다

같은 렌더러라도 둘로 갈린다: context 없는 표면에 꽂은 것은 배선이고, 점 하나로 선을 그으라는 것은 호출이다.

이름의 문법

공개 API 이름이 따르는 규칙 (2026-08-11 클린 리뷰 N1). 소비자가 이름만 보고 "무엇을 돌려주고 어디에 꽂는가"를 추론할 수 있어야 한다.

  • 재료는 명사다crosshair()·tooltip()·legend()·drawingTools() 처럼 use에 꽂는 플러그인 팩토리, lineSeries()·priceLine()처럼 등록에 꽂는 재료. 만들어서 꽂으면 끝이다.
  • 계산 노드도 명사다macd()·rsi()는 값(노드)을 돌려줄 뿐 아무것도 설치하지 않는다 (ADR-0018 — 계산은 값이다).
  • attach*는 배선 묶음이다attachMacd()처럼 계산 노드 + 시리즈 + pane 소유까지 한 번에 설치하는 지표 플러그인. bare 이름과 attach가 짝으로 있으면, bare는 계산만 하고 attach가 화면에 얹는 쪽이다plot.use(macd(...))ContractError로 거절되는 이유가 이 문법이다 (use(plugin)는 함수여야 한다 — 계산 노드는 객체다). 예전에 여기 *"아무것도 안 그린다"*고 적혀 있었는데 checkPlugin이 서면서 조용한 무동작이 큰 소리로 던지는 것으로 바뀌었고 이 줄만 안 따라왔다. 틀린 쪽이 더 나빴다: 콘솔이 이미 답을 말하는데 독자는 빠진 attach*를 찾는다.
  • create*는 계약의 기본 구현 팩토리다createCanvasRenderer처럼 구현 클래스는 숨기고 계약 타입으로 돌려준다.
  • 값이냐 함수냐는 상태가 정한다 — 같은 슬롯에 꽂히는 것들이라도, 무상태면 값(immediateScheduler·noStyle)이고 매개변수나 인스턴스 상태가 있으면 함수(frameScheduler(view?)·manualScheduler()가 인스턴스마다 새 flush를 만든다)다. 호출 모양이 갈리는 것은 비대칭이 아니라 그 차이를 드러내는 것이고, 무상태를 함수로 감싸면 호출마다 같은 클로저를 새로 짓는 의식이 된다. 오용은 컴파일러가 잡는다.

규칙에 안 맞는 이름 하나(현행 유지): @finchart/domcssReader(container)StyleReader(계약)를 돌려주므로 create* 자리인데 접두가 없다. 개명하지 않기로 판단했다createCssReader는 ADR-0005·ADR-0019가 쓰는 옛 슬롯 이름(PlotDeps.createCssReader, 지금은 createStyleReader)과 겹쳐, 규칙 하나를 사면서 같은 이름이 두 시기에 서로 다른 것을 가리키게 된다. 그 비용이 규칙 순수성보다 크다. 베끼지 마라 — 새 이름은 위 규칙을 따른다.

(0.1.0 공개 표면 확정 때 일괄 판단한다던 개명 항목은 이 절로 닫혔다. 원장 A절 참조.)

헷갈리는 짝

AB가르는 기준
DataErrorContractError값이 틀렸다 / 부르는 법이 틀렸다
ContractErrorRenderError호출부를 고친다 / 배선을 고친다
도메인범위(range)데이터 단위 / 픽셀
Range 타입스케일의 range그냥 구간 / 화면 픽셀 구간
뷰포트그림 영역보이는 데이터 구간(+캔버스 크기) / 패딩 뺀 픽셀 사각형
ScaleAxis값↔픽셀 변환 / 눈금 계산
SeriesPane하나의 표현 / 값 축을 공유하는 묶음
PanePloty·시리즈 소유 / x·캔버스·상호작용 소유
handle.setDatahandle.append새 데이터셋(리핏 O) / 같은 데이터셋 이어붙이기(리핏 X)
손잡이(SeriesHandle)syncSeries데이터를 소유 / 목록을 소유
clear()commit()명령 버리기 / 화면 지우고 재생
scheduleRender()render()예약 / 지금 그리기
DrawTargetRenderer시리즈가 보는 것 / Plot이 보는 것
SeriesDecoration값 축을 차지함 / 차지하지 않음
Decoration확장(extension)계약 하나(그리기) / 총칭(플러그인·장식 팩토리)
data.widthcanvas.widthCSS 픽셀 / 물리 픽셀
flexminHeight비율 / 바닥

관련

  • PRINCIPLES.md — 원칙 (이름으로 참조한다)
  • architecture.md — 모듈 구조와 의존 방향
  • plot-contract.md — 어떤 메서드가 무엇을 건드리는가
  • rendering.md — CSS 변수에서 픽셀까지