-
timestamptz에 저장한 시간대 이름은 어디로 갔을까Data Analysis 2026. 10. 5. 00:20728x90반응형

2026년 9월 28일 서울 오전 9시 예로 순간과 지역 이름의 보관 위치를 설명한 자체 제작 개념도입니다. PostgreSQL의
timestamptz에는 입력한Asia/Seoul같은 시간대 이름이 남지 않습니다. 저장되는 것은 한 순간입니다. 원래 선택한 지역까지 다시 보여 줘야 한다면 시간대 이름을 별도 열에 보관하세요.서울 오전 9시를 저장했는데 조회 결과가 자정으로 나오는 것도 같은 이유로 설명할 수 있습니다. 조회 세션의 시간대가 UTC라면 서울 오전 9시에 해당하는 UTC 자정을 보여 줍니다. 값이 아홉 시간 이동했다고 판단하기 전에 입력의 자료형과 세션 설정부터 확인해야 합니다.
입력, 저장, 표시가 각각 하는 일
timestamp with time zone이라는 이름은 시간대 문자열도 값 안에 함께 들어갈 것처럼 보입니다. PostgreSQL 문서는 입력값을 UTC 기준으로 변환하며, 원래 지정했거나 추정한 시간대는 보존하지 않는다고 설명합니다. 출력할 때는 현재 세션의TimeZone에 맞춰 변환합니다. PostgreSQL 18 날짜·시간 자료형다음 세 입력은 같은 순간을 가리킵니다.
2026-09-28 09:00:00+092026-09-28 00:00:00+002026-09-28 09:00:00 Asia/Seoul
첫 번째의
+09는 UTC와 아홉 시간 차이라는 수치입니다. 세 번째의Asia/Seoul은 지역 규칙을 고르는 이름입니다. 두 표현으로 같은 순간을 만들었다고 해서 저장된 값에서 어느 표현을 사용했는지 복원할 수 있는 것은 아닙니다.오프셋만으로 지역을 알아내려 해도 답이 하나로 정해지지 않습니다. 같은 오프셋을 쓰는 지역이 여럿일 수 있고, 지역에 따라 계절이나 시기에 맞춰 오프셋이 달라집니다. 사용자가 고른 지역을 알아야 하는 기능이라면 그 정보를 처음부터 받는 편이 분명합니다.
같은 값을 두 방식으로 표시하는 SQL
아래는 공식 변환 규칙을 적용한 설명용 SQL입니다. 실제 서버의 실행 로그는 아닙니다.
SELECT instant AT TIME ZONE 'UTC' AS utc_clock, instant AT TIME ZONE 'Asia/Seoul' AS seoul_clock FROM ( VALUES ( TIMESTAMPTZ '2026-09-28 09:00:00+09' ) ) AS example(instant);utc_clock은2026-09-28 00:00:00,seoul_clock은2026-09-28 09:00:00을 나타냅니다. 두 개의 사건을 만든 것이 아니라 같은 순간을 서로 다른 지역의 시계로 읽은 결과입니다. 여기서 반환된 두 열은timestamp without time zone입니다. 출력에 오프셋이 붙지 않는 이유까지 자료형과 함께 봐야 합니다. AT TIME ZONE의 입력·출력 자료형반대로
timestamp without time zone에AT TIME ZONE 'Asia/Seoul'을 적용하면, 그 벽시계 숫자를 서울의 시각으로 해석해timestamptz를 만듭니다. 같은 연산자라도 입력 자료형에 따라 방향이 바뀝니다.SELECT TIMESTAMP '2026-09-28 09:00:00' AT TIME ZONE 'Asia/Seoul';이 결과의 표시 형태는 세션 시간대의 영향을 받습니다. UTC 세션에서는 자정과
+00이 보일 수 있습니다.AT TIME ZONE을 한 번 더 붙여 원하는 숫자가 나올 때까지 조정하기보다, 현재 값이 지역의 벽시계 시각인지 이미 확정된 순간인지 먼저 확인하세요.시간대 없는 입력이 들어오는 지점
입력 문자열에 시간대가 없는데 대상 열이
timestamptz라면 PostgreSQL은 세션의TimeZone을 사용해 해석합니다. 따라서 앱 연결은 UTC인데 관리 도구 연결은 서울로 설정돼 있으면, 같은09:00문자열을 넣어도 서로 다른 순간을 만들 수 있습니다. 시간대가 없는 입력의 해석진단할 때는 쓰기 직전의 값과 자료형을 먼저 기록합니다. 다음으로 같은 연결에서 세션 설정을 확인합니다.
SHOW TimeZone;예를 들어 화면에서 선택한 “서울 오전 9시”를 API가
2026-09-28T09:00:00으로만 전송한다면 지역 정보가 이미 빠졌습니다. DB 출력 형식을 바꿔도 그 누락을 해결하지 못합니다. API에서 오프셋을 포함한 순간을 보내거나, 지역 이름과 현지 시각을 명시적으로 전달해 변환 위치를 한곳으로 정해야 합니다.timestamp without time zone리터럴에+09를 붙이는 실수도 피해야 합니다. PostgreSQL은 문자열을 먼저 훑어서 자료형을 자동으로 바꾸지 않으며, 시간대 없는 자료형으로 정해진 입력의 시간대 표시는 무시할 수 있습니다. 예제에서TIMESTAMPTZ와TIMESTAMP를 일부러 구분한 이유입니다.예약 테이블에는 무엇을 더 저장할까
이미 발생한 사건이라면
occurred_at timestamptz하나가 중심이 됩니다. 사용자가 어느 지역에서 입력했는지까지 필요할 때만 별도 메타데이터를 붙이면 됩니다. 반면 “매주 뉴욕 오전 9시”라는 예약은 미래의 현지 시각을 반복한다는 규칙을 보존해야 합니다.한 번 확정된 예약의 표시 지역을 기억하려면 다음처럼 설계할 수 있습니다. 제품에 적용할 완성 스키마가 아니라 저장 책임을 나눈 예시입니다.
CREATE TABLE appointment_example ( starts_at timestamptz NOT NULL, zone_name text NOT NULL );starts_at으로 순서를 비교하고,zone_name으로 사용자가 고른 지역의 시계를 다시 표시합니다.text NOT NULL만으로 유효한 지역 이름을 검사하는 것은 아니므로 입력 검증도 필요합니다. PostgreSQL의pg_timezone_names는 서버가 인식하는 시간대 이름을 확인하는 데 사용할 수 있습니다. 시간대 이름 뷰반복 일정이라면 현지 날짜·시각과 반복 규칙도 별도로 필요할 수 있습니다. 지역의 미래 시간대 규칙이 바뀔 때, 예약된 순간을 유지할지 현지 9시를 유지할지는 제품이 정해야 합니다. UTC에 변환한 값만으로 사용자의 원래 의도를 다시 알아낼 수는 없습니다.
현재 테이블에
timestamptz만 남아 있다면, 시간대 이름은 원본 입력이나 별도 기록에서 찾아야 합니다. 조회 결과의 오프셋을 지역 이름으로 바꿔 채우지 마세요. 새 입력부터 “언제인가”와 “어느 지역의 시간으로 정했는가”를 나눠 받으면 표시가 달라져도 해석이 흔들리지 않습니다.2026년 9월 28일 PostgreSQL 18 공식 문서 기준입니다. API 드라이버가 실제로 보내는 자료형과 연결별 설정은 해당 환경에서 확인해야 합니다.
728x90반응형'Data Analysis' 카테고리의 다른 글
UNIQUE를 걸었는데 빈 값이 여러 개 들어가는 이유 (0) 2026.10.05 SQLite에 외래 키를 썼는데 잘못된 참조가 들어가는 이유 (0) 2026.10.05 DuckDB-Wasm이란? CSV를 서버에 올리지 않고 분석하는 구조 (0) 2026.09.11 P-Value, T-Test, Z-Test 설명 (0) 2023.06.27 기상데이터와 GS25 판매량 데이터를 이용한 분석 리포트 - 2 (0) 2021.03.08