정의
Canvas 위에 그리는 노드(그래프·네트워크 시각화의 점)의 색·크기·반짝임 같은 장식 값을, 매 프레임 Math.random()이 아니라 노드 ID에서 항상 같은 값이 나오도록 계산하고, 그리기 직후 Canvas 2D 컨텍스트 상태(globalAlpha, shadowBlur 등)를 기본값으로 되돌리는 렌더링 패턴이다.
왜 필요한가
force-directed graph 라이브러리는 보통 Canvas 2D(브라우저가 픽셀 버퍼에 직접 그리는 API)로 노드를 그린다. DOM 요소가 아니므로 CSS @keyframes를 노드 하나에 직접 걸 수 없다. Math.random()으로 색을 고르면 새로고침마다 같은 문서 노드가 다른 색·박자로 보여 그래프가 불안정해 보인다.
반짝임·광원 번짐을 넣으려면 노드 draw 콜백 안에서 시간에 따라 투명도를 계산해야 한다. 이때 globalAlpha나 shadowBlur를 설정한 뒤 복구하지 않으면 라벨·엣지·다음 노드까지 흐려지는 부작용이 생긴다. prefers-reduced-motion(애니메이션 줄이기 접근성 설정)을 쓰는 사용자에게는 반짝임을 멈춰야 한다.
동작 원리
- ID → 해시: 문서 ID 문자열을 작은 정수 시드로 바꾼다(암호학적 해시는 불필요, 시각적 분산만 목적).
- attach 시 visual 메타: 그래프 데이터에 노드가 붙을 때 색(hue/팔레트 인덱스), 반짝임 주기(period), 위상(phase)을 한 번 계산해 노드 객체에 저장한다.
- draw 콜백: 매 프레임
alpha = base + amplitude * sin(2π·t/period + phase)처럼 투명도만 갱신한다. 색상 팔레트는 고정. - 광원: 중심 원은 선명하게,
shadowColor·shadowBlur로만 얕은 번짐을 준다. - 상태 복구: 노드 하나를 그린 직후
ctx.globalAlpha = 1,ctx.shadowBlur = 0등으로 리셋한다. - reduced motion:
matchMedia('(prefers-reduced-motion: reduce)')이면 alpha=1 고정, 그래프 라이브러리의 자동 redraw(autoPauseRedraw)를 켜 반짝임 루프를 멈춘다. - 범례 분리: 노드 색이 카테고리를 뜻하지 않게 범례 점은 중립색을 쓴다.
실무 적용
- 별도
requestAnimationFrame루프를 만들기보다 이미 있는 graph redraw 루프를 재사용한다. - 시각 회귀는 reduced motion on/off, 320px 뷰포트에서 캡처 전 force layout 안정화를 기다린다.
트레이드오프
- ID 해시 팔레트는 충돌 시 비슷한 색이 나올 수 있으나, 수백 노드 규모에서는 허용 가능하다.
shadowBlur는 작은 반경·낮은 노드 수에 적합하다. 수천 노드에서는 페인트 비용이 커질 수 있다.- Canvas 애니메이션은 메인 스레드에서 돈다. 무거우면 노드 수·효과 강도를 줄이거나 WebGL 레이어를 검토한다.
사용하면 안 되는 경우
- 노드가 수십 개뿐이고 DOM/SVG로 충분하면 Canvas 커스텀 draw는 유지보수 비용만 늘릴 수 있다.
- 색이 카테고리 인코딩이어야 하면 ID 해시 색과 요구가 충돌한다 — 범례·데이터 채널을 분리하거나 색 스케일을 명시적으로 매핑한다.
- reduced motion을 무시하고 계속 반짝이면 접근성 위반이다.
흔한 실수
globalAlpha·shadowBlur를 리셋하지 않아 텍스트 라벨이 전체적으로 흐려진다.- 매 프레임 ID 문자열을 다시 해시해 CPU만 낭비한다 — attach 시점에 메타를 붙인다.
- 배경은 CSS로 반짝이는데 노드는 정적이라 UX가 어긋난다 — Canvas 경로에 별도 twinkle 로직이 필요하다.
autoPauseRedraw의미를 반대로 이해해 일반 모드에서 redraw가 멈춘다.
관련 개념
- bfs-document-relation-graph — 로컬 그래프 데이터·BFS 탐색
- critical-rendering-path — Canvas 페인트는 메인 스레드 렌더 경로
- css-view-timeline-entry-animation — DOM이 아닌 Canvas 노드에는 CSS 타임라인 불가