서버와 브라우저의 시간대 맞추기
QA 기간이라 이번 주는 버그를 잡는 커밋이 대부분이었다. 그중 두 달 넘게 마음에 걸려 있던 시간대 문제를 정리했다.
4월의 임시방편
4월에 스케줄 관리 화면을 실제 API와 붙이면서 일정이 엉뚱한 시간 칸에 그려지는 문제가 있었다. API는 날짜와 HH:mm:ss 시간을 따로 주고, 이걸 합쳐서 Date로 만들어 캘린더에 넘긴다. 그런데 이 변환이 서버 컴포넌트에서 일어나고, 캘린더는 브라우저에서 그린다. 같은 문자열이라도 어느 쪽 시간대로 해석하느냐에 따라 결과가 달라졌다.
그때는 new Date()로 직접 만들어 보기도 하고, moment.tz로 변환하는 함수를 만들어 보기도 하면서 임시 커밋이 아홉 개나 쌓였다. 마지막에는 서버와 클라이언트 양쪽을 모두 UTC로 맞추는 쪽으로 정리했다. 일정 변환은 moment.utc로 하고, 캘린더 컴포넌트에는 moment.tz.setDefault('utc')를 넣었다. 화면은 맞게 나왔지만, 왜 맞는지 설명하기 어려운 코드였다.
기본 시간대를 한 곳에서
이번에는 반대로 접근했다. 센터 운영 시간은 한국 시간 기준이니, moment가 어디서 실행되든 기본 시간대를 서울로 고정한다.
// app/layout.tsx
import moment from 'moment-timezone';
moment.tz.setDefault('Asia/Seoul');
루트 레이아웃은 서버에서 실행되니 서버 쪽 moment가 이 설정을 따르고, 캘린더 컴포넌트에 있던 'utc' 기본값도 'Asia/Seoul'로 바꿨다. 적용하면서 레이아웃에 현재 시간을 찍는 로그를 잠깐 넣어, 배포된 QA 서버에서도 서울 시간으로 나오는지 확인한 뒤 지웠다.
다음 날에는 자동 로그인도 다시 켰다. 테스트용으로 10초로 줄여 두었던 쿠키 만료 시간을 21일로 되돌리고, 내비게이션의 Link들에는 prefetch를 명시해서 메뉴 이동이 빨라지도록 했다.
다음에 날짜를 다루는 화면을 만들 때는 변환이 서버와 브라우저 중 어디서 일어나는지부터 적어 두고 시작하려고 한다.
