본문 바로가기
Web과 프로그래밍 언어/JavaScript

[VUE.JS] 조회한 데이터로 차트 그리기 (Echarts, Apexcharts 사용하기)

by cosmicgy 2025. 1. 16.

vue.js 에서 조회 결과로 차트를 그리려고 함. 처음에는 echartbar 로 시도했는데, 반응형이 아니어서 아쉽기도하고 디자인이 조금 더 세련되었으면 하는 요구사항이 있어서 apexcharts 로 2안을 마련했음. 

완성된 차트를 먼저 확인해보자.

APEXCHARTS 사용

 

ECHARTS 사용

ECharts와 ApexCharts의 차이점

라이선스 무료 (Apache 2.0) 무료 + 일부 유료 기능
사용 난이도 중간 (설정 복잡) 쉬움 (직관적인 설정)
차트 유형 매우 다양 적당히 다양
데이터 처리 능력 대규모 데이터 처리에 적합 소규모/중간 규모 데이터에 적합
프레임워크 지원 독립적 사용 및 플러그인 형태로 통합 가능 Vue, React, Angular와 강력한 통합
디자인 강력한 커스터마이징, 복잡한 그래프 가능 깔끔하고 세련된 기본 디자인 제공
반응형 기본적으로 반응형 아님 모든 차트가 반응형

위의 차이점은 챗지피티가 정리해주었음. 두개 비교해보니 사용자가 느끼는 가장 큰 차이점은 반응형이라는점? 정도일 것으로 생각됨.

이제 코드를 살펴보자 .

 

1. ECHARTS

1) template code

          <EchartBar ref="EchartBar" style="height: 100%"></EchartBar>
 

2) script code

function getData(data, unit) {
  // 동적으로 source 생성
  const source = data.map(item => ({
    Product: item.gbn,
    수익: valueGetterAmt(item.incomeAmt, unit),
    원가: valueGetterAmt(item.tcostAmt, unit),
    손익: valueGetterAmt(item.diffAmt, unit),
  }));
  return {
    /* 막대색상 */
    color: ['rgb(67,101,178)', 'rgb(78,157,78)', 'rgb(192,37,52)'],
    /* 구분 */
    legend: {
      orient: 'vertical',
      left: 'left',
      data: ['수익', '원가', '손익', '기타'],
    },
    textStyle: {
      fontFamily: '차트명',
      fontWeight: 700,
    },
    /* 데이터 */
    dataset: {
      dimensions: ['Product', '수익', '원가', '손익'],
      source, // 동적으로 생성된 source 배열
    },
    xAxis: { type: 'category' },
    yAxis: {},
    series: [
      {
        type: 'bar',
        /* 값표시 */
        label: {
          show: true,
          position: 'top',
        },
      },
      {
        type: 'bar',
        label: {
          show: true,
          position: 'top',
        },
      },
      {
        type: 'bar',
        label: {
          show: true,
          position: 'top',
        },
      },
    ],
  };
}
 
import EchartBar from '@/components/common/EchartBar.vue'; // 컴포넌트 임포트
 
 components: {
    EchartBar,
  },
// 컴포넌트 선언
 
 methods: {
 // 조회 한 결과를 그래프로 그릴 것이기 때문에 조회 버튼 함수에 차트 refresh 
getGrid: async function () {
      let param = {};
      param['abc'] = this.search.abc.replace(/-/gi, '');
      param['def'] = this.search.def.replace(/-/gi, '');
      const rs = await abc _API. getGrid (param);
      this.data = rs.data.list;
      this.data.filter(el => {
        el.diffAmt = el.incomeAmt - el.tcostAmt;
      });
      this.gridApi.setRowData(this.data);
      if (this.data.length > 0) {
        this.$refs.EchartBar.refresh(getData(this.data, this.search.unit)); // 이부분이 차트 그리기, getData 함수는 최상단에서 정의함
      }
    },
},

 

2. APEXCHARTS

1) template code

          <apexchart ref="ApexChart" :options="chartOptions" :series="chartOptions.series"> </apexchart>
 

2) script code

import VueApexCharts from 'vue3-apexcharts';
 
function getData(data, unit) {
  // 동적으로 xAxis 카테고리 및 series 데이터 생성
  const categories = data.map(item => item.gbn); // xAxis에 들어갈 gbn 값
  const series = [
    {
      name: '수익',
      data: data.map(item => valueGetterAmt(item.incomeAmt, unit)),
    },
    {
      name: '원가',
      data: data.map(item => valueGetterAmt(item.tcostAmt, unit)),
    },
    {
      name: '손익',
      data: data.map(item => valueGetterAmt(item.diffAmt, unit)),
    },
  ];

  // ApexCharts 차트 설정 반환
  return {
    chart: {
      type: 'bar', // 막대 차트
      height: 330,
      toolbar: {
        show: true, // 다운로드 버튼 표시 여부
      },
    },
    colors: ['rgb(67,101,178)', 'rgb(78,157,78)', 'rgb(192,37,52)'], // 막대 색상
    plotOptions: {
      bar: {
        horizontal: false, // 수직 막대 차트
        borderRadius: 5, // 막대 모서리 둥글게
      },
    },
    dataLabels: {
      enabled: true, // 값 표시
      style: {
        fontSize: '12px',
        fontWeight: 'bold',
      },
    },
    legend: {
      position: 'right', // 범례 위치
      fontSize: '14px',
    },
    xaxis: {
      categories, // x축 카테고리
    },
    yaxis: {
      tickAmount: 5,
      labels: {
        formatter: function (val) {
          return val.toFixed(0); // 소수점 제거
        },
      },
    },
    series, // 동적으로 생성된 series 데이터
  };
}
 
components: {
    apexchart: VueApexCharts,
  },
//컴포넌트 선언
 
data: () => ({
//data에 초기값 선언
    chartOptions: {
      series: [], 
      chart: {
        type: 'bar',
        height: 330,
      },
      xaxis: {
        categories: [], 
      },
      colors: ['#4365B2', '#4E9D4E', '#C02534'],
    },
  }),
 
methods: {
getGrid: async function () {
      let param = {};
      param['abc'] = this.search.abc.replace(/-/gi, '');
      param['def'] = this.search.def.replace(/-/gi, '');
      const rs = await abc _API. getGrid (param);
      this.data = rs.data.list;
      this.data.filter(el => {
        el.diffAmt = el.incomeAmt - el.tcostAmt;
      });
      this.gridApi.setRowData(this.data);
 // 이 부분이 echarts 와는 변경된 code
 if (this.data.length > 0) {
        const unit = this.search.unit;
        this.chartOptions = getData(this.data, unit);
      }
    },
},

한가지 걸리는 건 데이터 처리량이 소, 중 규모라는 것인데 여기저기 확인해보니 10,000개 이상의 데이터 포인트를 가진 복잡한 차트의 경우 성능 저하가 있을 수 있다고 함. 거기에 애니메이션이나 데이터 레이블 등을 사용하게 되면 더 영향을 받고.. 한 차트에 10개 시리즈를 가지고 각 시리즈에 100~200 개의 데이터 포인트 정도는 안정적으로 사용 가능!

사실 디자인 때문에 바꾼 것이었는데, 크게 뭔가 드라마틱한 건 없는 것으로.. 

결론 내가 만일 상호작용이 많은 고성능 시각화 차트가 필요하다면 echarts 나 uPlot 같은 라이브러리를 사용하는게 좋겠다.