실시간 투자 정보 플랫폼 · 구현 기록 03

2-Layer Canvas 차트 엔진

정적 차트와 고빈도 포인터 UI를 두 개의 Canvas로 분리해 필요한 레이어만 다시 그리도록 설계했습니다.

실시간 투자 정보 플랫폼으로 돌아가기
01

문제 정의

캔들·거래량·축·분석선은 데이터나 화면 범위가 바뀔 때 갱신되지만, 크로스헤어와 툴팁은 포인터가 움직일 때마다 바뀝니다. 두 종류의 요소를 하나의 Canvas에 그리면 포인터 이동만으로도 전체 차트를 반복해서 다시 그리게 됩니다.

  • 변경 빈도가 다른 요소가 같은 렌더링 루프에 묶여 있었습니다.
  • 포인터 이동은 초당 많은 이벤트를 발생시킵니다.
  • 정적 차트까지 다시 그리면 불필요한 연산과 페인팅이 증가합니다.
02

Layer Separation

레이어표현 요소갱신 시점
Base Canvas캔들, 거래량, 가격·시간 축, 지지·저항선데이터·범위·크기 변경
Overlay Canvas크로스헤어, 포인터, 툴팁, 선택 상태포인터 이동·사용자 인터랙션
┌────────────────────────────┐
│ Overlay Canvas             │  ← pointer / tooltip / hover
├────────────────────────────┤
│ Base Canvas                │  ← candle / volume / axis / line
└────────────────────────────┘
03

Rendering Flow

Data / Viewport Change ──→ drawBase()
Pointer Move ─────────────→ drawOverlay()
                              ↓
                    requestAnimationFrame
  1. 데이터 또는 화면 범위가 바뀌면 Base Canvas를 갱신합니다.
  2. 포인터 좌표는 차트 좌표계로 변환합니다.
  3. 크로스헤어·툴팁 상태를 Overlay Canvas에만 그립니다.
  4. requestAnimationFrame 기준으로 여러 입력을 한 번의 화면 갱신에 묶습니다.
04

좌표와 인터랙션

변환역할
Time → X시계열 인덱스 또는 시간을 화면 가로 좌표로 변환
Price → Y가격 범위를 화면 세로 좌표로 변환
Pointer → Data마우스 위치에서 가장 가까운 시점과 가격을 계산

렌더링 레이어는 분리했지만 같은 좌표 변환 규칙을 사용해 Base Canvas의 데이터와 Overlay Canvas의 포인터 UI가 정확히 일치하도록 구성했습니다.

05

Before / After

구분단일 Canvas2-Layer Canvas
포인터 이동전체 차트 다시 그리기Overlay만 갱신
렌더링 책임정적·동적 요소 혼합변경 빈도에 따라 분리
성능 분석병목 범위가 넓음레이어별 갱신 조건 확인 가능

무조건 덜 그리는 것보다, “무엇이 언제 변하는가”를 기준으로 렌더링 책임을 나누는 것이 핵심이었습니다.

06

결과

  • 포인터 이동 시 Overlay Canvas만 갱신합니다.
  • 정적 차트와 고빈도 UI의 갱신 조건이 분리되었습니다.
  • 차트 엔진의 렌더링 흐름과 디버깅 범위가 명확해졌습니다.