본문 바로가기
Vue.js

[Vue.js] 14. use Vue chart plugin

by 청양호박이 2021. 3. 8.

application을 만들다보면, 다양한 수치의 데이터에 대해서 직관적으로 chart로 보여줘야 할 때가 많습니다. 예를들어 AT Project에서 진행하는 MACD / Signal 에 대한 지표에 대해서도 Golden Cross나 Dead Cross를 시각적으로 보는것이 훨씬 이해가 빠를 것 입니다.

 

이번에는 Vue에서 이러한 Chart를 구현할 수 있도록 해주는 Plugin에 대해서 알아보겠습니다. 뭔가 새로운 것을 내 프로젝트에 적용하려고 할때는 가끔 막막할 때가 많습니다. 하지만 이럴때는 역시 npm repository에서 검색을 해보는게 가장 좋겠죠??

 

모든 검색에서는 중요한 것이 검색어 인데... 한번 아래의 키워드로 검색을 해보겠습니다. 

 

vue charts

 

뭐 있나요. 단도 직입적으로 내가 하고 싶은것을 입력합니다...ㅎㅎㅎ 그 결과 아래처럼 다양한 plugin이 검색됩니다.

여러가지 plugin을 둘러보았는데... 가장위에 검색된 vue-chartjs의 경우가 주간다운로드도 많고 엄청나게 많은 개발자들에게 사랑을 받고있음을 알 수 있었습니다.

 

해당 plugin은 공식 웹페이지가 존재하며, 자세하게 적용하는 방식을 설명해주고 있어서 처음사용하는 입장에서도 거부감없이 다가갈 수 있을 것 같습니다.

 

vue-chartjs.org/

 

📈 vue-chartjs

 

vue-chartjs.org

그럼 한번 적용해 볼까요??

 

 

1. vue-chartjs install


우선 vue-chartjs를 vue-project 폴더 내 package.json에서 dependencies안에 추가를 해 줍니다. 

  "dependencies": {
    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "axios": "^0.21.1",
    "vuetify": "2.4.3",
    "vue-chartjs": "3.5.1"
  },

패키지의 이름과 버전은 위에 npm repository의 vue-chartjs 관련 페이지에서 확인이 가능합니다. 

 

그 다음에는 vue-project의 root폴더에서 console을 열고 npm install을 수행합니다.

C:\VueProjects\atproject\at-vue>npm install
npm WARN ajv-keywords@2.1.1 requires a peer of ajv@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN vue-chartjs@3.5.1 requires a peer of chart.js@>= 2.5 but none is installed. You must install peer dependencies yourself.

어라 뭔가 설치가 잘 안된거 같은데요?? 내용을 확인해보면... 일단 chart.js가 2.5버전 이상이 필요하다고 하네요?? 확인을 위해서 vue-chartjs의 공식 페이지에 가서 Getting Started를 확인해 보겠습니다. 

 

Chart.js는 peerDependency이기 때문에 chart.js를 프로젝트내 dependencies에 추가해야합니다. 이렇게하면 Chart.js에 대해서 완전히 제어 할 수 있다고 합니다.

 

그럼 이번에는 npm repository에서 chart.js를 검색해 보겠습니다.

아... 이분은 진심으로 대단한 분이네요... 현재 버전은 2.9.4 이고 패키지 명은 chart.js로 확인 되었습니다. 그럼 package.json에 추가해 보겠습니다. 

  "dependencies": {
    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "axios": "^0.21.1",
    "vuetify": "2.4.3",
    "chart.js": "2.9.4",
    "vue-chartjs": "3.5.1"
  },

이어서 console화면에서 npm install 설치를 하면 이상없이 설치가 완료된 것을 확인할 수 있습니다. 그럼 이제 사용을 해 볼까요??

 

 

2. Use vue-chartjs Basic


뭔가 와 닿지는 않지만... vue-chartjs를 이용해서 SPC(single file components)를 구현할 수 있다고 설명되어 있지만, 제약조건이 있습니다. 일단 vue-charjs로 그래프를 코드가 <template> </ template>안에 포함되어 있으면 안된다고 합니다. 왜냐하면, 자체적으로 template은 mixin에 포함되어 있으며... 코드에 template 태그를 남겨두면 기본 차트에서 가져온 태그를 덮어 쓰고 빈 화면이 나타나게 된다고 합니다.

 

일단 기존과 다르게 코딩을 해야한다는 말인 것 같습니다. 역시 백문이 불여일견이라고... 구현을 해보겠습니다.

 

[ChartTestBasic.vue]

<script>
import { Line } from 'vue-chartjs'

export default {
  extends: Line,
  data() {
    return {
      chartdata: {
        labels: ['January', 'February'],
        datasets: [
          {
            label: 'Data One',
            backgroundColor: '#9575CD',
            data: [40, 20]
          },{
            label: 'Data Two',
            backgroundColor: '#64B5F6',
            data: [30, 40]
          }
        ],
      },
    };
  },
  mounted () {
    this.renderChart(this.chartdata, this.options)
  }
}
</script>

<style>

</style>

코드는 어마무시하게 간단합니다. 하나하나 살펴보겠습니다. 

 

  • 우선 vue-chartjs plugin을 해당 vue에 import를 해줍니다. 이때, 그릴 chart의 type을 지정하여 import합니다.
  • chart를 그리기 위한 data를 세팅해 줍니다. 해당 data의 구성은 labels와 datasets 입니다. 
  • labels - 가로축에 표시할 데이터의 기준입니다.
  • datasets > label - 범례에 표시할 datasets의 이름입니다. (다수가 될 경우 각 dataset의 이름입니다.)
  • datasets > bgcolor - 적용할 chart의 색상을 지정합니다.
  • datasets > data - 실제 chart의 표시할 data 정보 값 입니다.
  • 이렇게 chartdata까지 지정되면, mounted( ) lifecycle에다가 renderChart( ) 메서드를 호출합니다. 이때, chartdata와 options를 입력 parameter로 넣어줍니다.

 

결과 화면은 위와 같습니다. 

 

 



 

3. Use vue-chartjs Advanced


이번에는 단일 vue 페이지로 chart를 그리는 것이 아닌, 다양한 정보를 제공하는 페이지 내에서 chart를 그 중 한개로 표현하는 방법에 대해서 알아보겠습니다. 다시말해서, 어떤페이지에서 구성을 왼쪽에는 통계를 보여줄 대상의 list를 보여주고 오른쪽에서는 그 대상의 chart를 보여주는 그런 구성을 할때를 예로 들 수 있겠습니다.

 

이렇게 구성을 하기 위해서는 몇가지 조건이 있습니다. 

 

  • chart를 나타낼 vue를 mini component화 해서 호출이 가능해야함
  • 해당 chart vue는 실시간으로 요청오는 chart data에 대해서 역시나 실시간으로 변경되어 표시되어야 함

 

다음과 같습니다. 우선 mini component화 하여 구성를 해보겠습니다. vue-chartjs basic에서 구성했던 코드에서 약간의 변경이 필요합니다. 

 

[ChartTest.vue - minicomponent]

<script>
import { Line } from 'vue-chartjs';

export default{
  extends: Line,
  props: ['chartData', 'options'],
  mounted() {
    this.renderChart(this.chartData, this.options);
  },
};
</script>

<style>

</style>

차트를 그려주는 vue에서는 크게 변경되는 부분은 없습니다. 이제 chartData는 main component에서 props로 전달 받을 것이기 때문에 props를 추가하고 값에 변수명만 정의해 주는 부분만 반영하면 됩니다.  

 

그렇다면, 이제 main component에 대해서 알아보겠습니다. 

 

[ChartTestMain.vue]

<template>
  <div class="small">
    <chart-test :chart-data="dataCollection"></chart-test>
    <button @click="fillData()">Randomize</button>
  </div>
</template>

<script>
import ChartTest from '@/components/ChartTest';

export default {
  components: {
    ChartTest,
  },
  data() {
    return {
      dataCollection: null,
    };
  },
  created() {
    this.fillData();
  },
  methods: {
    fillData() {
      this.dataCollection = {
        labels: [this.getRandomInt(), this.getRandomInt()],
        datasets: [
          {
            label: 'Main One',
            backgroundColor: '#f87979',
            data: [this.getRandomInt(), this.getRandomInt()],
          }, {
            label: 'Main One',
            backgroundColor: '#f87979',
            data: [this.getRandomInt(), this.getRandomInt()],
          },
        ],
      };
      console.log('ChartTestMain', this.dataCollection);
    },
    getRandomInt() {
      return Math.floor(Math.random() * (50 - 4)) + 5;
    },
  },
};
</script>

<style>
  .small {
    max-width: 600px;
    margin:  150px auto;
  }
</style>

 

  • 우선 ChartTest.vue를 import해 줍니다. 그리고 components에 import한 vue를 사용하기 위해 선언해줍니다.
  • 그리고 data( )에는 인자로 넘겨줄 chartData 형태의 값을 담기위한 변수를 선언합니다. 
  • created( ) lifecycle에서는 fillData( ) 함수를 호출해서 chartData 형태의 값을 생성하여 dataCollection에 저장합니다.
  • <template/> 에서는 import한 ChartTest.vue를 호출하면서 props인 :chart-data에 dataCollection을 넣어서 호출합니다. 
  • ChartTest.vue에 this.renderChart( )를 통해서 그려진 chart는 ChartTestMain.vue에서 보여지게 됩니다. 

 

여기서 주의할 점은 분명히 ChartTestMain.vue에서는 chartData를 생성할때 random( )으로 하기 때문에, 매번 다르게 chart가 그려져야 합니다. 하지만 Randomize button을 아무리 클릭해서 chartData를 바꿔도 ChartTest.vue를 통해서 chart가 변경되지 않습니다.

 

우측의 개발자 도구를 통해서 console.log를 찍어봐도... 정상적으로 ChartTestMain.vue에서는 chartData를 바꾸어서 생성하고 있습니다. 왜 chart는 자동으로 update가 되지 않을까요?? 

 

 

4. Update Chart


vue-chartjs에서 공식적으로 제공하는 guide를 확인해 보도록 하겠습니다.

 

우선 Chart.js는 기본적으로 datasets에 변화가 생겨도 실시간 update를 지원하지 않습니다. 하지만 vue-chartjs는 근본이 되는 Chart.js와 달리 2가지 기능을 제공합니다.

 

reactiveProp, reactiveData

 

이 2가지 기능중에 개발자는 reactiveProp를 주로 쓰게 될 것이라고 하니... 그 기능에 대해서 알아보겠습니다.

 

reactiveProp는 자동으로 chartData라는 props를 mixin에 자동 생성하고, vue안에 watch( )에 생성된 props를 등록해 줍니다. 만약에 chartData에 변경이 생기면 update( )나 renderChart( )를 호출하게 되는 것 입니다. 따라서 위의 경우처럼 ChartTestMain.vue를 통해서 계속 변경을 해주면 계속 변경된 chartData를 기준으로 chart를 그려주게 되는 것 입니다.

 

반면에 reactiveData는 chartData라는 변수를 생성하고, watch( )에 생성된 변수를 등록해 줍니다. props가 아닌 변수로 생성하기 때문에 해당 x.vue 내에서 모든게 처리되는 간단한 로직에서정도 사용이 가능해 보입니다. 그래서, 개발자가 reactiveProp를 주로 쓸거라고 한 것 같습니다.

 

그럼 구현을 해 볼까요??

 

[ChartTest.vue - reactiveProp]

<script>
import { Line, mixins } from 'vue-chartjs';

export default{
  extends: Line,
  mixins: [mixins.reactiveProp],
  props: ['options'],
  mounted() {
    console.log('ChartTest mount!!');
    console.log('ChartTest', this.chartData);
    console.log('ChartTest', this.options);
    this.renderChart(this.chartData, this.options);
  },
};
</script>

<style>

</style>

 

  • 변경된 사항은... mixins에 reactiveProp를 추가하여 정의해주는 부분 입니다.
  • 아참!! 그리고 props에서 별도로 chartData를 정의하지 않습니다. 왜냐하면, reactiveProp가 자동으로 생성이 되서 등록을 시켜주기 때문입니다.

 

이미지로는 표현이 어렵지만... Randomize버튼을 누를때 마다 chart가 변경이 됨을 확인할 수 있습니다. 또한, ChartTestMain.vue에서는 계속 데이터가 변경되서 생성이 되지만... 실제로 ChartTest.vue로는 mounted( ) lifecycle이 재호출 되지 않고 chart가 변경됨을 확인 할 수 있습니다. 왜냐하면, ChartTest.vue의 mounted( )에 변경된 데이터의 호출을 확인하기 위해 console.log를 찍었지만 변화가 없기 때문입니다. 

 

이렇게 Chart가 구현되었습니다. 향후 원하는 입맛에 맞게 구현하기 위해서는 custom이 필요할 수 있습니다. 

 

- Ayotera Lab -

댓글