위험한 자바스크립트 날짜 파서: 날짜 파싱 실수를 피하는 방법
자바스크립트의 new Date(string) 생성자는 어떤 문자열 입력이라도 날짜로 추출하려 시도하며, 종종 예상치 못한 결과를 초래합니다. 이는 버그가 아니라 V8과 SpiderMonkey 엔진의 기능입니다. 파서는 텍스트를 적극적으로 해석하기 때문이죠.
예시를 통해 문제를 확인해 보세요:
new Date("2020-01-23")
// Wed Jan 22 2020 19:00:00 GMT-0500 (UTC로 해석됨)
new Date("Today is 2020-01-23")
// Thu Jan 23 2020 00:00:00 GMT-0500 (현지 시간)
new Date("Route 66")
// Sat Jan 01 1966 00:00:00 GMT-0500
new Date("Beverly Hills, 90210")
// Mon Jan 01 90210 00:00:00 GMT-0500
이러한 변환은 유효한 Date 객체를 만들어내지만 값이 잘못되어 디버깅을 어렵게 만듭니다. '캐치 22' 상황에서는 Invalid Date가 반환되는데, 이는 드물지만 실제로 올바른 동작입니다.
V8 파서의 작동 방식
ECMAScript 사양은 ISO 8601의 일부만 파싱하도록 명시하고 있습니다. 나머지는 구현에 따라 다릅니다.
V8 알고리즘:
- ISO 8601 여부 확인: 문자열이 4자리 연도 또는 부호로 시작해야 함.
- 레거시 파서로 대체: 첫 번째 숫자가 나올 때까지 단어를 무시함.
DayComposer에서 숫자 처리:
- 1–12: 월로 해석됨.
- 13–31: 모호함, 대부분 거부됨.
- 32+: 연도로 간주 (50–99 +1900).
- 기본값: 1월 1일.
이것이 왜 "Route 66"이 1966년으로, "90210"이 90210년으로 해석되는지를 설명합니다.
시간대 혼란
ISO 형식의 문자열인 "2020-01-23"은 UTC로 파싱되지만, 레거시 형식은 현지 시간을 사용합니다. 차이는 접두사에 달려 있습니다:
- 순수한 ISO: UTC로 파싱됨.
- 텍스트 포함 문자열: 레거시 모드, 현지 시간.
앞뒤 공백이 있으면 파서 동작이 바뀌며, 시간대에 따라 최대 하루까지 결과가 달라질 수 있습니다.
사파리(JSC)는 더 엄격합니다: 레거시 예제와 뒤에 공백이 있는 문자열을 거부합니다.
실제 프로젝트에서의 버그와 해결책
실제 프로젝트에서는 사용자 입력에 대해 new Date()로 대체하면 "Route 66"이 날짜로 변환되어 데이터 테이블이 손상될 수 있습니다. 해결책: 정규표현식 검증을 통한 커스텀 파서만 사용하세요.
중급/고급 개발자를 위한 최적의 실천법:
new Date()호출 전 정규표현식으로 포맷을 검증하세요.- 엄격한 ISO 파싱에는
date-fns parseISO()를 사용하세요. - 완전한 제어가 필요하면 Luxon이나 Day.js 같은 라이브러리와 커스텀 파서를 활용하세요.
- 신뢰할 수 없는 입력에
new Date(string)를 절대 사용하지 마세요. - 브라우저 간 테스트: V8, SpiderMonkey, JSC 모두 포함.
자바스크립트 vs 파이썬: 비교 분석
파이썬은 모호성을 피합니다:
datetime.fromisoformat(): 오직 ISO 8601만 허용.strptime(): 엄격한 포맷, 추가 문자 없음.
자바스크립트의 레거시 파서는 조용히 추측하지만, 파이썬은 ValueError를 던집니다.
핵심 요약
Date파서는 임의의 텍스트에서 유효하지만 잘못된 객체를 생성합니다.- 파서 동작(ISO vs 레거시)은 접두사와 공백에 따라 달라집니다.
- 프로덕션 환경에서는 항상 파싱 전에 입력을 검증하세요.
- 미래 지향적인 코드를 위해 Temporal API로 마이그레이션하세요.
- 엔진 차이로 인해 브라우저 간 테스트는 필수입니다.
— Editorial Team
아직 댓글이 없습니다.