Node 백엔드에서 new Date()로 시각을 저장하는데, 저장된 값이 실제 한국시간이랑 9시간 밀려서 조회됩니다. 컬럼은 이렇게 잡혀 있어요.
created_at timestamp NOT NULL DEFAULT now()예를 들어 오전 11시에 등록한 글인데 DB엔 02:03 으로 들어가 있고, 화면에서도 그대로 02시로 보여요. 딱 9시간 차이라 타임존 문제인 건 알겠는데, 앱에서 시간을 따로 변환하는 코드는 없거든요. 컬럼 타입을 timestamptz로 바꾸면 되는 건지, 아니면 앱에서 +9 해서 넣어야 하는 건지 헷갈립니다. 어떻게 잡는 게 맞나요?
댓글 2
왜 9시간 밀렸냐면, timestamp(=timestamp without time zone)는 타임존 정보를 아예 안 가진 '벽시계 문자열' 같은 타입이에요. 드라이버가 UTC 기준 값을 보내면 Postgres는 그걸 아무 변환 없이 그 숫자 그대로 저장합니다. 그리고 읽을 때도 변환을 안 해주니, 저장은 UTC(02:03)로 됐는데 사람은 그걸 KST로 착각해서 보는 거죠. 딱 9시간이 어긋나는 이유입니다.
timestamptz(timestamp with time zone)는 이름과 달리 타임존을 '같이 저장'하는 게 아니라, 항상 UTC라는 절대 시점 하나로 저장해두고 읽을 때 세션 타임존에 맞춰 변환해서 보여줍니다. 그래서 저장/조회 어느 쪽이든 일관돼요.
마이그레이션은 이렇게 갑니다.
ALTER TABLE t ALTER COLUMN created_at TYPE timestamptz
USING created_at AT TIME ZONE 'Asia/Seoul';
주의할 건 USING 절이에요. 지금 컬럼에 들어있는 기존 값들이 '한국시간을 timestamp로 잘못 담아둔 것'인지 'UTC를 담아둔 것'인지에 따라 AT TIME ZONE에 뭘 넣을지가 달라집니다. 몇 건 뽑아서 실제 저장된 값이 어느 기준인지 먼저 확인하고 변환하세요. 여기서 잘못 잡으면 또 9시간 틀어집니다.
앞으론 앱은 UTC로만 저장/전달하고, 한국시간 표기는 화면 그리는 마지막 단계에서 포맷팅하세요. DEFAULT now()는 timestamptz에서도 그대로 잘 동작합니다.