[React] 라이브러리를 사용한 데이터 시각화(armChart, D3, Recharts)

2022. 8. 27.공부/React

728x90

 

목적은 규모있는 공공데이터(CSV 또는 json)를 이용한 데이터 시각화였는데, 라이브러리는 3가지 정도를 보았다.

 

1. armChart (https://www.amcharts.com/demos/)

사이트 들어가보면 Demos가 시각화부터 애니메이션까지 매우 잘 되어있다. 그러나 대용량 데이터 처리에는 다른 것이 적합할 것 같아서 사용하지 않았다. 간단한 json으로 만들었으면 이것을 썼을듯..?

 

2. D3 (https://observablehq.com/@d3/gallery)

리서치했을 때 블로그에서 가장 자주 보이던 라이브러리. 인터페이스 세련미 넘친다. 다음 프로젝트에 D3를 이용한 데이터 시각화 넣고 싶을 정도로.. 그런데 이번에는 실제로 3-4시간 동안 D3로 코드 작업을 하다보니 작업하고 있는 프로젝트에는 적합하지 않은 것 같아서 중단하였다. 라이브러리에서 데이터 핸들링이 어렵고 비주얼을 쌓는 기능 위주로 구성되어 있다고 느꼈다. 

function d3() {

var margin = {top: 40, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);

var y = d3.scale.linear()
.range([height, 1]);

var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");

var yAxis = d3.svg.axis()
.scale(y)
.orient("left");


var svg = d3.select("section").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");


 d3.csv("http://localhost:3000/dummy/rentcar2021.csv", function(d) {
  x.domain(d.map(function(a) { return a.VHCLE_NM; }));
  y.domain([0, d3.max(d, function(a) { return a.USE_TIME_CO; })]);


  /* x축 */
  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
      
  /* y축 */
  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append("text")
      .attr("transform", "rotate(-90)")
      .style("text-anchor", "end")
      .text("이용 시간");

  svg.select("body").selectAll("div")
      .data(d)
      .enter().append("div")
      .attr("class", "bar")
      .attr("x", function(a) { return x(a.VHCLE_NM); })
      .attr("width", x.rangeBand())
      .attr("y", function(a) { return y(a.USE_TIME_CO); })
      .attr("height", function(a) { return height - y(a.USE_TIME_CO); })
});

function type(d) {
    d.USE_TIME_CO = +d.USE_TIME_CO;
    return d;
  }
};

export default d3;

 

3. Recharts (https://recharts.org/en-US)

결국 이 라이브러리를 사용했는데, 리액트의 상태값으로 데이터 시각화가 가능해서 너무 좋았다. 사이트 들어가보면 API 문서도 매우 자세하게 되어있고, UI도 심플하고 촌스럽지 않다. hover 시 나오는 툴팁도 D3에서는 D3-tip이라는 것을 따로 설치해야 구현할 수 있었는데 Recharts에서는 지원하고있는 툴팁 컨포넌트로 손쉽게 구현이 가능하다. 

 

import { useState } from "react";
import { BarChart, Cell, Bar, XAxis, YAxis,  Tooltip,  CartesianGrid, ResponsiveContainer, Legend } from "recharts";

const data = [
    {name:"코나 일렉트릭 EV",USE_TIME_CO:"1996"}
    ,
    {name:"K5 2세대",USE_TIME_CO:"1752"}
    ,
    {name:"쏘나타 DN8",USE_TIME_CO:"1568"}
    ,

.... 생략

export default function App(dataImg) {
    const [ activeIndex, setState ] = useState(0);
    const [ imgUrl, setUrl ] = useState( "/assets/sub/rent/kona-electric.jpg");

    const handleClick = (data, index) => {
		setState(index);
        setUrl(dataImg.dataImg[index].img);
        console.log(imgUrl);
	}
    return (
        <>
        <li className="like-list-item" id="rent-card">
            <div className="tag"><strong>{activeIndex + 1}</strong>위</div>
        		<div className="like-list-item-contents">
        			<div className="like-card-left-sec">
                		<h1 claassName="info-tit" id="info-tit">
                    	{data[activeIndex].name}
                    	</h1>
                		<p>
                		제주도를 찾는 여행객과
                		<strong>{data[activeIndex].USE_TIME_CO}</strong>
                		<span>시간 함께하였습니다.</span>
                		</p>
        				</div>
        				<div className="like-card-right-sec">
            				<div className="like-list-item-ic-cart" id="rent-img">
            				<img src={`${process.env.PUBLIC_URL}${imgUrl}`} alt="차량이미지" style={{width:'100px', height:'100px', objectFit:'cover'}}/>
            			</div>
        			</div>
    			</div>
    		</li>
    <ResponsiveContainer width={1800} height={350}>
    		<BarChart width={1800} 
            		  height={400} 
                      data={data.slice(0,13)} 
                      barSize={40} 
                      margin={{top: 180,left:200}}>
        		<XAxis padding={{left: 60}} 
                       tickMargin="10" 
                	   tickSize="10" 
                       interval="preserveStart" 
                       width={1200} 
                       scale="point" 
                       type="category" 
                       tick={{fontSize: 13, padding: "6px"}} 
                       dataKey="name"/>
        		<YAxis hide={true} 
                	   padding={{bottom: 10}} 
                	   domain={[0, '2000']} 
                       type="number" 
                       tickFormatter={(value) => `${value}시간`} 
                       tick={{fontSize: "13px"}} 
                       dataKey="USE_TIME_CO"/>
        		<CartesianGrid strokeDasharray="3 3" vertical={false}/>
        		<Bar dataKey="USE_TIME_CO" 
                	 onClick={handleClick} 
                	 label={{fontSize: 13, position: "top"}}>
             		{data.slice(0,13).map((entry, index) => 
                    	  (<Cell cursor="pointer" 
                    	   fill={index === activeIndex ? '#82ca9d' : '#4e6a75'} 
                           key={`cell-${index}`} />))}
       	 		</Bar>
        		<Tooltip />
    		</BarChart>
    </ResponsiveContainer>
    </>
  );
}

'공부 > React' 카테고리의 다른 글

[React] CORS 해결하기  (0) 2022.09.03
[React] React Router DOM  (0) 2022.08.27
[React] 가격 컴포넌트(가격 표시 UI) 만들기  (0) 2022.08.25
[React] 댓글 기능 구현  (0) 2022.08.23
[React] 별점 컴포넌트 만들기  (0) 2022.08.21