데이터베이스에는 항상 UTC로 저장하세요
데이터베이스 시간 저장의 기본 규칙: 모든 타임스탬프를 UTC로 저장하세요. 사용자나 서버의 위치와 무관하게 이 규칙이 적용됩니다. 데이터베이스에 현지 시간을 저장하면 일광절약시간제 전환 시 모호한 데이터가 생기고 다중 지역 배포가 악몽이 됩니다.
컬럼 타입 참고
PostgreSQL
-- TIMESTAMP WITH TIME ZONE (timestamptz) — 권장
-- 내부적으로 UTC 저장, 세션 시간대로 표시
CREATE TABLE events (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- TIMESTAMP WITHOUT TIME ZONE — 시간대 변환 없음, 지양 권장
MySQL / MariaDB
-- TIMESTAMP: UTC 저장, 범위 1970~2038 (Y2K38 영향!)
-- DATETIME: 시간대 변환 없음, 범위 1000~9999
-- 권장: DATETIME + 애플리케이션에서 UTC 처리
CREATE TABLE events (
created_at DATETIME NOT NULL DEFAULT (UTC_TIMESTAMP())
);
SQLite
-- SQLite는 네이티브 datetime 타입 없음
-- ISO 8601 텍스트로 저장 권장: "2024-03-01T14:00:00Z"
CREATE TABLE events (
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
현지 시간 저장의 DST 문제
뉴욕 현지 시간을 저장하다가 11월 DST가 종료되면 어떻게 될까요? 오전 2시에 시계가 오전 1시로 되돌아갑니다. 오전 1시 30분에 이벤트가 있다면 이제 오전 1시 30분 이벤트가 두 개가 됩니다 — 어느 것이 먼저일까요? UTC는 항상 앞으로만 이동하므로 이 문제를 완전히 피할 수 있습니다.
저장된 UTC를 사용자에게 표시하기
-- PostgreSQL: 쿼리 시 특정 시간대로 변환
SELECT
created_at AT TIME ZONE 'Asia/Seoul' AS created_at_seoul
FROM events;
-- 세션 시간대 설정
SET timezone = 'Asia/Seoul';
SELECT created_at FROM events; -- 출력 시 자동 변환
마이그레이션: 현지 시간 → UTC
-- PostgreSQL: 기존 현지 시간 컬럼을 UTC로 변환
UPDATE events
SET created_at = created_at AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC';
-- 컬럼 타입 변경
ALTER TABLE events ALTER COLUMN created_at TYPE TIMESTAMPTZ;