[Spring/Ajax] Chart.js로 차트 만들기 2
안녕하세요 코북입니다. 지난번 https://cobook.tistory.com/36 에서 Chart.js를 이용해 차트 만들기를 해봤었습니다. 그때는 DB에 넣은 값을 단순하게 보여주는 것이 끝이었다면 오늘은 DB에 있는 값들을 연산하여 차트로 만들어봤습니다. 작업 진행 순서는 다음과 같습니다.
- VO
- Mapper.xml
- Mapper Interface
- Controller
- JavaScript
1. VO
사용할 변수에 맞춰 VO를 작성해줍니다.
package city.turtle.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GraphVO {
private int pos_seq;
private String pos_type;
private String pos_time;
private int pos_count;
private String mb_id;
private String pos_time2;
}
2. Mapper.xml
이 쿼리를 만든 목적은 1주일간 기록된 pos_count 데이터를 더하기 위함입니다. sum() 함수를 사용해 pos_count를 모두 더해 주었습니다. 바뀐 컬럼 명은 as pos_sum으로 재설정해 주었습니다. 사용자의 ID와 자세 유형에 따라 값을 받아오기 때문에 mb_id와 pos_type을 조건으로 하고 pos_time은 현재를 기준으로 7일 씩 가져옵니다. 최초로 가져오는 조건은 다음과 같습니다.
between DATE_SUB(NOW(), INTERVAL 7 DAY) and DATE_SUB(NOW(), INTERVAL 0 DAY)
이제 여기서 7, 0이 14,7로 바뀌면 2주차 데이터를 가져올 수 있습니다. 마찬가지로 21,14로 바뀌면 3주차 데이터를 가져올 수 있게 됩니다. 반복되는 걸 보면 이제 감이 오실겁니다. order by pos_time으로 최근 시간(큰 수)을 나중에 가져오도록 설정했습니다.
<select id="countSum" resultType="int">
select sum(pos_count) as pos_sum
from POSTURE
where mb_id=#{vo.mb_id} and pos_type=#{vo.pos_type}
and pos_time between DATE_SUB(NOW(), INTERVAL #{num1}+7 DAY) and DATE_SUB(NOW(), INTERVAL #{num1} DAY)
order by pos_time;
</select>
3. Mapper Interface
xml과 잘 연결될 수 있도록 변수들에 @Param을 설정해줍니다. 쿼리의 결괏값은 숫자이므로 리턴타입은 int로 하였습니다.
package city.turtle.service;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import city.turtle.vo.GraphVO;
public interface GraphService {
// 거북목, 눈깜빡임 카운트
public List<GraphVO> countTurtle(GraphVO vo) throws Exception;
// 주간 카운트
public int countSum(@Param("vo")GraphVO vo, @Param("num1")int num1) throws Exception;
4. Controller
Controller의 리턴 타입은 mapper를 실행해 받은 int 타입의 값을 리스트로 담을 것이기 때문에 List<Integer>로 설정했습니다. 사용자에게 받은 ID값과 post_type을 mapper에 넘겨줘야하기 때문에 변수는 GraphVO로 하였습니다. 1주 단위로 총 4주간의 데이터가 필요하기 때문에 쿼리에 들어가는 날짜(숫자)가 7씩 더해지는 것이 반복돼야 합니다. for문을 통해 리스트에 값을 반복적으로 넣어주면 될 것 같습니다. i는 0에서 시작해서 7씩 더해집니다. i는 21까지만 증가해야하기 때문에 22보다 작으면 반복문을 멈추도록 하겠습니다. 이제 int 타입 데이터를 담을 수 있는 List 객체를 하나 생성해줍니다. 객체에 add() 메소드를 통해 값을 넣어줬습니다. i가 0부터 시작하기 때문에 처음 불러오는 값이 가장 큰(최근) 값입니다. 저는 add(0, 값)으로 설정하여 이후로 불러오는 값들을 앞 자리에 위치 시켰습니다. 차트를 보여줄 때 왼쪽에 가장 오래된 값(작은 수)이 출력될 수 있도록 하기 위해서 입니다.
package city.turtle.web;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import city.turtle.service.GraphService;
import city.turtle.vo.GraphVO;
@Controller
public class GraphController {
@Autowired
private GraphService mapper;
@RequestMapping("/countSum.do")
public @ResponseBody List<Integer> countSum(GraphVO vo) throws Exception{
List<Integer> sumSum = new ArrayList<>();
for(int i =0; i <22;i+=7) {
sumSum.add(0, mapper.countSum(vo, i));
}
return sumSum;
}
}
5. JavaScript
페이지가 로드될 때 getSumGraph 함수가 시작될 수 있도록 설정해줬습니다. getSumGraph함수가 실행되면 ajax통신이 실행됩니다. countSum.do에 요청을 보내면콜백 함수를 통해 json방식의 데이터를 받습니다. 미리 만들어둔 sumList 리스트에 받아온 데이터 값을 넣어줬습니다. data.data에 받아온 값을 넣어주면 차트가 그려집니다.
$(document).ready(function(){
getGraph();
getSumGraph();
});
// 거북목 주간 합 그래프
function getSumGraph(){
let sumList = [];
$.ajax({
url: "${cpath}/countSum.do",
type : "get",
data : {mb_id:"${signIn.mb_id}", pos_type:"거북목"},
dataType : "json",
success: function(data){
/* console.log(data);
console.log(data[0]);
console.log(data[1]); */
for (let i =0; i<data.length; i++){
sumList.push(data[i]);
}
/* console.log(sumList); */
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: ["4주 전","3주 전","2주 전","1주 전"],
datasets: [
{
label: "월간 거북목",
backgroundColor: [
//색상
'rgba(255, 99, 132, 0.4)',
'rgba(54, 162, 235, 0.4)', // 파란색
/* 'rgba(255, 206, 86, 0.4)', */ // 노란색
'rgba(255, 159, 64, 0.4)', // 주황색
'rgba(153, 102, 255, 0.4)',
'rgba(75, 192, 192, 0.4)' // 초록색
],
borderColor: [
//경계선 색상
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)', // 파란색
/* 'rgba(255, 206, 86, 1)', */ // 노란색
'rgba(255, 159, 64, 1)', // 주황색
'rgba(153, 102, 255, 1)',
'rgba(75, 192, 192, 1)' // 초록색
],
borderWidth: 1, //경계선 굵기
data: sumList
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: '월간 거북목'
}
}
});
},
error:function(){
alert("실패");
}
}) // ajax
} // getSumGraph
구현 화면
구현 화면입니다.
사용 기술
JavaScript, SpringMVC, MySQL
배운 점
@Param을 통해서 Interface와 xml 사이에서 여러개의 변수들을 mapping시킬 수 있었습니다. add() 메소드를 사용하여 ArrayList에 값을 넣을 때 인덱스 설정을 할 수 있었습니다. 반복되는 코드들의 공통점을 찾아 반복문을 만들어 볼 수 있었습니다.
본 글은 아래 링크의 내용을 참고하여 학습한 내용을 나름대로 정리한 글임을 밝힙니다.
ArrayList