자바스크립트의 시간 문제를 해결한 9년의 여정, Temporal
(bloomberg.github.io)- 자바스크립트의 Date 객체 한계를 근본적으로 대체하는 새로운 표준 Temporal API가 9년간의 개발 끝에 ECMAScript Stage 4에 도달
- Temporal은 불변(immutable) 타입, 명시적 시간대·달력 지원, 나노초 단위 정밀도를 제공하며, 기존 Date의 모호성과 오류를 제거
-
Bloomberg, Igalia, Microsoft, Google, Mozilla 등 다양한 기관이 협력해 사양 설계와 구현을 진행, Rust 기반 공용 라이브러리
temporal_rs로 다중 엔진 협업을 실현 - Temporal은 ZonedDateTime, Instant, PlainDate/Time, Duration 등 세분화된 타입을 통해 시간 연산과 국제화 달력 처리를 정확히 지원
- 30년간의 문제를 해결한 이 표준은 자바스크립트 생태계의 협업과 개방형 혁신의 성공 사례로 평가됨
자바스크립트의 시간 처리 문제와 Temporal의 등장
- 기존 Date 객체는 1995년 Java의 Date를 그대로 포팅한 것으로, 가변성, 불일치한 월 계산, 모호한 파싱 등으로 수십 년간 버그의 원인이 되어 왔음
- 예:
setMonth사용 시 월말 계산 오류, ISO 유사 문자열 파싱 시 브라우저별 결과 불일치
- 예:
- 2010년대 이후 웹 애플리케이션이 복잡해지면서 Date의 한계가 심화됨
- 개발자들은 Moment.js 등 외부 라이브러리로 문제를 보완했으나, 번들 크기 증가와 유지보수 부담이 발생
- 2017년 Maggie Johnson-Pint가 TC39에 Temporal 제안을 제출하며 표준화 논의가 시작됨
TC39와 산업계의 협업
- Temporal은 2018년 Stage 1에서 출발해 9년에 걸쳐 Stage 4(표준화) 에 도달
-
Bloomberg는 대규모 자바스크립트 환경에서의 시간대·정밀도 문제 해결을 위해 적극 참여
- 요구사항: 사용자 지정 시간대, IANA 기반 역사적 시간대 정확성, 나노초 단위 정밀도
- Igalia, Microsoft, Google, Mozilla 등과 협력하여 사양 설계 및 구현을 진행
- Philipp Dunkel, Ujjwal Sharma, Philip Chimento, Shane Carr, Justin Grant 등 여러 엔지니어가 챔피언으로 참여
Temporal의 주요 타입과 기능
-
Temporal.ZonedDateTime: 명시적 시간대·달력·DST 보정이 포함된 불변 시각 표현
- 예: 런던 DST 전환 시
01:30이 존재하지 않으면 자동으로02:30으로 보정
- 예: 런던 DST 전환 시
-
Temporal.Instant: 시간대·달력 없는 절대 시점 표현, 나노초 단위 정밀도 지원
- 동일 시점을 여러 시간대로 변환 가능
-
PlainDate / PlainTime / PlainDateTime / PlainYearMonth / PlainMonthDay: 시간대 없는 ‘벽시계형’ 타입
- 단순 날짜·시간 표시나 계산에 적합
-
Temporal.Duration: 시간 간격 표현, 다양한 단위 변환 가능 (
total({ unit: "second" })) - 캘린더 지원: 히브리력 등 비그레고리력 연산을 정확히 수행
구현과 표준화 과정
- Temporal은 ECMAScript 역사상 가장 큰 사양 추가로, 약 4,500개의 테스트 케이스를 포함
-
Rust 기반 공용 구현체
temporal_rs가 개발되어 V8, Boa 등 여러 엔진이 공동 사용- 장점: 진입 장벽 감소, 장기 유지보수 용이, 코드 품질 향상
- 2024~2025년 동안
temporal_rs가 100% 테스트 통과, 다중 엔진 협업의 성공 사례로 평가됨
지원 현황과 향후 과제
- Temporal은 이미 Firefox 139, Chrome/Edge 144, TypeScript 6.0 Beta에서 지원
- Safari는 기술 프리뷰 단계, Node.js 26은 예정
- 향후 과제는 웹 API와의 통합
- 예:
<input type="date">등 폼 요소에서Temporal타입 지원 -
DOMHighResTimeStamp대체 가능성 검토 (Temporal.Now.instant()활용 예시 제시)
- 예:
협업과 개방형 혁신의 성과
- Temporal은 9년간의 다기관 협업을 통해 완성된 표준으로,
- Microsoft, Google, Mozilla, Bloomberg, Igalia, Boa 등 다양한 주체가 참여
-
temporal_rs는 공유 인프라 모델의 성공 사례로,- 중복 구현 비용 절감, 일관성 향상, 혁신 가속화를 입증
- Temporal은 단순한 API 개선을 넘어, 자바스크립트 커뮤니티가 장기적 기술 부채를 해결한 협력의 증거로 평가됨
- 30년 만에 자바스크립트는 현대적 날짜·시간 API를 갖추게 되었음
Hacker News 의견들
- Temporal이 시간 관리의 복잡성을 제대로 다루도록 강제하는 점이 정말 마음에 듦
순간(instant)과 달력 기반 datetime의 구분 덕분에 Date에서 흔히 생기던 실수를 거의 방지할 수 있음
약간 장황하긴 하지만, 새벽 3시에 DST 버그를 고치러 불려 나가는 것보단 훨씬 나음- 기술적으로 말하자면, 새벽 3시에 DST 버그를 고칠 일은 일요일 외에는 거의 없을 것 같음
- 나도 Python에서 ISO8601 날짜 파싱 문제로 거의 10년간의 고생을 했음
2012년에 시작된 이슈가 결국 표준 라이브러리에 해결책으로 들어감
관련 토론은 이 Google Groups 스레드에서 볼 수 있음- 진심으로 감사함. fromisoformat 외의 방식으로 날짜를 파싱하는 건 이제 너무 비직관적으로 느껴짐
예전엔 ciso8601을 썼지만, 표준에 들어온 이후로는 훨씬 단순하고 안정적임
- 진심으로 감사함. fromisoformat 외의 방식으로 날짜를 파싱하는 건 이제 너무 비직관적으로 느껴짐
- Firefox가 Temporal을 스펙 단계에서 구현할 수 있었던 건 André Bargull(Anba)의 덕분인데,
그가 사실 자원봉사자로 혼자서 전부 구현했다는 점이 특히 인상적임 - Temporal은 큰 진전이지만, 여전히 API가 마음에 들지 않음
나는 클라이언트와 서버 간에 코드를 공유하기 때문에 데이터와 로직을 엄격히 분리하려 함
모든 데이터를 순수 JSON으로 유지해 직렬화/역직렬화를 쉽게 하고 싶은데, Temporal 객체는 함수 속성을 가진 클래스 인스턴스라 불편함
date-fns처럼 데이터 전용 객체에 순수 함수를 적용하는 방식이 더 좋다고 생각함- 이건 의도된 설계임. Temporal 타입들은 직렬화 가능하지만, JSON.parse로 자동 복원이 되지 않음
개발자가 직접 ISO 문자열에서 올바른 객체를 재구성해야 함
자동화하면 잘못된 타입을 다루는 위험이 있음
문서의 Temporal.Instant reviver 예시가 참고될 만함 - 나도 같은 문제를 자주 겪음. JSON.parse/stringify로 프로토타입이 사라지는 건 흔한 이슈임
하지만 Temporal 팀의 선택이 옳다고 봄. 날짜·시간 로직은 단순 데이터+함수 접근보다 타입 안정성이 중요함
객체에 연산을 묶으면 PlainDate가 실수로 ZonedDateTime으로 처리되는 걸 방지할 수 있음
tRPC 같은 곳에서는 Temporal.from()과 toString()을 경계에서 변환하는 얇은 레이어만 추가하면 충분함
약간 번거롭지만, 타입 안정성을 포기하는 것보단 낫다고 생각함 - 사실 JavaScript의 Date 인스턴스도 같은 문제를 가짐
Date.toJSON은 있지만, JSON 파싱 시 문자열을 다시 Date로 변환해야 함
Temporal도 마찬가지고, date-fns도 결국 네이티브 Date 인스턴스를 다룸 - 모든 Temporal 객체는
.toString()과Temporal.from()으로 쉽게 직렬화/역직렬화 가능함 - JSON.parse가 자동으로 Temporal 객체를 생성하도록 바꾸는 건 과도한 접근이라고 생각함
Date와 마찬가지로
이런 식으로 명시적으로 처리하는 게 맞음serialize: instant.toJSON() deserialize: Temporal.Instant.from(jsonDate)
- 이건 의도된 설계임. Temporal 타입들은 직렬화 가능하지만, JSON.parse로 자동 복원이 되지 않음
- Temporal이 승인되어 정말 기쁨
오랫동안 노력한 모든 챔피언들에게 축하를 보냄
지난 몇 년간 temporal_rs 작업을 하며 즐거웠음 - Java의 시간 API 개선 여정(Joda-Time → JSR 310 → Java 8)을 함께 언급했으면 흥미로웠을 것 같음
JavaScript의 급진적 제안이 2018년에 나왔으니, Java의 접근이 어느 정도 영향을 줬을지도 궁금함- Joda가 Moment.js에 영향을 주고, 그게 다시 TC39 논의에 반영된 것으로 보는 게 맞음
TC39는 다른 언어의 선례를 참고하되, JavaScript에 최적화된 방향으로 합의를 이룸
이번 API는 9년에 걸쳐 JS 전문가들이 설계한 가장 완성도 높은 구현이라고 생각함 - 맞음, JavaScript도 Java에서 나쁜 버전의 Date를 가져왔었음
관련 내용은 이 HN 스레드에서도 볼 수 있음
- Joda가 Moment.js에 영향을 주고, 그게 다시 TC39 논의에 반영된 것으로 보는 게 맞음
- “Mocha 시절 Ken Smith가 Java의 Date 코드를 C로 포팅했다”는 말이 재밌음
왜냐면 Java의 util.Date 자체가 거의 C의 time.h API 포트였기 때문임 - Safari가 Temporal을 부분 지원한다는 걸 보고 웃음이 나왔음
이제 Safari가 IE의 정신적 후계자가 된 듯함- Safari는 새 기능 도입이 느리지만, 그래도 꾸준히 구현 중임
IE의 문제는 느림이 아니라, 지배적 위치에서 멈췄던 것이었음
지금은 Chrome이 제국의 자리에 있고, 오히려 Safari와 Firefox가 더 필요함
Chrome 전용 사이트가 늘어나는 게 진짜 문제임 - 2026년이 되어도 모바일 Safari에 네이티브 날짜 선택기가 없을 것 같음
- Safari는 새 기능 도입이 느리지만, 그래도 꾸준히 구현 중임
- Temporal에 interval 타입이 있었으면 좋겠음
const D = new Temporal() const t = new Interval({minutes:5}) const v = D.add(t)- 그건 Duration임
MDN 문서 참고const D = Temporal.PlainDate.from("2020-06-16"); const t = Temporal.Duration.from({ day: 1 }); const v = D.add(t) // 2020-06-17 - 맞음, 그건 Duration이라고 부름
- 그건 Duration임
- 이걸 위해 9년 동안 1배속으로 시간 여행을 해준 팀에 감사함