JavaScript Temporal API: Date의 현대적 대체
JavaScript Date는 수십 년 동안 잘 알려진 방식으로 망가져 있었습니다. TC39 Temporal — 2025년 초부터 Stage 4, 현대 브라우저와 Node.js에 탑재 — 은 순간, 벽시계 날짜, 시간대가 붙은 날짜·시각을 깔끔하게 분리합니다. 이 가이드는 새로운 타입, 그것들이 Unix 타임스탬프에 어떻게 대응하는지, 그리고 마이그레이션 방법을 설명합니다.
한눈에 보는 Temporal vs Date
JavaScript의 내장 Date는 수십 년간 알려진 버그의 원천이었습니다. 가변적이고, 로컬 시간대와 UTC만 이해하며, 월이 0부터 인덱싱되고, 파싱이 느슨하게 명세되어 있습니다. Temporal은 표준화된 대체 — Stage 4이며 ECMAScript 2026의 일부 — 로, 이 문제들 각각을 목적에 맞게 만든 불변 타입으로 고칩니다. 아래 표는 큰 틀의 대비입니다; 이 가이드의 나머지는 타입과 그것들이 Unix 타임스탬프에 어떻게 대응하는지를 다룹니다.
| 측면 | Date(레거시) | Temporal |
|---|---|---|
| 가변성 | 가변 | 불변 |
| 정밀도 | 밀리초 | 나노초 |
| 시간대 | 로컬 + UTC만 | 모든 IANA 시간대(ZonedDateTime) |
| 월 인덱싱 | 0 기반(0 = 1월) | 1 기반(1 = 1월) |
| 파싱 | 관대함, 구현 정의 | 엄격한 ISO 8601 / RFC 9557 |
| 순간 vs 벽시계 | 한 타입에 혼재 | 분리된 타입 |
왜 Temporal이 존재하는가
JavaScript Date는 여러 별개 개념을 혼동합니다: 정확한 순간, 벽시계 시각, 시간대가 붙은 날짜·시각. Date에는 또한 잘 알려진 파싱 특이점, 단일 시간대(사용자의 것), 밀리초 정밀도가 있습니다. Temporal은 기저 개념을 별개의 타입으로 노출하고, 나노초 정밀도, 임의의 IANA 시간대, 명시적 달력 체계를 지원합니다.
- 2025년 초부터 Stage 4; Firefox 139에서 처음 기본 탑재
- 현재 Chrome 144+, Firefox 139+, Node.js 26+에서 사용 가능
- 폴리필(@js-temporal/polyfill)은 모든 현대 환경에서 동작
- Date와 공존하도록 설계 — 양방향 상호 운용 메서드가 존재
Temporal의 핵심 타입
작은 타입 집합이 날짜·시각 문제를 깔끔하게 다룹니다. 각각은 정규 문자열 형식을 가집니다(ISO 8601, 시간대 타입은 RFC 9557로 확장):
| 타입 | 나타내는 것 | 예시 문자열 |
|---|---|---|
| Temporal.Instant | Unix 타임스탬프 같은 정확한 순간(ns 정밀도) | 2026-01-01T00:00:00Z |
| Temporal.ZonedDateTime | 순간 + IANA 시간대 + 달력 | 2026-01-01T09:00:00+09:00[Asia/Tokyo] |
| Temporal.PlainDateTime | 날짜 + 시각, 시간대 없음 | 2026-01-01T09:00:00 |
| Temporal.PlainDate | 달력 날짜(예: 생일) | 2026-01-01 |
| Temporal.PlainTime | 벽시계 시각 | 09:00:00 |
| Temporal.Duration | 단위를 아는 기간 | P3DT4H10M |
Unix 타임스탬프 다루기
Temporal.Instant이 Unix 타임스탬프 타입입니다. 탑재된 API는 밀리초와 나노초 epoch 변환만 노출합니다 — 이전의 fromEpochSeconds와 fromEpochMicroseconds 메서드는 Stage 4 전에 제거되었습니다 — 그러니 Unix 초는 1000을 곱해 변환하세요. 저장과 전송에는 Instant를, 특정 시간대의 벽시계 뷰가 필요할 때는 ZonedDateTime을 쓰세요.
- Temporal.Now.instant() — 현재의 정확한 순간
- Temporal.Instant.fromEpochMilliseconds(Date.now()) — JS 밀리초 타임스탬프에서
- Temporal.Instant.fromEpochMilliseconds(1700000000 * 1000) — Unix 초에서(× 1000)
- Temporal.Instant.fromEpochNanoseconds(1700000000000000000n) — 나노초에서(BigInt)
- instant.epochMilliseconds와 instant.epochNanoseconds — epoch 값을 도로 읽기
- instant.toZonedDateTimeISO("America/New_York") — 어떤 시간대의 벽시계 뷰
시간대와 DST를 올바르게 처리
ZonedDateTime은 IANA 시간대를 지니므로 DST 전환, 공백 시각, 중복 시각이 모두 명시적으로 처리됩니다. 모호성 해소 옵션으로 모호한 현지 시각에 대한 정책을 고를 수 있고, 정규 문자열 형식은 RFC 9557(시간대를 대괄호로 붙인 ISO 8601 타임스탬프)입니다.
- zdt.timeZoneId — IANA 이름(예: America/Los_Angeles)
- zdt.add({ hours: 1 }) — 벽시계 관점의 DST 인식 산술
- zdt.until(zdt2) — 두 시간대 날짜·시각 사이의 거리
- 모호성 해소 옵션: "earlier", "later", "compatible"(기본값 — 공백은 이후, 중복은 이전), "reject"
- 왕복: instant ↔ 시간대 날짜·시각은 무손실
Date에서의 마이그레이션 패턴
가장 간단한 마이그레이션 전략은 먼저 경계(입력 파싱, 출력 포매팅)에서 Temporal을 도입하고 내부 로직을 점진적으로 옮기는 것입니다.
- Date → Instant: Temporal.Instant.fromEpochMilliseconds(date.getTime())
- Instant → Date: new Date(instant.epochMilliseconds)
- 새 코드는 어디서나 Temporal을 선호하고 API 가장자리에서만 Date로 변환하라
- date-fns와 Luxon은 둘 다 Temporal 인식 모드/어댑터를 가진다
- JSON: Temporal.Instant.prototype.toJSON은 ISO 8601 문자열을 반환한다
브라우저와 런타임 지원
Temporal은 2025년에 탑재되었고 네이티브 지원은 이제 넓지만 아직 보편적이지는 않습니다. 오래된 브라우저와 Safari 안정판이 아직 쓰이는 동안은 폴리필이 가장 안전한 길입니다.
- Firefox 139+: 처음 탑재, 기본 활성화(2025년 5월)
- Chrome 144+: 기본 활성화(2026년 1월)
- Node.js 26+: 기본 활성화(2026년 5월)
- Safari: Technology Preview에서 사용 가능, 아직 안정판에는 미탑재
- 폴리필: @js-temporal/polyfill 또는 temporal-polyfill — 동일한 API, 모든 현대 환경
관련 참고
FAQ
- Temporal은 Date의 대체인가요?
- 네 — Temporal은 새 코드에서 Date를 완전히 대체하도록 설계되었습니다. Date는 하위 호환성을 위해 언어에 남아 있고, 둘은 epoch 밀리초를 통해 상호 운용됩니다.
- Unix 타임스탬프를 Temporal로 어떻게 변환하나요?
- Temporal.Instant.fromEpochMilliseconds()를 쓰세요. Unix 초는 1000을 곱합니다: Temporal.Instant.fromEpochMilliseconds(seconds * 1000). 탑재된 API에는 fromEpochMilliseconds와 fromEpochNanoseconds만 있습니다 — 더 오래된 fromEpochSeconds 메서드는 Temporal이 Stage 4에 도달하기 전에 제거되었습니다.
- Temporal은 나노초를 지원하나요?
- 네. Temporal.Instant는 내부적으로 나노초 정밀도를 가지며 epochNanoseconds를 BigInt로 노출합니다.
- 오늘 Node.js에서 Temporal을 쓸 수 있나요?
- Node.js 26+에서는 Temporal이 기본으로 활성화됩니다. 더 오래된 Node에서는 @js-temporal/polyfill을 설치하세요 — API 표면은 동일합니다.
- 어떤 브라우저가 Temporal을 지원하나요?
- Firefox 139+(2025년 5월), Chrome 144+(2026년 1월), Node.js 26+(2026년 5월)이 Temporal을 기본 탑재합니다. Safari는 Technology Preview에 있습니다. 더 오래된 것에는 @js-temporal/polyfill을 쓰세요.
- Temporal은 DST 공백을 어떻게 처리하나요?
- ZonedDateTime 생성자와 산술은 모호성 해소 옵션을 받습니다. "compatible"(기본값)은 공백에는 이후 순간을, 중복에는 이전 순간을 고릅니다; "reject"는 현지 시각이 모호하면 오류를 던집니다.