React에서 d3-cloud 라이브러리 사용하기

TEO·2021년 2월 9일
1

이번 포스팅은 d3 라이브러리를 사용하기 위해 고군분투한 경험을 적겠습니다.

📊D3.js 란?

D3.js란 데이터를 기반으로 문서를 조작하기위한 JavaScript 라이브러리입니다. D3는 HTML, SVG 및 CSS를 사용하여 데이터를 시각화 하기에 아주 좋습니다. 데이터 시각화 프로그램인 R을 생각하면 쉬울텐데요. D3는 Javascript 라이브러리로써 웹에 바로 띄우기 아주 좋다는 장점이 있습니다.


자바스크립트 기반이기 때문에 프레임워크인 리액트에서도 사용할 수 있습니다. 그러나 활용하는 코드 방식이 좀 달라서 애를 먹었는데요.. 일단 react는 npm기반으로 create-react-app을 이용하여 설치했기 때문에 npm모듈을 이용하여 d3를 다운받아야 했습니다.

npm 패키지에 다행히 d3가 있더라고요. 근데 제가 활용하고자 하는 wordcloud기능은 없었습니다.


더 찾아보니 d3-cloud라고 따로 패키지가 존재했습니다.


들어가보면 d3-cloud에 대한 API 사용법은 있는데 자세한 건 안나와있고 특히 react에선 어떻게 사용해야하는지 안적혀있었어서 여러 검색과 시행착오를 통해 완성했습니다.

React에서 d3.js 사용하기

다운받는게 먼저니 두개의 패키지를 다운 받습니다.

$ npm install d3
$ npm install d3-cloud

두개를 설치하면 package.json에 해당 모듈이 추가가 됩니다.

이제 어떻게 react에서 사용할 것인가...
react로 그냥 d3.js 라이브러리를 사용한 예제 코드와 d3-cloud의 깃헙에 존재하는 예제 코드를 보며 짬뽕시켰습니다. ㅎ

// Result/index.js
import React, { useEffect } from 'react';
import * as d3 from 'd3';
import cloud from 'd3-cloud';

const width = 400
const height = 400

function HotelsResult() {
  useEffect(() => {
    const data = [
      "Hello", "world", "normally", "you", "want", "more", "words",
      "than", "this"]

    cloud()
      .size([width, height])
      .words(data.map(function(d) {
        return {text: d, size: 10 + Math.random() * 90, test: "haha"};
      }))
      .padding(5)
      .font("Impact")
      .fontSize(function(d) { return d.size; })
      .on("end", end)
      .start();

    function end(words) {
      d3.select("#word-cloud")
          .append("svg")
          .attr("width", 500)
          .attr("height", 500)
          .style("border", "1px solid black")
        .append("g")
          .attr("transform", "translate(" + 500 / 2 + "," + 500 / 2 + ")")
        .selectAll("text")
          .data(words)
        .enter().append("text")
          .style("font-size", function(d) { return d.size + "px"; })
          .style("font-family", "Impact")
          .attr("text-anchor", "middle")
          .attr("transform", function(d) {
            return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
          })
          .text(function(d) { return d.text; });
    }
  })

  return (
    <div>
      <h1>리뷰 분석 결과</h1>
      <div id="word-cloud"></div>
    </div>
  )
}

export default HotelsResult;

일단 import * as d3 from 'd3'로 d3 모듈을 임포트합니다.
import cloud from 'd3-cloud'로 d3-cloud 모듈도 따로 임포트 해줍니다.

원래는 d3 라이브러리 안에 d3-cloud가 있어서 d3.layout.cloud() API로 워드클라우드 형성이 되어야 하는데 npm에선 따로 다운을 받았기 때문에 둘다 임포트 해주고 cloud() API로 워드클라우드를 형성시킬 수 있습니다.

render로 div를 만들고 id를 설정해줍니다. 이는 나중에 d3.select()로 해당 div를 선택하여 만들 수 있습니다.

data는 아무거나 테스트용으로 설정해두고, cloud()부터는 예제 코드를 복붙했습니다. d3.select('#word-cloud')부분만 id를 선택하게끔 바꾸고 나머지는 그대로 했습니다. d3.js를 정식으로 공부하지 않았기 때문에 attr과 style에 대해 자세하겐 모르겠지만 어쨌든 해당 워드클라우드의 글씨 크기, 폰트 스타일, 기울임 정도 등을 설정한 것 같습니다.

또한 useEffect안에 함수를 넣어 데이터가 변동 될때 감지하여 rerendering하도록 했습니다.

다음과 같이 단어들이 잘 나오는 것을 확인 할 수 있습니다. ㅎㅎ

이제 리뷰단어들을 data부분에 배열의 형태로 잘 넣으면 워드클라우드 형태로 아주 잘 나올 것입니다!

!!여기서 함정!!

정상적인 wordcloud로 제일 많이 나온 단어가 크고, 제일 적게 나온 단어가 작고 그런 식이 아닙니다. D3.js는 그저 R과 같은 시각화 모듈이기 때문에 글자마다 size를 직접 설정해주어야 합니다. 근데 저 코드는 잘 보시면 알겠지만, size를 random으로 설정했습니다.. 그래서 랜덤으로 어떤 단어가 크고 작고 그럽니다... 이 부분은 python을 이용한 딥러닝 부분이므로 프론트엔드와 관련이 없어서 생략하였습니다.

거기다가 python으로 결과를 내어 어떻게 프론트로 전달할지 모르겠는 부분도 있습니다.. ㅜㅜ 기술적인 부분으로 인해 야매로 wordcloud를 만든 것이니 참고하시길 바랍니다.

profile
프론트엔드 개발 공부 시작합니다~ 같이 공부해요!

0개의 댓글