본문 바로가기
Q&A해결2026년 8월 5일1분 읽기

DB에 저장된 시간이 9시간 밀려서 나오는데 timestamp 타입 문제일까요?

t
tz_narae
조회 816댓글 2

Node 백엔드에서 new Date()로 시각을 저장하는데, 저장된 값이 실제 한국시간이랑 9시간 밀려서 조회됩니다. 컬럼은 이렇게 잡혀 있어요.

created_at timestamp NOT NULL DEFAULT now()

예를 들어 오전 11시에 등록한 글인데 DB엔 02:03 으로 들어가 있고, 화면에서도 그대로 02시로 보여요. 딱 9시간 차이라 타임존 문제인 건 알겠는데, 앱에서 시간을 따로 변환하는 코드는 없거든요. 컬럼 타입을 timestamptz로 바꾸면 되는 건지, 아니면 앱에서 +9 해서 넣어야 하는 건지 헷갈립니다. 어떻게 잡는 게 맞나요?

댓글 2

김김영삼2개월 전
앱에서 +9 하는 건 절대 하지 마세요. 그건 데이터를 오염시키는 임시방편이라 나중에 반드시 더 큰 사고로 돌아옵니다. 타입을 timestamptz로 가는 게 맞아요.

왜 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에서도 그대로 잘 동작합니다.
ttz_narae(guest)2개월 전
기존 값이 UTC로 들어가 있는 걸 확인하고 USING 절 기준 맞춰서 timestamptz로 바꾸니 시간이 정확히 맞네요. +9 해서 우겨넣을 뻔했는데 안 하길 잘했습니다. timestamp랑 timestamptz 차이를 이제야 제대로 이해했어요, 감사합니다.
Ctrl+Enter로 등록