페이지가 필요하다..
Django Template을 이용해 데이터를 표출해줘야 하는 상황에 직면했다. 즉 Front 페이지가 필요한 상황인 것이다. 간단히 데이터 몇 개만 그래프로 그리면 되긴 하는데 Front에 관련된 것이라고는 Html, CSS, JavaScript 그리고 예전에 조금 깔짝 여본 React가 전부인데 이를 어떻게 해결하나 싶은 순간에서 대학 시절에 조금 만져봤던 Chart.js를 다시 꺼내 들었다
JavaScript의 Fetch API를 동기적으로 써먹기
JavaScript에 Http Request에 사용할 수 있는 Fetch API가 존재한다고 한다. 대학 시절에는 XMLHttpRequest를 썼기 때문에 비슷한 부류겠지 하고 인터넷을 뒤적거린 결과 다음과 같은 예제 코드를 발견했다.
function get_data(){
fetch('http://example.com/movies.json')
.then((response) => response.json())
.then((data) => console.log(data));
}
그런데 문제는 위 코드는 단순히 Http Request를 보내기만 할 뿐 다음과 같은 부분에서 사용해먹지 못했다.
- async 방식으로 call을 하기 때문에 위 함수와 연관된 태그(버튼)를 여러 번 누르면 Repsonse를 제대로 처리해주지 못해, 위 함수를 통해 얻은 결과를 DOM에 표출한다고 버벅이는 등 정상적으로 동작하지 못하는 현상이 존재함
- JavaScript를 잘 알지 못하는 상황에서 써야 하기 때문에 논리 구조상 두 번째 then 구문 안에서 DOM에 html을 밀어 넣어주는 코드를 작성한다든지 코드 구성이 복잡해짐
그래서 async로 동작하는 fetch를 sync 방식으로 써먹기 위해 다음과 같은 코드를 적용해야 했다.
async function get_data() {
const url = ''
const in_query = ''
const response = await fetch(url + in_query);
const data = await response.json()
return data;
}
위 함수를 별도의 위치에서 사용한다고 하면 아래 형태로 써먹으면 된다.
const response = await get_data();
javascript에 관해 잘 모르기 때문에 async 방식을 sync 방식으로 사용한다고 표현하는 것이 맞는 것인지는 모르겠으나 실제로 이렇게 코드를 쓰게 된 배경은 이 포스팅을 계속 읽다 보면 나온다.
Chart.js 에서 라인 그래프가 이동하는 현상
Chart.js로 그래프를 표현하기 전에 순서를 설명할 필요가 있다.
- 특정 페이지에서 카드 리스트가 표출된다
- 각각의 카드에는 view라는 버튼이 존재한다.
- 버튼 클릭 시 모달 창이 나타나며 다음과 같은 과정이 일어난다.
- 위에 작성한 Fetch 함수로 데이터를 Django API에서 데이터를 가져온다
- 가져온 데이터를 chart.js로 만들어진 그래프를 그려주는 함수에 넘겨 그래프 그린다.
- 모달 창에 그래프를 그린다.
위와 같이 간단한 구조이다.잠깐 언급한 이 과정이 FetchAPI를 사용하는 방법과도 연관되어있다. 버튼만 계속 클릭하게 되면 FetchAPI가 async적이기 때문에 요청과 응답처리 시간의 차이로 인해 데이터를 불러오지 못하게 되니 그래프를 그릴 수 없는 현상이 존재한다.
하지만 async에서 sync 방식으로 변경했기 때문에 데이터(그래프를 그리는 x축, y축)가 잘못 생성되는 현상은 존재하지 않았다. 다만 특이한 점은 y축을 나타내는 데이터의 범위가 굉장히 유동적이다라는 점이다. y축에 들어가는 데이터의 예시는 다음과 같다.
[1, 2, 3, 4, ..., 10]
[10,20,30,40, ..., 100]
[100, 200, 300, 400, ..., 1000]
즉 한 자릿수가 되기도 하고 두 자리수가 되기도 하며 세 자리수가 되기도 한다(참고로 x축은 시간을 표현한다).
이 사실로 보아 y축에 표현되는 데이터의 Step을 y축 데이터를 보고 자동으로 조정해주는 auto scale을 적용해줘야 한다는 뜻인데 이는 Chart.js의 document를 열심히 뒤적거린 결과 ticks 속성에 다음과 같은 옵션을 넣어줌으로써 해결했다.
...
yAxes: [{
ticks: {
scaleOverride: true,
scaleStartValue: 0,
scaleSteps: 500,
scaleStepWidth: 0.5,
maxTicksLimit: 20,
autoSkip: false
},
...
사실 조금 더 큰 문제는 어째선지 Chart.js로 표현된 Line 그래프의 특정 tick에 커서를 올리면 Line Chart의 그래프가 다시 그려지는 현상이 발생한다는 점이다.
데이터를 Fetch 하는 과정에서 일어나는 문제가 아니기 때문에 당연히 Chart.js 쪽을 부릅뜨고 볼 수밖에 없었는데 검색 도중 chart.js의. update()와. destory()를 사용하라는 정보가 눈에 띄었다. 이것으로 다음과 같이 적용했다.
const chart = get_line_chart(times, closes);
chart.update()
var myModalEl = document.getElementById('exampleModal')
myModalEl.addEventListener('hidden.bs.modal', function (event) {
chart.destroy();
})
. addEventListener는 모달 창이 닫히는 시점에 destory()를 해줘야 하는데 이를 가능하게 하는 건 알고 있는 범위 내에선 선 EventListener이 다였기 때문이다.
결론적으로는 그래프가 다시 그려지는 현상이 사라졌다.