[PixiJS] D3 그래프에 PixiJS를 도입하게 된 계기

naring·2024년 3월 16일

PixiJS

목록 보기
1/5
post-thumbnail

우리 프로젝트의 캐치 프레이즈가 '함께 만들어나가는 지식의 별자리'이다. 여기서 별자리란, 우리 메인 페이지의 그래프 뷰를 의미한다. d3의 force-graph를 활용했다.
force-graph란 데이터의 노드와 그 사이의 링크를 시각화하는 데 사용되는, 시뮬레이션 기반의 그래프 렌더링 방법이다. 그러니까 물리학의 '힘'을 모방해 그래프를 그리는 것이다.

지금까지는 D3 라이브러리에서 svg 요소로 그래프를 그리는 방법을 채택해왔다. 하지만 데이터가 늘어남에 따라 그래프 렌더링 자체도 그렇고, 사용자와 상호작용하는 줌인 줌아웃, 검색, hover시 애니메이션 등이 아주 살짝 버벅거리는 느낌이 생겼다. 실제로 빌드 전 dev 모드에서는 상당히 지연이 생기기도 했다.

어떻게 그래프 렌더링을 최적화할까 ... "군집화"

원래 프로젝트를 시작할 때에는 군집화를 통해 최적화하려고 했었다. 아래 직방 사진처럼, 줌 레벨에 따라 뭉쳐서 보이거나, 하나로 보이는 식으로 말이다.

그러나 ...

우리가 적용하기엔 무리가 있었다.

  1. 정확한 위치의 부재
    지도는 위도/경도라는 정확한 위치가 존재한다. 하지만 우리 그래프는 화면에서 정확한 위치를 고정시킬 수가 없다. 위치를 고정시켜버리면 위치를 우리가 지정해주어야 하는데 모든 데이터가 생성 될 때마다 위치를 고정시켜 주기가 어렵다. 또한 이렇게 되면 반응형 구현이 어려워졌다.
  2. 줌인/줌아웃 시 증가할 노드의 개수 정하기의 어려움
    여기 지도에서는 군집화된 노드의 개수만 보여주지만, 우리는 노드 자체를 보여주어야 하는 요구사항이 있었다. 따라서 줌인이 될 때마다 증가시켜서 보여 줄 노드의 개수를 정했어야 했는데, 그룹마다 어떤 특성을 가질 지 모르기 떄문에 이 또한 문제가 되었다. 우리는 '상위 계층 태그' 라는 것으로 그룹을 만드는데, depth가 10개고 각 depth마다의 노드가 1개인 그룹과, depth는 3까지 있는데 각 depth마다 노드가 100개씩 있는 그룹을 줌 레벨에 따라서만 렌더링을 다르게 해주기는 무리였다 ...

이러한 이유로 그래프 렌더링의 다른 최적화 방법을 찾아 나섰다.

그리고 만난 canvas

그러다가 내가 그린 그래프 뷰에서는 svg요소를 사용해 그래프를 그렸다는 것을 알게 되었다. svg는 하나하나 DOM 요소가 되기 때문에 그래프 데이터가 많아지면 성능 저하에 영향을 미칠 수 있다. 따라서 canvas 요소로 코드를 바꾸기로 했다!
svg와 cavas를 비교 정리 한 내용은 다음에서 볼 수 있다.
그런데... canvas를 사용했을 때의 단점은 DOM 요소가 아니기 때문에 애니메이션 설정이 어렵다는 것이다! 물론 canvas API를 사용하면 되긴 하지만 직접적인 DOM 요소였던 svg에 비해 훨씬 불편하다. 따라서 여러 방법을 찾아보다가 pixi.js를 알게되었다.

pixi? webGL?

PixiJS는 고속, 가벼운 2D 웹 기반 렌더링 시스템이다. 게임, 데이터 시각화, 그래픽 집약적인 프로젝트 등의 디지털 콘텐츠를 아름답게 만들 수 있도록 설계되었고, WebGL을 지원하며, 필요한 경우 자동으로 HTML5의 canvas로 폴백한다. 이를 통해 사용자는 WebGL에 대한 사전 지식 없이도 하드웨어 가속의 힘을 즐길 수 있습니다. PixiJS는 정말 빠르며, 모든 디바이스에서 작동합니다.

webGL이란

웹 GL은 웹 기반의 3D 그래픽을 구현하는 데 사용되는 기술로, 웹 브라우저에서 하드웨어 가속 3D 그래픽을 지원하기 위해 만들어진 JavaScript API다. 쉽게 말하자면, 웹 기반의 그래픽 구현을 할 수 있게 도와주는 API다.

정리하자면, pixiJS는 webGL을 지원해 그래픽 구현에 도움을 주고, 만약 사용자의 조건에서 webGL이 동작하지 않는다면 알아서 canvas로 폴백해준다.

우려가 되었던 점

하지만 이미 NextJS를 사용하면서 NextJS 자체가 크기가 컸다. 따라서 라이브러리를 무지성 도입하기는 꺼려졌기 때문에 pixiJS를 도입하면 번들 크기가 너무 커지진 않을지 걱정했다. npm 기준으로 unpacked 사이즈가 7.62 MB인데, 웹 라이브러리 치고 작지 않은 크기다. 찾아보니 React-query가 2. 얼마 정도 d3는 873 kB...
고민이 되었지만 ... 도입해보지 않고는 우리 프로젝트에서 어떻게 될 지 모르고 pixiJS는 webGL로 압도적으로 빠르게 렌더링을 해준다고 하니, 일단 도입해 본 후 비교하기로 했다.

profile
개발은 즐거워

0개의 댓글