의 함정과 올바른 날짜 비교
1. 문제의 핵심: 과 로컬 타임존의 괴리
자바스크립트의 Date 객체는 내부적으로 유닉스 타임스탬프(UTC 기준 밀리초)를 저장합니다.
문제는 이를 문자열로 변환할 때 발생합니다.
❌ 흔한 실수: 절삭
많은 경우 YYYY-MM-DD 형식의 날짜가 필요할 때 다음과 같은 코드를 사용합니다.
new Date().toISOString().slice(0, 10);
이 방식은 한국(UTC+9) 기준 오전 00:00 ~ 08:59 사이에 "어제" 날짜를 반환합니다.toISOString()은 이름 그대로 UTC(0시) 기준의 표준시를 출력하기 때문입니다.
| 출근 직후 | 2026-02-23 08:30 | 2026-02-22 23:30 | "2026-02-22" (오류) |
| 점심 시간 | 2026-02-23 12:30 | 2026-02-23 03:30 | "2026-02-23" (정상) |
2. 날짜 처리의 3가지 원칙
타임존 이슈를 근본적으로 방지하기 위해 다음 원칙을 준수해야 합니다.
원칙 1: 날짜 비교는 '문자열' 혹은 '순수 날짜 객체'로 통일
시간 정보(시, 분, 초)가 포함된 상태로 비교하면 타임존 오프셋에 따라 결과가 뒤틀립니다. 날짜만 비교해야 한다면 반드시 YYYY-MM-DD 포맷의 로컬 문자열로 변환 후 비교하세요.
원칙 2: 메서드 사용 지양
"오늘"의 연, 월, 일을 구할 때는 사용자의 환경(브라우저) 또는 서버 설정에 맞춘 로컬 메서드를 사용해야 합니다.
- 사용 금지:
getUTCFullYear(),getUTCMonth(),getUTCDate() - 사용 권장:
getFullYear(),getMonth(),getDate()
원칙 3: 서버와 클라이언트의 '오늘' 정의 동기화
서버가 UTC 기준인 DB 환경에서 그대로 "오늘"을 계산하면, 한국 클라이언트가 보는 "오늘"과 데이터가 불일치하게 됩니다. 기준이 되는 타임존을 명시하거나, 날짜 문자열(YYYY-MM-DD) 자체를 주고받는 것이 안전합니다.
3. 추천 해결 방법
A. 유틸리티 함수 활용
외부 라이브러리 없이 로컬 날짜를 안전하게 추출하는 방법입니다.
/**
* 전달받은 Date 객체를 해당 환경의 로컬 날짜(YYYY-MM-DD)로 변환
*/
export function toLocalDateStr(date = new Date()) {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, "0");
const d = String(date.getDate()).padStart(2, "0");
return `${y}-${m}-${d}`;
}
// 사용 예시
const today = toLocalDateStr();
const isPast = today < "2026-02-25"; // 문자열 비교도 안전함
B. Intl.DateTimeFormat 활용
조금 더 현대적이고 깔끔한 방식입니다.
const today = new Intl.DateTimeFormat('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
}).format(new Date()); // "2026-02-23"> 참고: 'ko-KR' 로케일은 YYYY-MM-DD 형식을 표준으로 사용하므로 유용합니다.
4. 최종 체크리스트
프로젝트 배포 전, 다음 코드가 포함되어 있는지 확인하세요.
toISOString().slice(0, 10)이 비즈니스 로직(날짜 비교, 오늘 표시)에 사용되고 있는가?- 서버에서
new Date()로 생성한 값이 한국 시간대(KST)를 고려하지 않은 채 DB에 쿼리되고 있는가? - 기한 만료(Expired), 잠금(Locked) 등의 로직이 00시~09시 사이에도 정상 작동하는가?
'TIL' 카테고리의 다른 글
| [260312 TIL] Next.js + Prisma + tRPC + TQuery (0) | 2026.03.12 |
|---|---|
| [260117 TIL] Next Image와 Preload를 활용한 이미지 최적화 (0) | 2026.01.17 |
| [251227 TIL] RSC 에서 redirect 사용시 주의점 (0) | 2025.12.27 |
| [251214 TIL] React2Shell 사건 정리 (0) | 2025.12.14 |
| [251127 TIL] Next.js 이미지 최적화 정리 (0) | 2025.11.27 |