본문 바로가기
DATABASE/PostgreSQL

[PostgreSQL] TIMESTAMP 컬럼의 Timezone 알아보기 (timestamp / timestamptz)

by DANEW 2026. 4. 14.
반응형

TIMESTAMP 컬럼 타입

PostgreSQL을 주력 DB로 쓰지 않고, 시스템실에서 세팅해주는 VM 서버 위에 간단한 용도로 쓰다가

현재 회사의 레거시 DB를 새로운 통합 DB로 구축하는 프로젝트를 진행 하고 있다.

 

새로운 통합 DB를 PostgreSQL로 정하여 k8s 환경에 CNPG를 올리게 되었고, 새로운 환경에서 새롭게 처음 사용하게 되었다.

 

기존에는 다 타임존을 KST로 세팅하고 진행하였으나, 각 서비스의 파드별로 Timezone 설정이 다를 수 있다는 것을 알게 되었고 그렇게 Timezone이 이슈가 될지 이때 처음 알게되었다.

 

Timestamp컬럼의 timezone에대해 한번 알아보고 사용해 보도록하자.

 

TIMESTAMP /  TIMESTAMPTZ 컬럼의 차이

너무나 신기하게도 PostgreSQL에서는 DB의 TIMEZONE이 아닌 클라이언트(세션)의 TIMEZONE을 최우선으로 반영한다

DB내장 함수 now()를 호출하여도... 클라이언트의 timezone에 맞게 시간이 생성된다.

 

ORACLE / MSSQL을 주력으로 사용하던 입장으로써는 매우 당황스럽게 느껴진 부분이다.

 

WITHOUT TIME ZONE (TIMESTAMP)

타임존을 명시하지 않으며, 입력되는 날짜 + 시간만 저장


클라이언트(세션)의 타임존에 따라 날짜 + 시간을 저장하며, 조회 시에는 저장된 시점의 값을 그대로 보여줌

 

WITH TIME ZONE (TIMESTAMPTZ)

입력 클라이언트(세션)의 타임존을 해석하여 내부적으로 UTC 값으로 변환하여 날짜 + 시간을 저장

클라이언트(세션)의 타임존이 어느 값이든 UTC 값으로 변환하여 저장하며, 조회 시에는 UTC로 저장된 값이 클라이언트(세션)의 타임존에 따라 계산되어 보여줌

 

실제 사용 예시

컬럼의 설명만으로는 너무나 받아들이기 어려웠다.

역시나 모를때에는 실제로 한번 테스트 해보는 것.

세션의 설정 된 타임존 별로 TIMESTAMP / TIMESTAMPTZ 에 대해 입력 및 조회 해보았다.

 

NOW() 함수

세션의 타임존 별로 각 데이터를 now()함수로 INSERT 하는 것에 대한 테스트

 

Asia/Seoul

SET timezone = 'Asia/Seoul';

INSERT INTO t_ban_time_zone_test VALUES(1, now(), now(), 'Asia/Seoul -> NOW()');

SELECT * FROM t_ban_time_zone_test where t_no = 1;

 

UTC

SET timezone = 'UTC';

INSERT INTO t_ban_time_zone_test VALUES(2, now(), now(), 'UTC -> NOW()');

SELECT * FROM t_ban_time_zone_test where t_no = 2;

America/New_York

SET timezone = 'America/New_York';

INSERT INTO t_ban_time_zone_test VALUES(3, now(), now(), 'America/New_York -> NOW()');

SELECT * FROM t_ban_time_zone_test where t_no = 3;

 

각 컬럼 타입에 대한 테스트 결과

타임존 별로 INSERT된 3개의 row에 대해 세션에 설정 된 타임존 별로 데이터 SELECT

  1. Asia/Seoul
  2. UTC
  3. America/New_York
 
    1.  

TIMESTAMP 컬럼의 경우 입력 하는 세션의 타임존의 시간을 고정적으로 입력 (타임존 정보가 없음)

  • 입력 시 타임존에 따라 의도치 않은 시간을 입력 할 수 있음
  • 조회 시 고정적으로 입력된 시간을 그대로 조회 할 수 있음

TIMESTAMPTZ 컬럼의 경우 입력할 때 타임존의 시간을 계산하여 입력 (타임존 정보가 있음)

  • 입력 시 타임존에 영향을 받지 않고 절대적인 공통 시간으로 계산되어 입력 됨
    • 조회 시 세션의 타임존에 따라 시간이 계산되어 다르게 조회 될 수 있음

VALUE 값 입력

세션의 타임존 별로 각 데이터를 value로 INSERT 하는 것에 대한 테스트

 

Asia/Seoul

SET timezone = 'Asia/Seoul';

INSERT INTO t_ban_time_zone_test VALUES(4, '2025-12-23 20:50:00', '2025-12-23 20:50:00', 'Asia/Seoul -> value');

SELECT * FROM t_ban_time_zone_test where t_no = 4;

UTC

SET timezone = 'UTC';

INSERT INTO t_ban_time_zone_test VALUES(5, '2025-12-23 20:50:00', '2025-12-23 20:50:00', 'UTC -> value');

SELECT * FROM t_ban_time_zone_test where t_no = 5;

America/New_York

SET timezone = 'America/New_York';

INSERT INTO t_ban_time_zone_test VALUES(6, '2025-12-23 20:50:00', '2025-12-23 20:50:00', 'America/New_York -> value');

SELECT * FROM t_ban_time_zone_test where t_no = 6;

각 컬럼 타입에 대한 테스트 결과

 

타임존 별로 INSERT된 3개의 row에 대해 세션에 설정 된 타임존 별로 데이터 SELECT

  1. Asia/Seoul
  2. UTC
  3. America/New_York

  1.  

    특정 VALUE 값을 넣으려 할 때 (예: 데이터 마이그레이션 등의 작업)

    TIMESTAMP 컬럼의 경우에는 원하는 값을 세션에 상관없이 고정값으로 입력이 가능

    TIMESTAMPTZ 컬럼의 경우 세션의 타임존에 대해 계산이 되어 저장되기에 주의가 필요


    원하는 값을 정확하게 넣기 위해서는 꼭 세션에 타임존 맞추어 입력

반응형