VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
DATETIME 대 TIMESTAMP
이 두 타입은 비슷해 보이지만 결정적인 순간 — 조회 — 에 다르게 동작합니다.TIMESTAMP는 값을 자동으로 변환합니다:
- INSERT/UPDATE 시: 저장을 위해 세션
time_zone에서 UTC로 변환 - SELECT 시: 표시를 위해 UTC에서 다시 세션
time_zone으로 변환
DATETIME은 아무 변환도 하지 않습니다. 써넣은 값이 그대로 돌아옵니다.
'America/New_York' 같은 이름 있는 시간대는 시간대 테이블이 로드되어 있어야 합니다(아래 이름 있는 시간대를 보세요) — 새로 초기화한 서버에는 그 테이블이 없습니다. 아래 예를 실행하기 전에 SELECT COUNT(*) FROM mysql.time_zone_name;으로 확인하세요; 0이면 먼저 로드하거나 '-05:00' 같은 숫자 오프셋으로 대체하세요.
2038년 문제
TIMESTAMP는 32비트 Unix 타임스탬프로 저장됩니다. 2038-01-19 03:14:07 UTC 이후의 날짜는 표현할 수 없습니다. 미래 날짜를 저장하는 모든 애플리케이션 — 예약, 구독, 예정된 이벤트 — 은 이 한계에 부딪히지 않도록 DATETIME을 사용해야 합니다.
서버 시간대와 세션 시간대
MySQL에는 서로 독립적인 2개의 시간대 설정이 있습니다:time_zone이 SYSTEM으로 보이면 MySQL은 운영 체제의 시간대를 사용하고 있습니다. 이것은 OS가 바뀔 때까지(서버 이전, DST 전환) 동작합니다 — 그다음에는 타임스탬프가 어긋납니다.
모범 사례: 서버를 명시적으로 UTC로 설정하고, 표시 변환은 애플리케이션에서 처리하세요.
이름 있는 시간대
'+00:00'과 'UTC'는 둘 다 유효하지만, 'America/New_York' 같은 이름 있는 시간대는 시간대 테이블이 로드되어 있어야 합니다. CONVERT_TZ()가 NULL을 반환하거나 이름 있는 시간대가 실패하면 테이블이 없는 것입니다.
AUTO_UPDATE 열
TIMESTAMP 열은 삽입과 갱신 시 자동 채우기를 지원합니다:
CURRENT_TIMESTAMP는 UTC로 평가되므로, 누가 어느 시간대에서 연결하든 created_at과 updated_at은 일관되게 저장됩니다.
DATETIME과 NOW()로도 같은 일을 할 수 있습니다:
NOW()는 세션 시간대의 현재 날짜와 시간을 반환합니다 — 세션을 UTC로 통일해야 하는 또 하나의 이유입니다.
자주 묻는 질문
타임스탬프를 DATETIME에 UTC로 저장해야 하나요, TIMESTAMP를 써야 하나요?
날짜가 2038년 상한 안에 머문다면TIMESTAMP가 더 깔끔합니다 — UTC 변환을 자동으로 처리합니다. 2038년 이후의 미래 날짜나 1970년 이전의 과거 날짜를 저장해야 하는 애플리케이션에서는 DATETIME을 사용하고, 삽입 전에 항상 UTC로 변환해서 애플리케이션 계층에서 UTC를 강제하세요.
서버 이전 후 타임스탬프가 어긋나는 이유는 무엇인가요?
이전 서버는 한 OS 시간대를 가리키는time_zone = SYSTEM을 사용했고, 새 서버는 다른 시간대(또는 UTC)를 가리킵니다. UTC로 저장된 TIMESTAMP 값은 두 시간대 모두에서 올바르게 표시되지만, UTC가 아니라 시스템 시간대를 가정하고 저장된 값이 있다면 어긋납니다. 이전하기 전에 두 서버 모두에서 SELECT @@global.time_zone으로 점검하세요.
시간 부분 없이 날짜만 저장하려면 어떻게 하나요?
DATE를 사용하세요. 3바이트로 저장되고, 시각이나 시간대의 모호함이 없습니다. WHERE date_col = '2024-03-15' 같은 연산은 세션 시간대와 관계없이 모호하지 않습니다.
문제 해결
함께 보기
- MySQL 날짜와 시간 함수 — DATETIME과 TIMESTAMP 값을 다루는 함수