2025년 08월 11일

4

크로미움 기반 브라우저와 사파리 브라우저에서의 Date 객체 처리 방식

크로스 브라우징

왜 ISO 8601 형식으로 날짜를 다뤄야 할까요?

프론트엔드 개발에서 백엔드로부터 받은 날짜 데이터를 화면에 표시할 때, 특정 브라우저(Safari)에서만 Invalid Date 오류가 발생하는 경우가 많습니다. 이는 new Date() 생성자가 브라우저마다 다르게 동작하기 때문이며, 모든 브라우저에서 일관된 결과를 얻기 위해서는 표준 형식인 ISO 8601을 사용하는 것이 중요합니다.

JavaScript의 공식 명세(ECMAScript)는 ISO8601 형태(YYYY-MM-DDTHH:mm:ss.sssZ)의 날짜 문자열만 모든 브라우저에서 일관되게 파싱하는 것을 보장합니다. 따라서 비표준 형식의 경우 어떻게 처리할지는 브라우저 재량에 따르게 됩니다.


문제 상황

디자이너가 작성한 디자인 시안에 따라 날짜를 2025. 08. 11.과 같이 점(.)으로 구분하여 표시해야 했습니다. 만약, 백엔드로부터 받은 응답이 2025. 08. 11과 같은 문자열이라면, 이 문자열을 Date 생성자에 전달하면 어떻게 될까요? 결과적으로 유저가 사용하는 브라우저 종류에 따라 다른 결과를 낳게 됩니다!

1const dateResponseFromServerr = "2025. 08. 11."; 2const myDate = new Date(dateString); 3 4console.log(myDate) // ❗️ 사파리 브라우저에서는 Invalid Date 에러가 발생합니다.

이 코드는 크롬에서는 정상적으로 동작하는 것처럼 보이지만, 사파리에서는 Invalid Date 오류를 반환합니다. 사용자가 어떤 브라우저를 사용할지 모르는 상황에서 Date 객체 파싱을 브라우저 재량에 따르게 하는것은 정확한 날짜를 유저가 인지하지 못하게 할 위험 부담이 따릅니다.


브라우저별 동작 차이

이 문제의 원인은 자바스크립트 표준(ECMAScript)이 날짜 문자열 파싱에 대해 어떻게 규정하고 있는지 살펴보면 명확해집니다.

  • 표준의 부재: 자바스크립트 명세는 new Date()가 오직 ISO 8601 형식(YYYY-MM-DDTHH:mm:ssZ)의 문자열 파싱만을 보장합니다. 그 외의 형식은 구현 종속적(implementation-dependent) 이므로 브라우저마다 다르게 동작할 수 있습니다.
  • 크롬의 관대함: 크롬의 V8 엔진은 개발자 편의를 위해 다양한 비표준 형식을 최대한 '추측'하여 유효한 날짜로 변환해 줍니다.
  • 사파리의 엄격함: 사파리의 JavaScriptCore 엔진은 표준을 엄격하게 준수하여, ISO 8601 형식이 아닐 경우 해석을 거부하고 Invalid Date를 반환합니다. (저의 경우도 크롬과 달리 사파리에서는 Invalid Date가 화면에 표시되는 문제였습니다.)

올바른 접근 방법

안정적인 날짜 처리를 위해서는 파싱포매팅 단계를 명확히 분리해야 합니다.

  1. ISO 8601 형식으로 Date 객체 생성하기 백엔드로부터 날짜 데이터를 받을 때는 항상 ISO 8601 형식으로 받는 것이 좋습니다. 이 표준 형식의 문자열을 new Date()에 전달하면 모든 브라우저에서 안전하게 Date 객체를 생성할 수 있습니다.

    1// 백엔드에서 받은 표준 형식의 날짜 문자열 2const isoDateString = "2025-08-11T15:30:00Z"; 3 4// 표준 형식을 사용하므로 모든 브라우저에서 안전함 5const myDate = new Date(isoDateString);
  2. 생성된 객체를 원하는 형식으로 포매팅하기 일단 유효한 Date 객체가 생성되었다면, 이 객체의 메서드를 사용하여 기획/디자인 시안에 맞는 문자열로 가공하여 보여주면 됩니다.

    1function formatDateWithDots(date) { 2 if (isNaN(date.getTime())) { 3 return "날짜 오류"; 4 } 5 6 const year = date.getFullYear(); 7 const month = String(date.getMonth() + 1).padStart(2, '0'); 8 const day = String(date.getDate()).padStart(2, '0'); 9 10 return `${year}. ${month}. ${day}.`; 11} 12 13// 1단계에서 생성한 myDate 객체를 사용 14const formattedDate = formatDateWithDots(myDate); // "2025. 08. 11." 15console.log(formattedDate);
HS
@Hyungseok Kwon
Journey To Solution