레슨 2 / 8·20분
스케일과 축
스케일(Scale)이란?
실제 데이터 값(domain)을 화면의 픽셀 좌표(range)로 변환하는 함수가 스케일입니다. 예를 들어 매출 0~1000만원을 그래프 높이 0~300px에 매핑합니다. D3은 연속형, 서열형, 범주형 등 다양한 스케일을 제공합니다.
javascript
// 연속형 스케일: 숫자 → 픽셀
const yScale = d3.scaleLinear()
.domain([0, 1000]) // 데이터 범위: 0~1000
.range([300, 0]); // 픽셀 범위: 300~0 (SVG는 위가 0)
console.log(yScale(500)); // 150 (중간값)
console.log(yScale(0)); // 300 (바닥)
// 서열형 스케일: 카테고리 → 균등 분할 위치
const xScale = d3.scaleBand()
.domain(['1월', '2월', '3월', '4월', '5월'])
.range([0, 400])
.padding(0.2); // 막대 사이 여백 비율
console.log(xScale('3월')); // 해당 막대의 x 좌표
console.log(xScale.bandwidth()); // 각 막대의 너비
// 범주형 색상 스케일
const colorScale = d3.scaleOrdinal()
.domain(['A', 'B', 'C'])
.range(['#e41a1c', '#377eb8', '#4daf4a']);축(Axis) 생성하기
D3의 축 생성기(axis generator)는 스케일을 받아 눈금선과 라벨을 자동으로 그려줍니다. axisBottom은 아래쪽 축, axisLeft는 왼쪽 축을 만듭니다.
javascript
const width = 500, height = 350;
const margin = { top: 20, right: 20, bottom: 40, left: 50 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height);
// 마진 적용을 위한 그룹 요소
const g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// 스케일 정의
const x = d3.scaleBand()
.domain(data.map(d => d.month))
.range([0, innerWidth])
.padding(0.2);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([innerHeight, 0])
.nice(); // 깔끔한 눈금 범위로 자동 조정
// X축 그리기
g.append('g')
.attr('transform', 'translate(0,' + innerHeight + ')')
.call(d3.axisBottom(x));
// Y축 그리기
g.append('g')
.call(d3.axisLeft(y).ticks(6));- •d3.scaleLinear() — 연속형 숫자 매핑 (가장 자주 사용)
- •d3.scaleBand() — 범주형 데이터를 균등한 띠(band)로 매핑
- •d3.scaleOrdinal() — 범주형 데이터를 이산적인 값(색상 등)에 매핑
- •.nice() — domain을 깔끔한 반올림 값으로 확장
- •d3.axisBottom(scale) / d3.axisLeft(scale) — 축 생성기
- •g.call(axis) — 그룹 요소에 축을 렌더링
💡
margin convention(마진 규약)은 D3 시각화의 표준 패턴입니다. SVG 안에 g 요소를 만들고 translate로 여백을 확보하면 축과 데이터 영역이 겹치지 않습니다.