본문 바로가기
BOOKS/수월한 자바스크립트

chart.js를 사용한 데이터 시각화하기 #3/3

by IT여행자 2024. 12. 27.
728x90


https://jobtc.tistory.com/146 (기본 차트)
https://jobtc.tistory.com/147 (실시간 차트)
https://jobtc.tistory.com/148 (서버 데이터 차트)

 

안녕하세요 IT여행자입니다.

 

chart.js 라이브러리를 사용한 데이터 시각화의 마지막 단계인 서버로부터 실시간으로 데이터를 수신받아 그래프를 그려보는 과정입니다. 본 지면에서는 서버를 spring boot의 Restful API를 사용하여 데이터를 수신받았지만 실제로는 어떤 서버를 사용하던 상관이 없습니다. 단 수신된 데이터가 JSON구조이어야 합니다.

또한 본 지면에서는 서버와 관련된 설정 부분이나 서버 전체 코드 부분은 생략합니다. 이점 양해해 주시기 바랍니다.

 

서버와의 데이터 송수신은 서버가 능동적으로 클라이언트에게 전송하느냐, 아니면 클라이언트의 요청이 있는 경우에만 데이터를 전송하느냐의 차이는 서비스의 종류에 따라 달라질 수 있는 상황입니다. 본 지면에서는 클라이언트의 요청이 있는 경우에만 서버가 데이터를 송신하는 것으로 작성하였습니다.

 

1. 서버단

클라이언트의 자바스크립트가 fetch("/chart_data")를 사용하여 서버에게 데이터를 요청하면 실행되는 spring boot의 컨트롤러 일부분입니다. spring boot 뿐만 아니라 Node.js 혹은 파이썬 등등 어떤 언어를 사용하던 상관없습니다. 클라이언트에게 전달되는 데이터 유형이 JSON 구조라만 큰 문제가 없을 것입니다.

@RestController
public class ChartController {
    ...

    @GetMapping("/chart_data")
    public Map<String, Object> chartResp() {
        Map<String, Object> map = new HashMap<>();
        int[] respData = new int[7];
        for (int i = 0; i < 7; i++) {
            respData[i] = (int) (Math.random() * 90) + 10;
        }
        map.put("msg", respData);
        return map;
    }
}

 

위의 코드는 "msg" 키에 7개의 정수를 렌덤 하게 발생시켜 발생된 데이터를 배열에 담아 클라이언트에게 전달됩니다.

 

2. 클라이언트단

서버에게 데이터를 요청하기 위해 버튼을 하나 추가한 후 read() 함수를 호출합니다.

read() 함수는

 

서버에게 데이터를 요청하여 데이터가 수신될 때까지 시간 지연이 발생되며, 그래프를 그릴 때도 그래프가 모두 렌더링 될 때까지 시간 지연이 발생합니다. 이를 위해 read() 함수에 async를 붙여 동지화 작업을 하도록 합니다.

var read = async ()=>{ ... }

 

자바스크립트의 fetch() 함수를 사용하여 서버에게 데이터를 요청할 수 있습니다. 

var response = await fetch("/chart_data")     
var data = await response.json();

 

await fetch("/chart_data")는 서버단에 정의된 @GetMapping("/chart_data")으로 지정된 메서드를 호출하여 데이터가 수신될 때까지 기다리라는 의미입니다. 그다음줄의 await response.json()은 수신된 데이터를 JSON 객체로 바꾸어 변수 data에 저장하는 코드입니다.

<!DOCTYPE html>
<html lang="ko">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="http://cdn.jsdelivr.net/npm/chart.js"></script>
        <title>chart step 3</title>
        <style>
            #chart{
                width: 600px;
                height:400px;
                display: flex;
                flex-direction: column;
                justify-content: center;
            }
        </style>
    </head>

<body>
    <h3 class="info">
        실시간 서버 데이터 연동하기
    </h3>    
    <div id="chart">
        <canvas id="myChart"></canvas>
        <button onclick="read()">READ</button>
    </div>
<script>
        var ctx = document.querySelector('#myChart').getContext('2d')
        var data = [10, 50, 30, 70, 90, 40, 55]
        var x_labels = ['1월','2월','3월','4월','5월','6월']
var colors =['#f55a', '#5f5a', '#ff5a', '#f5fa', '#345a', '#123a', '#986a']

        var myChart = new Chart(ctx, {
            data: {
                labels: x_labels, /*x축 라벨 */
                datasets: [
                    {
                        label: '판매', 
                        data: data,
                        type : 'line',
                        borderWidth: 2,
                        borderColor: '#00f',
                        pointBackgroundColor:colors,
                        pointRadius: 4,
                        tension : .35
                    },
                    {
                        label: '순이익',
                        data: data,
                        type: 'bar',
                        borderWidth: 0,
                        backgroundColor: colors,
                    },
                    
                ]
            },
            options: {
                responsive : true, /* 차크 크기 자동 조정 */
                plugins:{
                 title:{
                 display : true,
                 text:'전체 판매현황',
                 }
                },
                scale:{
                    y:{
                        min : 0,
                        max : 110,
                        ticks : {
                            stepSize : 20,
                        }
                    }
                }
            }
        })
        
        
        var read = async ()=>{
            try{
                var cnt = 0;
                while(cnt<10){
                    var response = await fetch("/chart_data")     
                    var data = await response.json();
                    myChart.data.datasets[0].data = data.msg;      
                    myChart.data.datasets[1].data = data.msg;      
                    myChart.update()
                    cnt++;
                    await new Promise(resolve=> setTimeout(resolve, 1000))
                }
            }catch(error){
                console.log('error:',error)
            }
        }

    </script>

</body>

</html>

 


그래프의 모양은 그때 그때 달라지며, READ버튼이 클릭되면 10회까지 계속해서 변경되는 것을 볼 수 있습니다.

 

이것으로 3회에 걸쳐 chart.js 라이브러리를 사용한 데이터 시각화 작업을 마치도록 하겠습니다. 물론 본 지면을 통해 chart.js 라이브러리에 대한 모든 내용을 다루지는 못하였습니다. 아니, 거의 다루지 못했다고 해도 과언이 아닙니다. 기타 자세한 내용은 http://chartjs.org를 방문하여 살펴보시길 바랍니다.