Postgres의 "AT TIME ZONE 'UTC'"에 숨은 함정

1 week ago 10

timestamptz에 AT TIME ZONE 'UTC' 를 적용하면 시간대만 바뀌는 것이 아니라, 시간대 정보가 없는 timestamp로 타입이 바뀜 월 단위 덧셈은 시간대에 의존하므로, UTC 기준으로 동작하는 제품에서는 한 달을 더하기 전에 UTC 기준으로 변환해야 함 UTC의 월초가 다른 시간대에서는 전월 말일일 수 있어, 기본 시간대에서 INTERVAL '1 months' 를 더하면 의도한 다음 달 월초와 다른 결과가 나올 수 있음 UTC 변환 후 월을 더해도 결과는 timestamp 이므로, timestamptz 열과 비교하는 월별 차이 계산 쿼리에 문제가 남음 월 덧셈 결과에 AT TIME ZONE 'UTC'를 다시 적용해 timestamptz로 되돌리는 방식으로 비교 문제를 해결함 UTC 변환이 타입까지 바꾸는 함정 Postgres에는 timestamp와 timestamptz 라는 두 타임스탬프 타입이 있음 timestamp에는 시간대 정보가 없으므로, 그 값만으로 현실 세계의 특정 시점을 나타내지 못함 현실에서 “오후 5시”라고 할 때도 실제로는 “우리 시간대의 오후 5시”라는 전제가 필요함 Postgres Wiki는 UTC 시각 저장에 timestamp without time zone을 사용하지 말 것을 권고함 AT TIME ZONE 'UTC' 는 timestamptz를 timestamp로 변환하므로, 시간대 없는 타입을 피하려 해도 연산 중에 사용하게 될 수 있음 '2026-02-28 16:00:00-08'::timestamptz AT TIME ZONE 'UTC'의 결과는 +00이 없는 2026-03-01 00:00:00임 실행 예제에서 타입 변환을 확인할 수 있음 원문은 timestamp와 timestamptz의 동등 비교가 항상 false가 된다고 단정하며, 두 값에서 EXTRACT(EPOCH FROM <timestamp>)로 같은 값을 얻더라도 비교가 혼란스러울 수 있다고 경고함 월별 차이 계산과 두 번의 시간대 변환 시계열 제품에서 전월 대비 차이를 계산할 때 다음처럼 한 달 차이의 행을 연결할 수 있음 SELECT a.month_start, (a.value - b.value) AS delta FROM data a JOIN data b ON a.month_start = b.month_start + INTERVAL '1 months' 월 덧셈은 시간대에 의존하므로, UTC 기...

Read Entire Article