간단한 날짜 포맷은, Intl.DateTimeFormat

Sohee Park·2023년 1월 19일
8
post-thumbnail

"마지막 업데이트 시간이 표시되면 좋겠어요."

기획자가 오늘 내게 요구했던 사항 중 하나다.
개발 데드라인이 오늘이었는데, 마지막 개발자 테스트를 하던 중 요구했던 스펙 중 하나가 의도와 다르게 구현하기가 어렵게 되자 차선책으로 얘기를 꺼냈다.

어려운 일은 아니니, 알겠다고 하고 라이브러리를 쓸 정돈 아닌 것 같아서 Date객체를 이용해서 뚱땅뚱땅 만들고, 2자리 숫자의 시간은 10미만일 때 숫자 0을 앞자리에 붙여주었다.

개발 완료하고 코드리뷰를 받는데 리뷰어가 코멘트를 달아줬다.

Intl.DateTimeFormat을 쓰는건 어때요?

솔직히 처음보는 메서드라, 이게 뭔고 싶어서 검색해봤더니 정말 간단한 날짜 표시에 제격인 녀석이였다.

Intl이 뭐예요..?

Intl 객체는 각 언어에 맞는 문자비교, 숫자, 시간, 날짜비교를 제공하는, ECMAScript 국제화 API를 위한 이름공간(namespace)입니다.

사용할 때는 어떤 언어(locales)로 보여줄 지 정해야 하는데, 생략하게 되면 구현된 기본 locales가 사용된다고 한다(아마 사용하는 기본 언어 설정에 따른다는 소리 같다 🤔).

언어 식별자(locale identifier)는 아래 순서대로 lookup 혹은 best fit방식으로 찾아서 사용한다.

  1. a language subtag,
  2. (optionally) a script subtag,
  3. (optionally) a region (or country) subtag,
  4. (optionally) one or more variant subtags
  5. (all of which must be unique),
  6. (optionally) one or more BCP 47 extension sequences, and
  7. (optionally) a private-use extension sequence

subtag은 하이픈으로 구별되는데, 제일 익숙한걸로 예시를 들자면 ko-kr 중 하이픈 뒤에 있는 krsubtag이다.

script subtag이 뭔지 궁금하긴 하지만, MDN 예시를 보니 다른 나라 언어를 쓸 게 아니고 한국어만 쓸 거라면 참고만 하면 될 것 같다.

출처: MDN - Intl

마지막 업데이트 시간 구현

Intl.DateTimeFormat에 관한 문서는 한글화가 아주 잘되어 있고, 예제도 상당히 많아서 MDN 문서를 보면 그리 어렵지만은 않다.

이 API를 알기 전 구현했던 코드는 아래와 같았다.

const getLastUpdateTime = () => {
  const date = new Date();
  const month = date.getMonth + 1
  return `${date.getFullYear()}.${addZero(month)}.${addZero(date.getDate()) ${addZero(date.getHours())}:${addZero(date.getMinutes())}:${addZero(date.getSeconds())}`;
};

const addZero = (num:number):string => {
  return num < 10 ? '0' + num : '' + num;
}

푸우짤이게 대체 무슨 코드람

구현이야 했지만 얼마나 더러운지.. 🤦🏻‍♂️
하지만 Intl.DateTimeFormat을 사용하면..?

const getLastUpdateTime = () => {
  const option = {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit', 
    minute: '2-digit', 
    second: '2-digit',
    hour12: false,
  }
  return new Intl.DateTimeFormat('ko-KR', option).format(new Date());
}

console.log(getLastUpdateTime()); // 2023. 01. 20. 01:32:38

훨씬, 훨씬 깔끔해졌다!! 🧚🏼‍♂️

부록

사실 이 기능을 Next.js에서 만들다보니, 새로운 에러를 발견했었다. Text content does not match server-rendered HTML란 에러 메세지였다.

말그대로 서버에서 렌더링 했을 때의 텍스트와 실제 클라이언트의 렌더링 텍스트가 일치하지 않아서 생기는 문젠데, new Date()를 바로 사용했기 때문에 발생한 문제였다.

React의 useState를 사용해서 상태값으로 관리하면, 에러가 발생하지 않는다.

const [ lastUpdateTime, setLastUpdateTime ] = useState<string>('');

const getLastUpdateTime = () => {
  const option = {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit', 
    minute: '2-digit', 
    second: '2-digit',
    hour12: false,
  }
  return new Intl.DateTimeFormat('ko-KR', option).format(new Date());
}

useEffect(() => {
  setLastUpdateTime(getLastUpdateTime());
}, [router]) //next js router 이벤트가 발생할 때마다 실행하도록 했었다.

//...

return (
  <div>
  	//...
  	<p>마지막 업데이트 시간: {lastUpdateTime}</p>
  </div>
)

부록 2 - Intl.RelativeTimeFormat

이 메서드는 상대적인 시간 포맷팅을 해준다. 1시간전, 2일전, 30초전 같은 현재 시간에 상대적인 시간을 계산해서 그 나라 언어로 보여준다.
완전 꿀🍯 기능인듯!

profile
고양이 두마리를 모시고 사는 프론트엔드

1개의 댓글

comment-user-thumbnail
2023년 1월 20일

A commitment of appreciation is all together for the information, keep on sharing such a data. ACAeronet Login

답글 달기