플랜비 경기 일정이 하루 밀린 이유, 날짜에 시간대가 없었어요
날짜만 저장한 경기 일정이 KST에서 하루 앞뒤로 어긋나는 ±1일 버그의 원인과, JS Date 대신 문자열로 분리해 고친 3단계를 정리했어요.
플랜비 경기 일정이 하루 밀린 이유, 날짜에 시간대가 없었어요
라이프케어로그에서 만드는 농구 동호회 운영 매니저 플랜비(plan-b)를 개발하면서 제일 어이없었던 버그가 있어요. 경기 일정을 14일로 등록했는데 목록에는 13일로 보이는 거예요. 시간을 잘못 찍은 것도 아니었어요. 애초에 시간이 없다는 게 원인이었어요.
날짜만 있는 값은 자바스크립트가 마음대로 해석해요
경기 일정은 "5월 14일"처럼 날짜만 있으면 돼요. 그래서 YYYY-MM-DD 10자리 문자열로 받았는데, 어딘가에서 new Date('2026-05-14')로 바꾸고 있었어요. 이 한 줄이 문제예요.
브라우저 콘솔에서 직접 테스트해 보면 바로 보여요.
new Date('2026-05-14').toISOString()
// '2026-05-14T00:00:00.000Z' ← UTC 자정으로 해석날짜만 있는 ISO 문자열은 UTC 자정으로 잡혀요. 한국(KST)은 UTC보다 9시간 빠르니까 화면에선 14일 오전 9시가 돼요. 여기까진 날짜가 안 바뀌죠. 문제는 반대 방향이에요.
const d = new Date(2026, 4, 14); // 로컬(KST) 자정, 월은 0부터 세니까 5월=4
d.toISOString().slice(0, 10)
// '2026-05-13' ← 하루 전으로 밀림날짜 선택기에서 고른 값은 로컬 자정이에요. 이걸 toISOString()으로 저장하면 UTC로 바뀌면서 전날 15시가 되고, 앞 10자만 잘라 쓰면 13일이 저장돼요. 직접 돌려 보니 KST에서는 자정부터 오전 8시 59분까지, 하루 24시간 중 9시간 구간이 전부 전날로 넘어가더라고요. 자정에 만든 값은 100% 걸려요.
new Date('2026-05-14')는 UTC 자정 vs new Date(2026, 4, 14)는 KST 자정 — 같은 날짜, 다른 시각
시간대가 없는 값에 시간대를 붙이지 않기
원인을 보니 답은 단순했어요. 경기 날짜는 시각이 아니라 달력 위의 칸이에요. Date 객체로 만드는 순간 시간대라는 정보를 억지로 붙이게 돼요. 그래서 날짜만 있는 값은 끝까지 문자열로 다루기로 했어요.
- 저장: 입력값
2026-05-14를 문자열 그대로 DB에 넣어요.Date로 변환하던 코드는 지웠어요. - 정렬·비교:
YYYY-MM-DD는 자릿수가 고정이라 문자열 비교만으로 순서가 맞아요.'2026-05-13' < '2026-05-14'가 그대로 참이에요. - 표시: 화면에 "5월 14일 (목)"처럼 보여줄 때만 잘라서 조립해요. 요일이 필요하면 그때
new Date(y, m - 1, d)로 로컬 날짜를 만들고 바로 버려요.
적용해 봤더니 변환 코드가 사라진 만큼 줄 수도 줄었어요. 3단계 다 합쳐도 함수 하나 분량이에요. 반대로 경기 시작 시각처럼 진짜 시각이 필요한 값은 예전처럼 UTC ISO 문자열 24자로 저장하고, 표시할 때만 KST로 바꿔요. 날짜와 시각을 같은 타입으로 취급하던 게 진짜 원인이었어요.
테스트는 자정 값 하나면 충분해요
재발 방지용 테스트는 딱 하나 넣었어요. 로컬 자정으로 만든 날짜를 저장 함수에 넣고, 저장된 문자열이 입력과 같은지 비교하는 거예요. 고치기 전 코드에 돌려 보니 바로 빨간불이 났고, 고친 뒤엔 통과했어요. 출전 로테이션은 경기 날짜를 기준으로 도니까, 이 하루 차이가 그대로 누가 뛰는지에 영향을 줘요. 동호회 운영에서 날짜 하나가 틀리면 신뢰가 흔들리거든요.
날짜만 필요한데 Date를 쓰고 있다면 콘솔에 new Date(2026, 4, 14).toISOString() 한 줄만 쳐 보세요. 13일이 나오면 여러분 코드에도 같은 버그가 숨어 있는 거예요.
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.