UTCToLocal - 범용적인 타임존 처리방법

  • 구글 검색봇이 크롤링하는 시간값의 조건과 클라이언트에서 사용자가 보는 타임존 시간표기를 모두 달성하기 위한 테크닉입니다.
  • nextjs의 시간 관련 hydration error 해결해 나가면서, "구글 검색결과에서 올바른 시간표기를 위한 방법은 무엇일까?"에 대한 물음에서부터 출발했습니다.
  • prisma에서는 시간 저장 시 UTC+0 시간을 저장한다는 특성이 있었습니다. 얼핏보면 이는 한계처럼 보이지만 다른 올바른 의미가 있어보였습니다.
  • UTC+0 시간이란, 전 세계의 기준점이 되는 시간입니다. 타임존을 따로 지정하지 않아도 되는, 이로인해 설정이 가장 깔끔해질 수 있는 순수한 값이라고 생각할 수도 있습니다.
  • nextjs의 pre-rendering과 hydration 시에 에러가 나지 않기 위해서는, hydration까지 UTC+0 시간을 끌고가야한다고 판단했습니다.
  • 그렇게 하기 위해서는 데이터베이스에 시간 값을 저장시 UTC+0 을 저장하도록 합니다. prisma에 의해 이것은 잘 되고 있습니다.
  • 클라이언트 컴포넌트에서 어떻게할 지가 중요합니다. 처음에는 utc 시간을 그대로 출력시키되, useEffect 내부에서 클라이언트의 타임존에 맞는 시간을 출력하도록 설정하면 됩니다.
  • 구글 검색봇은 pre-rendering 된 시간값을 읽습니다. 더욱이 검색결과에 나오는 시간은 UTC+0 시간입니다. 이렇게 이해관계가 자연스레 일치되어 time 태그에 별도의 타임존을 지정하지 않아도 되므로, 설정 및 모든것이 깔끔한 상태가 되었습니다.
'use client'

import moment from 'moment-timezone'
import { useEffect, useState } from 'react'

type Props = {
  date: Date
  format?: string | undefined
}

const UTCToLocal = ({ date, format = 'YYYY-MM-DD HH:mm:ss' }: Props) => {
  const [dateString, setDateString] = useState(moment.utc(date).format(format))

  useEffect(() => {
    setDateString(moment.utc(date).tz(moment.tz.guess()).format(format))
  }, [date, format])

  return <>{dateString}</>
}
export default UTCToLocal