DERMA:CODE Chart Library
커스텀 Canvas 기반 차트 시각화 라이브러리
DERMA:CODE 플랫폼의 의료 데이터 시각화를 위해 Canvas API 기반으로 자체 설계한 차트 라이브러리. 플랫폼 디자인 시스템과 긴밀하게 통합되며, npm 패키지로 배포하여 독립적으로 사용 가능합니다.
The Challenge
DERMA:CODE 플랫폼은 6축 피부 점수를 표현하는 Hexa 차트 등 기존 라이브러리로는 대응할 수 없는 의료 특화 시각화가 필요했고, 동시에 플랫폼의 시각적 아이덴티티와 일관된 디자인 시스템 위에서 동작해야 했습니다.
- D3, Chart.js 등 범용 라이브러리로는 Hexa 차트, Level 차트 등 도메인 특화 차트 타입을 구현하기 어려움
- 차트마다 개별 스타일링이 적용되어 플랫폼 전체의 시각적 일관성이 깨지는 상황
- 상담 화면에서 복수의 차트가 동시에 렌더링되며, SVG 기반 접근으로는 프레임 드랍이 발생
- 향후 다른 프로젝트에서도 재사용할 수 있도록 플랫폼 코드베이스와 분리된 독립 패키지 구조가 필요
Technical Decisions & Approach
플랫폼 종속 없이 독립 사용이 가능하면서도 DERMA:CODE 디자인 시스템과 긴밀하게 연동되는 구조를 목표로, Canvas API 렌더링 엔진 위에 테마 시스템과 7가지 도메인 특화 차트 타입을 설계했습니다. 모노레포 구조로 라이브러리와 데모 앱을 함께 관리하며, Storybook을 통해 각 차트의 인터랙션과 테마 변형을 문서화했습니다.
왜 차트 렌더링에 SVG 대신 Canvas API를 선택했나요?
상담 화면에서 Hexa, Bar, Line 등 복수 차트가 동시에 렌더링되는 구조상, SVG의 DOM 노드 기반 접근은 차트 수가 늘어날수록 리플로우 비용이 증가합니다. Canvas의 비트맵 렌더링은 DOM 트리에 영향을 주지 않아 동시 렌더링 시 안정적인 프레임을 유지할 수 있었고, 애니메이션에 필요한 픽셀 단위 제어도 가능했습니다.
왜 D3나 Chart.js 대신 커스텀 라이브러리를 구축했나요?
D3는 시각화 자유도는 높지만 차트 단위 추상화가 없어 매번 로우레벨 코드를 작성해야 했고, Chart.js는 차트 타입 확장이 제한적이었습니다. 특히 Hexa 차트처럼 6축 데이터를 의료 맥락에 맞게 표현하는 커스텀 타입은 기존 라이브러리 위에서 구현하면 오히려 우회 코드가 늘어나 유지보수 비용이 더 높아진다고 판단했습니다.
테마 시스템을 어떻게 설계했나요?
색상, 타이포그래피, 간격, 불투명도 등을 디자인 토큰으로 정의하고, light·dark·minimal·colorful 4가지 프리셋 테마를 제공했습니다. 각 테마는 토큰 단위로 오버라이드 가능하여, 차트 인스턴스별 스타일링을 허용하면서도 전체적인 시각 일관성을 유지합니다.
왜 tsup과 모노레포 구조를 선택했나요?
pnpm workspace 기반 모노레포로 라이브러리(core)와 데모 앱(storybook)을 분리하되 같은 저장소에서 관리하여, 코드 수정 후 즉시 시각적 결과를 확인할 수 있는 개발 루프를 구축했습니다. 빌드 도구로는 tsup을 선택해 CJS + ESM 듀얼 출력과 TypeScript 선언 파일 생성을 단일 설정으로 처리했고, esbuild 기반이라 빌드 속도도 빨라 반복 개발에 적합했습니다.
Results & Impact
- 7가지 도메인 특화 차트 타입으로 DERMA:CODE 전체 시각화 레이어를 단일 라이브러리로 통합
- 테마 시스템 도입으로 신규 화면 추가 시 차트 스타일링 작업 제거 — 디자인 토큰 적용만으로 일관된 UI 확보
- 50개 이상의 Storybook 스토리로 차트별 props, 테마 변형, 인터랙션을 문서화하여 팀 커뮤니케이션 비용 절감
- npm 패키지(@gaia-corporation/dermacode-chart-lib)로 배포하여 타 프로젝트에서 설치 한 줄로 재사용 가능
라이브러리 도입 이후 새로운 차트 화면 추가 시 시각화 구현 시간이 크게 단축되었으며, Storybook 기반 문서화를 통해 디자인 리뷰와 QA 과정이 간소화되었습니다.