이전 포스팅을 올리면서 해결 될줄 알았던 TimeZone 의 문제는 해결되지 않았다..
-> 위에 보면 다이어리를 등록한후
등록된 해당 다이어리 를 클릭하면 등록했던 다이어리 내용이 보여진다.
클릭하면 제목과 내용은 잘 보여지는데 등록 한 date 와 보여지는 date 의 날짜가 다른것을 볼수 있다.
열심히 삽질을 해보았다.
1) 일단 timeZone에 관한 자료들을 찾아보았다.
2) 맨처음 개발시 server 자체에서 날짜부분을 UTC-> KST로 바꿨으나, 프론트에서 KST로 시간을 바꿔주는 로직이 없었다. 또한 server쪽에서 시간을 변환 하는 것보단 client 에서
시간을 바꿔 주는것이 유지 보수 하기 더 쉽다고 느껴져서
client 에서 로직을 구현 하기로 하였다.
3) 어떻게 하면 좋을지 찾아보던중 눈에 들어오는 제목의 글이 있었다.
"왜 내가 작성한 javascript Date 코드가 서버에서는 다르게 보일까"
-- 일단 지금 현재 서버에서 다르게 보이지 않고 client 에서만 다르게 보이지만,
다르게 보이는건 똑같기 때문에 글을 정독 하게 되었다.
timeZone에 관하여 정말 자세하게 써놓으셨다.
여기서 필요한 문장만 발췌해 보았다.
-> Z를 붙이면 UTC 기준으로 되기 때문에 client 단 에서도 UTC 기준으로 보여진게
아닐까 라는 생각을 하였다.
현재 server 쪽에서 자체적으로 UTC -> KST 로 바꿔주는 로직을 작성한 상태이다.
const Viewdiary = (item) => {
let time = item.date.split(".");
let dateValue = new Date(time[0]);
if(ViewData.id !== item._id){
setViewData({
title : item.title
,content : item.content
,color : item.color
,id : item._id
,date : dateValue
})
setBtnStatus(true);
}
};
let time = item.date.split(".");
-> split를 사용하여 . 을 기준으로 문자열을 분할 하였고
let dateValue = new Date(time[0]);
-> 분할한 [0]번째 index의 문자열 값을 dateValue 에 할당 하였다.
그리고 setViewData 의 date 부분에 dateValue 를 넣어주었다.
어떻게보면.. client 쪽에 UTC 로 인식하지 못하게 한것이다.
-> 등록된 날짜가 잘 보여지는것을 볼수 있다.
하지만 이 방법은 어떻게 보면 눈속임 일수도 있어서 수정하고 다른 방법을 찾아보았다.
PC의 표준시간대 설정 관계 없이 한국 시간 표시하기
const Viewdiary = (item) => {
const curr = new Date(item.date);
const utc = curr.getTime() + (curr.getTimezoneOffset() * 60 * 1000);
const KRTIME = 9 * 60 * 60 * 1000;
const dateValue = new Date(utc + (KRTIME));
if(ViewData.id !== item._id){
setViewData({
title : item.title
,content : item.content
,color : item.color
,id : item._id
,date : dateValue
})
setBtnStatus(true);
}
};
-> 날짜가 바뀌지 않는다.....
-> 서버단 시간 수정하는부분을 제거후,
화면쪽에서 만 UTC 시간대를 +9시간 해줘서 한국 표준시간 맞추는 함수로 구현 해보자.
따라, 입력창의 상태값으로 아래 와 같이 적었고 ,ViewData 안에 데이터들의 객체 를 넣어두었다.
const [ViewData, setViewData] = useState({
id:""
,title:""
,content:""
,date: new Date()
,color:""
})
const {title, content, date } = ViewData;
그리고 등록시 보이는 다이어리 list 의 상태값 으로는
아래와 같이 구현 하였다.
const [list, setData] = useState([]);
다이어리가 등록 되었을때 보이는 부분의 로직을 아래 와 같이 list. map을 사용해 나열해 주었다.
-> search 에 server의 데이터를 가져오는 로직을 구현해놓은 상태이다.
const UTCchangeKST = (date) => {
let krDate = new Date(date);
krDate.setHours(krDate.getHours() + 9);
return krDate.toISOString();
};
const search = (params) => {
let date = null;
if(params){
date = params;
}else{
date = new Date(ViewData.date);
}
console.log(ViewData.date);
axios.get(API_URL+ '/diary?year='+String(date.getFullYear())+'&month='+String(date.getMonth()+1))
.then((response) => {
let listData = [];
for(let i=0;i<response.data.data.length;i++){
listData[i] = response.data.data[i];
listData[i].date = UTCchangeKST(response.data.data[i].date)
}
setData(listData);
})
}
-> let krDate = new Date(date);
new Date() 는 현재 로컬 시간을 나타낸다.
let krDate = new Date(date); // new Date(date) 의 (date)는 UTC 형태로 가져오기 때문에
krDate.setHours(krDate.getHours() + 9); // date의 시간에 +9 시간을 해주었다.
return krDate.toISOString(); // return 값으로 이전의 문자열로 만들었던 date의 값을 ISO8601 표준형태로
맞춰 주기 위해 .toISOString(); 를 사용하였다.
-> let date = null; // 파라미터로 넘어온 date 값을 초기화 해주고
만약 search에 ()인자값이 파라미터로 넘어오면 date는 파라미터로 넘어온 인자 값이 되는것이고,
아닐시 , ViewData.date 의 담겨진 new Date 의 값이 된다.
axios.get(API_URL+ '/diary?year='+String(date.getFullYear())+'&month='+String(date.getMonth()+1))
-> 일년치의 다이어리에서 한달치의 다이어리 날짜만 가져오는 로직이다.
.then((response) => {
let listData = [];
for(let i=0;i<response.data.data.length;i++){
listData[i] = response.data.data[i];
listData[i].date = UTCchangeKST(response.data.data[i].date)
}
setData(listData);
})
-> listData 를 빈배열로 [] 초기값을 정하고
for문을 사용해 0 부터 받아온 data의 길이 값 만큼 반복할때
response.data.data[i] 의 값을 = listData[i] 에 할당해 주고,
UTCchangeKST(response.data.data[i].date)
-> response.data.data[i].date 의 값을 UTCchangeKST 함수를 사용해 UTC 의 시간을 KST로 바꿔주었다.
바꿔준후 setData에(listData)를 넣어 주었다.
-> 아래 사진을 보면
다이어리 등록할때 저장되는 date는 UTC 로 저장이 되있는데, 저장된 diary를 조회시 저장된 다이어리의 date가 KST의 형태로
나타나는것을 볼수 있다.
-> front쪽에서는 KST형식 <new Data()>으로 날짜 처리를 하고 있었고
백엔드서버에서는 UTC 형식으로 포맷을 쓰고 있다. 포맷은 ISO8601 쓰고 있는건 문제없었지만
시간차이가나서 날짜가 하루밀리는 현상이 발생. 따라 KST 를 -> UTC 로 바꿔주는 함수를 만들었다.
const KSTchangeUTC = (date) => {
let krDate = new Date(date);
krDate.setHours(krDate.getHours() - 9);
return krDate.toISOString();
};
const Viewdiary = (item) => {
if(ViewData.id !== item._id){
setViewData({
title : item.title
,content : item.content
,color : item.color
,id : item._id
,date : new Date(KSTchangeUTC(item.date))
})
setBtnStatus(true);
console.log(KSTchangeUTC(item.date))
}
};
-> 드디어 해결되었다.........
다시한번 정리를 하자면
1.server에서 받아오는 date의 값을 한국 시간으로 변환
2. 현재 보여지는 new Date()의 형태를 다이어리에 저장된 UTC 형태로 보여지게 하기
이 2가지의 방법을 가지고 해결하였다.
날짜랑 시간 맞추는게 이렇게 어렵다니.. 다른 timeZone 오류 보면 금방 쉽게 해결 하는것 같지만
왜 나는 유독 더 timeZone 오류 에 허덕인걸까... 🤤
보기 좋게 하기 위해 오류들을 정리 하고 해결 방법을 정리 하였지만,
사실상 이 문제를 해결하기 까지 꽤 많은 코드들을 썼다 지웠다 했다.
(지금도 주석 처리된 코드들이 많다.. 오류를 해결 하였으니 깨끗하게 지우고 다시 정리해야지)
막상 어떻게 해결 하면 좋을지 원리를 알기까지 꽤나 시간이 걸렸지만
이 문제를 해결하면서 어떻게 생각해야 하고 , 어떤 방식으로 접근 해야 할지 하나 더 배운것 같아서 기분이 뿌듯하다.
p.s 근데 다시는 만나고 싶지 않은 오류이다. 다른 블로그 글에서의 해결방법은 라이브러리를 사용하면 된다고 하는데
다음번엔 라이브러리를 사용해 봐야겠다.
TimeZone오류.. 다신 만나지 말자......
오호 시간쪽이 많이 어렵네요. 참고할게요~ 감사합니다. ♥