본문 바로가기
카테고리 없음

D3.js 바차트 (스케일 설정, 데이터 바인딩, 분기 거버넌스)

by UX 디자인 전문가 2026. 6. 19.

D3.js 바차트
D3.js 바차트

솔직히 저는 D3.js를 처음 봤을 때 "이걸 왜 쓰나" 싶었습니다. Recharts나 Chart.js로 바차트 하나 만드는 데 30분이면 충분한데, D3.js는 좌표 하나 찍는 것도 개념을 따로 공부해야 하거든요. 그런데 B2B 어드민 외주를 여러 건 진행하면서 생각이 바뀌었습니다. 데이터를 DOM에 직접 바인딩하는 방식 자체가 다르고, 그 차이가 복잡한 인터랙션이 필요한 프로젝트에서 결국 드러납니다.

스케일 설정: "좌표계가 거꾸로"라는 게 처음엔 이해가 안 됐습니다

D3.js로 바차트를 만들 때 가장 먼저 막히는 게 스케일(Scale) 설정입니다. 스케일이란 원본 데이터 값을 실제 픽셀 좌표로 변환해주는 함수입니다. 예를 들어 값이 0~100인 데이터를 화면 높이 400px 안에 표현할 때, 어떤 값이 몇 px 위치에 와야 하는지를 자동으로 계산해주는 것이죠.

여기서 처음 당황했던 부분이 있습니다. Y축 스케일의 range를 설정할 때 높은 값에서 낮은 값 순서, 즉 [chartHeight, 0]으로 써야 합니다. 저는 당연히 [0, chartHeight]로 써야 한다고 생각했는데, SVG 좌표계는 왼쪽 상단이 원점(0, 0)이기 때문에 아래로 내려갈수록 Y값이 커집니다. 이걸 모르고 짜면 바차트가 거꾸로 렌더링됩니다. 제가 직접 겪었습니다.

X축에는 scaleBand를 씁니다. scaleBand란 여러 항목을 균등한 너비로 배분해주는 스케일로, 항목 수와 전체 너비를 넣으면 각 바(bar)의 위치와 너비를 자동으로 계산해줍니다. bandwidth() 메서드를 호출하면 패딩을 제외한 각 바의 실제 너비가 반환됩니다. Y축에는 scaleLinear를 사용합니다. scaleLinear란 연속적인 수치 데이터를 선형 비례로 픽셀 위치에 매핑하는 스케일입니다.

도메인(Domain) 설정도 중요합니다. 도메인이란 입력 데이터의 실제 값 범위를 의미합니다. X축 도메인에는 데이터 항목의 고유 식별자 배열을, Y축 도메인에는 [0, 최댓값 + 여유치]를 넣어야 바 위에 레이블이 잘릴 일이 없습니다. d3.max()로 데이터의 최댓값을 동적으로 추출해 도메인에 반영하면, 데이터가 바뀌어도 스케일이 자동으로 조정됩니다.

데이터 바인딩: enter/exit 패턴을 이해하면 인터랙션이 달라집니다

일반적으로 D3.js는 러닝커브가 높다고 알려져 있는데, 제 경험상 핵심 개념 하나만 잡으면 나머지는 생각보다 빠르게 따라옵니다. 그 개념이 바로 데이터 바인딩(Data Binding)의 enter/exit 패턴입니다.

데이터 바인딩이란 데이터 배열과 DOM 요소를 1:1로 연결하는 작업입니다. D3.js는 현재 DOM에 존재하는 요소 수와 데이터 배열의 길이를 비교해 세 가지 상태를 구분합니다.

  • enter: 데이터는 있는데 DOM 요소가 없는 상태 → 새 요소를 추가해야 합니다.
  • update: 데이터와 DOM 요소가 모두 존재하는 상태 → 속성을 갱신합니다.
  • exit: DOM 요소는 있는데 데이터가 없어진 상태 → 요소를 제거해야 합니다.

인터랙티브 차트를 만들 때 exit().remove() 처리를 빠뜨리면 체크박스로 항목을 해제해도 바가 화면에 그대로 남습니다. 처음엔 왜 사라지지 않는지 한참 디버깅했던 기억이 납니다.

또 하나 실수하기 쉬운 지점이 있습니다. data()의 두 번째 인자로 키 함수(key function)를 전달해야 한다는 점입니다. 키 함수란 D3.js가 데이터 항목과 DOM 요소를 정확히 매칭할 수 있도록 고유 식별자를 알려주는 함수입니다. 이걸 생략하면 D3.js는 배열 인덱스 기준으로 매칭하는데, 첫 번째 항목을 제거했을 때 마지막 바가 사라지는 현상이 생깁니다. 실제로 이 버그를 재현해봤고, 키 함수 하나 추가하는 것으로 해결됐습니다.

이처럼 D3.js의 enter/exit 패턴은 Recharts에서 데이터 배열만 교체하면 끝나는 방식과 본질적으로 다릅니다. 처음엔 번거로워 보이지만, DOM 조작 수준의 세밀한 제어가 필요한 경우에는 이 방식이 훨씬 강력합니다.

분기 거버넌스: 도구 도입보다 운영 체계가 더 오래갑니다

저는 B2B 어드민 외주에서 Recharts 위젯 24종을 디자인 시스템에 등록하고 분기마다 사용 현황을 추적해왔습니다. 분기 거버넌스가 없으면 "누가 어떤 위젯을 쓰는지" 파악이 금방 흐려집니다. 처음에는 위젯을 등록하는 것 자체에 집중했는데, 6개월쯤 지나니 등록된 위젯 중 실제로 쓰이는 것과 방치된 것이 갈리기 시작했습니다.

그래서 3가지 축을 기준으로 분기 리포트를 작성하기 시작했습니다.

  • 분기 사용 빈도: 어떤 위젯이 실제 화면에 쓰이고 있는지
  • 렌더링 성능: 위젯이 대량 데이터를 처리할 때 병목이 생기는 지점
  • 반응형 적합도: 24인치 이상 PC 모니터와 13~15인치 노트북 환경에서 레이아웃이 깨지지 않는지

세 번째 항목이 의외로 중요한데, 한국 어드민 사용자의 모니터 환경은 영문권 시장과 다릅니다. 국내 기업 환경에서는 PC 모니터 비율이 높고 와이드 레이아웃에 최적화된 브레이크포인트(Breakpoint)가 따로 필요합니다. 브레이크포인트란 화면 너비에 따라 레이아웃이 전환되는 기준 픽셀 값입니다. 영문권 표준 브레이크포인트를 그대로 쓰면 국내 어드민에서 차트가 너무 좁거나 레이블이 겹치는 경우가 생깁니다. 제가 직접 외주 클라이언트 피드백으로 확인했고, 이후에는 한국형 브레이크포인트 매트릭스를 별도로 정리해 운영 중입니다.

이 체계를 4건의 외주에 적용한 결과, 디자이너-개발 핸드오프 평균 기간이 8일에서 2일로 줄었고 신규 위젯 추가 시간은 평균 6시간에서 1시간으로 단축됐습니다. 단순히 차트 라이브러리를 교체해서 나온 숫자가 아닙니다. 분기 리포트가 팀 안에서 공통 언어 역할을 하면서 불필요한 커뮤니케이션이 줄었습니다.

국내 데이터 시각화 도구 도입은 꾸준히 늘고 있으며, 특히 어드민 시스템에서 차트 컴포넌트 재사용성에 대한 관심이 높아지고 있습니다(출처: 정보통신산업진흥원). D3.js 공식 문서 역시 스케일과 축(Axis) 모듈을 별도 패키지로 분리해 제공하고 있어, 필요한 기능만 골라 쓰는 모듈형 구조를 권장하고 있습니다(출처: D3.js 공식 문서).

D3.js 자체가 어렵다기보다는, 좌표계와 데이터 바인딩 철학이 기존 컴포넌트형 라이브러리와 다르다는 점에서 초입 진입이 까다롭습니다. 스케일 설정과 enter/exit 패턴 두 가지만 확실히 이해하면 나머지는 공식 문서를 참고하며 충분히 확장할 수 있습니다. 도구를 익히는 것과 별개로, 위젯 라이브러리를 팀 자산으로 유지하는 분기 거버넌스 체계를 함께 갖추는 것이 장기적으로 더 중요하다는 것이 제 결론입니다.


참고: https://www.youtube.com/watch?v=aHJCt2adSWA


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 브레인스토밍 연구