이번 프로젝트 때 날짜 때문에 엄청 고생했다. Sequelize에서의 디폴트 날짜 값은 UTC를 기준으로 하기 때문에 한국 시간보다 9시간이 더 느리다. (주어진 시간에 +9 시간을 해야 한국시간) 이 부분은 Sequelize 객체를 만들 때 값을 조정하면 쉽게 해결이 되었는데, 문제는 이 값을 조회해 다시 사용할 때 였다.
위 사진을 찍을 당시의 시간은 '2021-05-02 오전 1시 5분' 이었다. 그런데 Date 생성자를 이용해 인스턴스를 만들었을 때 나오는 시간은 9시간 전이다. 이는 Sequelize에서 마찬가지로 기본 시간대가 UTC로 설정 되어 있기 때문이다.
이 문제는 Node.js, Sequelize를 이용해 데이터를 가져올 때 동일하게 발생한다. 예를 들어 '2021-02-14 8:00:00' 의 날짜 데이터를 가지고 올 때 Node.js를 거쳐서 -9 시간이 된 '2021-02-13 23:00:00'의 시간이 오는 것.
해결방법은 갖가지다. 가장 대표적인 방법으론 moment.js 라이브러리를 사용하면 되는것인데, 나는 프로잭트 진행 당시 코드를 이미 많이 작성하고나서 알게된 이슈라 moment.js를 적용하기 힘들었다.
그래서 내가 선택한 방법은 간단하게 get / set 메소드를 가져와서 쓰는 것이다.
위 사진을 보면 알 수 있듯이 만들어 준 인스턴스에 setHours 와 getHours 메소드를 통해 시간을 조정해 줄 수 있다.
Github에서 볼 수 있는 잔디판을 이번 프로젝트 때 구현하고자 했다. 먼저 Github의 잔디판을 분석하였는데 7개의 빈칸 한줄을 한 주로 치고 총 52주가 나와있었으며, 오늘 날짜가 속한 주의 빈칸은 오늘 날짜 까지만 나와있었다.
그래서 든 생각은 이차원 배열을 만들어 주 / 날짜를 표현하기로 했다.
[
// 배열 하나당 1주를 나타낸다.
[
{ date: '2020-05-10', feedNum: null },// 일
{ date: '2020-05-11', feedNum: null },// 월
{ date: '2020-05-12', feedNum: null },// 화
{ date: '2020-05-13', feedNum: null },// 수
{ date: '2020-05-14', feedNum: null },// 목
{ date: '2020-05-15', feedNum: null },// 금
{ date: '2020-05-16', feedNum: null } // 토
],
[
{ date: '2020-05-17', feedNum: null },
{ date: '2020-05-18', feedNum: null },
{ date: '2020-05-19', feedNum: null },
{ date: '2020-05-20', feedNum: null },
{ date: '2020-05-21', feedNum: null },
{ date: '2020-05-22', feedNum: null },
{ date: '2020-05-23', feedNum: null }
],
// 생략
[
{ date: '2021-05-02', feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null }
]
]
위와 같은 모습으로 구현했다.
방법은 아주 간단하다.
const arrFunc = () => {
const arr = [];
//? 날짜를 넣기전 52주의 2차원 배열 생성
for (let i = 0; i < 52; i += 1) {
arr.push([]);
for (let j = 0; j < 7; j += 1) {
arr[i].push({date: null, feedNum: null});
}
};
let d = 0;
let week = 51;
//? 시간을 제외한 오늘 날짜
const today = new Date(new Date().setHours(new Date().getHours() + 9)).toISOString().substr(0, 10);
const todayStr = String(today);
//? 날짜 넣기
while (week !== -1) {
//? 요일 구하기
const dayOfDate = new Date(new Date(todayStr).setDate(new Date(todayStr).getDate() - d)).getDay();
//? 0~6은 일~토를 가리키는 것을 이용해 할당
arr[week][dayOfDate].date = new Date(new Date(todayStr).setDate(new Date(todayStr).getDate() - d)).toISOString().substr(0, 10);
if (dayOfDate === 0) {
week -= 1;
}
d += 1;
}
return arr;
}
getDay()를 이용하면 그 날짜의 요일을 가져올 수 있는데 0(일요일) ~ 6(토요일) 이라는 점을 이용해 인덱스로 지정하여 할당하였다. 중간에 복잡하게 Date를 써놓은 것은 최대한 immutable하게 작업하기 위해서이다.
그리고 DB를 조회해 날짜에 따라 피드를 몇개 썼는지 까지 입력해주면 완성이다.
(이번 프로젝트 때 사용된 모습, 몇개 작성했는지 까지 데이터를 보내주었지만 프론트엔드에서 작업하기가 힘들었는지 아니면 까먹으시건지 빼먹으셨다 ㅠㅠㅠ 조금 아쉬운 부분이다.)
또 나를 힘들게 했던 fill() 메소드였다. 기본 개념이 조금 부족했던 탓에 고생을 했다.
const arr = new Array(7).fill({date: null, feedNum: null});
위의 코드를 통해 7개의 요소를 가진 배열을 만들었다. 그리고
arr[0].date = '2021-05-01';
arr[1].date = '2021-05-02';
위와 같이 날짜를 할당해주면 어떻게 될까?
[
{ date: '2021-05-01', feedNum: null },
{ date: '2021-05-02', feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null },
{ date: null, feedNum: null }
]
나는 위와 같은 결과를 기대했다. 그러나
이런 결과가 나왔다!! 그렇다면?
이렇게 같은 주소값을 갖고 있는 것을 알 수 있다.
처음엔 좀 놀랬다. 전혀 상상치도 못했다 ㅠㅠㅠ 많이 알고 있었다고 생각했었던 나 자신에게 실망을 하기도 했다. 다음부턴 조심해서 사용하자...