AZ Tools
← 가이드

버그 없이 시간대와 Unix 타임스탬프 다루기

날짜와 시간은 유독 많은 버그를 일으킵니다. 사람에게 당연해 보이는 것이 컴퓨터에겐 정말로 복잡하기 때문입니다: 시간대는 바뀌고, 시계는 한 해에 두 번 한 시간을 건너뛰며, '오늘'은 당신이 서 있는 곳에 달려 있습니다. 이 가이드는 핵심 개념을 설명하고, 대부분의 날짜 처리 실수를 막아 주는 몇 가지 규칙을 제시합니다.

시간은 절대 시점으로 저장하라

가장 중요한 단 하나의 규칙: 순간은 절대적이고 시간대에 무관한 시점으로 저장·전송하세요 — Unix 타임스탬프(1970년 1월 1일 UTC 이후의 초 또는 밀리초)나 UTC 기준 ISO 8601 문자열(끝에 Z)로요. 시점은 지구 어디서나 동일하며, 사람이 보는 표현만 달라집니다.

사람에게 값을 보여줄 때, 즉 맨 가장자리에서만 현지 시간대로 변환하세요. 시스템 내부는 UTC로 유지합니다. 가장 고통스러운 날짜 버그 대부분은 어느 시간대 기준인지 기록하지 않은 채 '현지' 시간을 저장해, 값을 영원히 모호하게 만드는 데서 옵니다.

UTC, 오프셋, 시간대는 같은 것이 아니다

UTC는 전역 기준 시계입니다. +09:00 같은 오프셋은 한 순간의 UTC로부터의 고정된 차이입니다. America/New_York 같은 시간대는, 역사상 매 시점에 어떤 오프셋이 적용되는지를 — 언제 바뀌는지를 포함해 — 기술하는 이름 붙은 규칙 집합입니다.

이 구분이 중요한 이유는 한 시간대 안에서도 오프셋이 바뀌기 때문입니다. 뉴욕은 겨울엔 -05:00, 여름엔 -04:00입니다. 오프셋만 저장하면 규칙을 잃어, 미래의 현지 시간을 올바르게 계산할 수 없습니다. '매일 뉴욕 시간 오전 9시'를 예약하려면 고정 오프셋이 아니라 시간대 이름이 필요한 이유입니다.

서머타임은 순진한 가정을 깨뜨린다

한 해에 두 번, 서머타임을 지키는 시간대는 점프합니다. 봄에는 한 시간을 건너뛰어, 그날 02:30 같은 현지 시간은 아예 존재하지 않습니다; 가을에는 한 시간이 반복되어 01:30이 두 번 일어나 모호해집니다. 매일이 24시간이라고, 또는 주어진 현지 시간이 항상 존재한다고 가정하는 코드는 결국 잘못된 결과를 내거나 죽습니다.

UTC로 작업하면 이를 통째로 비껴갑니다. UTC엔 서머타임이 없기 때문입니다. 표시를 위해 현지 시간으로 변환하거나 사람의 입력을 해석할 때만 그 틈과 겹침을 마주하는데 — 바로 거기서 직접 만든 산술 대신 검증된 날짜 라이브러리가 일을 해야 합니다.

초, 밀리초, 그리고 2038년

Unix 타임스탬프는 흔히 두 단위로 오며 섞어 쓰는 것이 잦은 버그입니다: 대부분의 Unix 도구와 API는 초를, JavaScript의 Date는 밀리초를 씁니다. 1000배 어긋난 값은 보통 단위를 혼동했다는 뜻입니다 — 타임스탬프가 갑자기 56000년이거나 1970년으로 돌아가 있죠.

크기 한계도 있습니다: 부호 있는 32비트 정수로 저장된 Unix 시간은 2038년 1월 19일에 오버플로합니다. 현대 시스템은 64비트 값을 써서 실용적으로는 문제를 없앴지만, 오래된 시스템이 먼 미래 날짜를 왜 잘못 다루는지 알아 둘 가치가 있습니다.

대부분의 버그를 막는 규칙

이 중 어느 것도 일상적으로 깊은 전문성을 요구하지 않습니다 — 몇 가지 습관이 거의 모든 경우를 덮습니다.

  • 시점은 UTC로 저장·교환하세요(Unix 타임스탬프 또는 Z가 붙은 ISO 8601); 표시할 때만 현지로 변환.
  • 미래의 현지 시간이 중요하면 IANA 시간대 이름(예: Europe/Paris)을 유지하세요; 오프셋만으론 부족합니다.
  • '하루'나 '한 달'을 위해 고정된 초를 더하는 식의 달력 계산을 하지 마세요 — 서머타임과 달의 길이를 아는 날짜 라이브러리를 쓰세요.
  • 모든 경계에서 초인지 밀리초인지 명확히 하고, 어느 쪽인지 표시하세요.

관련 도구