

JS/TS에서 다른 시간대(Europe/London)를 가져와서 서울 시간대(Asia/Seoul)로 변환하기
JS/TS에서 다른 시간대(Europe/London)를 가져와서 서울 시간대(Asia/Seoul)로 변환하는 방법을 소개합니다.
배경#
JS, NodeJS 에서는 기본 Date 객체가 존재합니다. 그리고 TimeZone 역시 존재합니다.
하지만 특정 TimeZone 으로 만들어진 시간을 가지고, UTC 시간대나 다른 TimeZone 으로 변환할때 문제가 발생할 수 있습니다. 기본 Date 객체는 항상 UTC 시간으로 인식하기 때문에 원하는 시간대라고 지정할 수 없습니다.
예를 들어서 유럽 이탈리아 로마에서 휴가 중 글을 작성할때 아래와 같은 문제가 발생할 수 있습니다.
- 글은 유럽 이탈리아, 로마 시간 기준으로 “2025-03-02 04:38:36” 에 작성
- 현지시간으로 작성자가 알아보기 쉽게 Europe/Rome TimeZone 과 함께 Rime Time 으로 생성
post.frontmatter.date = '2025-03-02 04:38:36';
post.frontmatter.tz = 'Europe/Rome';
js이때 한국에서 누군가가 제 글을 보게 된다면…?
Intl.DateTimeFormat
등을 이용하려고 해도 문자로 세겨진 시간을 가지고 특정 TimeZone 의 시간대로 생성할 수 없습니다.
new Date('2025-03-02 04:38:36')
처럼 Date 객체를 생성하는 순간 UTC 시간대로 만들어집니다.
결국 제가 작성했던 Europe/Rome
시간대로 시간을 만들어낼 수 가 없었습니다.
해결방법#
아에 해결할 수 없는 것은 또 아닙니다.
Moment(지금은 관리되고 있지 않음), Luxon ↗, 그리고 곧 Date 객체를 대체하게 될 Temporal ↗ 을 사용하면 원하는 결과를 얻을 수 있습니다.
Luxon 사용#
import { DateTime } from 'luxon';
// ✅ "Europe/Rome" 에서 생성된 시간
const romeDate = '2025-03-02 04:38:36';
const romeTimeZone = 'Europe/Rome';
// Rome 시간대의 Luxon DateTime 객체 생성
const romeDateTime = DateTime.fromFormat(romeDate, 'yyyy-MM-dd HH:mm:ss', { zone: romeTimeZone });
// ✅ 현재 브라우저(Local) 타임존 (ex. "Asia/Seoul")
// `Intl.DateTimeFormat().resolvedOptions().timeZone;` 과 같은 역할을 함
const currentTimeZone = DateTime.local().zoneName;
// 현재 브라우저 시간대로 변환 (ex. Asia/Seoul)
// Asia/Seoul 에서 확인하면, 정상적인 '2025-03-02 12:38:36' 으로 확인됨
romeDateTime.setZone(currentTimeZone);
jsTemporal 사용#
[Temporal](https://github.com/tc39/proposal-temporal)
은 아직 ECMAScript 표준화 과정 중 Stage3 ↗ 상태입니다.
그래서 NodeJS 와 Browser 에서 사용하려면, Polyfill(@js-temporal/polyfill) ↗ 이 필요합니다.
NodeJS 20+ 에서만 사용하면, --experimental-temporal
플래그만으로도 사용할 수 있기도 합니다.
import { Temporal } from '@js-temporal/polyfill';
// ✅ "Europe/Rome" 에서 생성된 시간
const romeDate = '2025-03-02 04:38:36';
const romeTimeZone = Temporal.TimeZone.from('Europe/Rome');
// Rome 시간대로 ZonedDateTime 변환/생성
const romeDateTime = Temporal.PlainDateTime.from(romeDate.replace(' ', 'T'));
const zonedRomeDateTime = romeDateTime.toZonedDateTime(romeTimeZone);
// ✅ 현재 브라우저(Local) 타임존 (ex. "Asia/Seoul")
// `Intl.DateTimeFormat().resolvedOptions().timeZone;` 과 같은 역할을 함
const currentTimeZone = Temporal.Now.timeZone();
// 현재 브라우저 시간대로 변환 (ex. Asia/Seoul)
// Asia/Seoul 에서 확인하면, 정상적인 '2025-03-02 12:38:36' 으로 확인됨
zonedRomeDateTime.withTimeZone(currentTimeZone);
jsLuxon vs Temporal#
현재 2025.03.02 KST 기준으로는 아래와 같은 이유들로 [Luxon](https://moment.github.io/luxon/index.html#/)
을 추천합니다.
- 즉시사용가능 :
Temporal
은 아직 Polyfill 이 필요함 - 안정적 : 이미 프로덕션 환경에서 많은 유저가 사용중임
- 간단함 :
DateTime.fromFormat
으로 ‘YYYY-MM-DD HH:mm:ss’ 형식을 바로 처리 가능함)
비교 항목 | Temporal Polyfill (@js-temporal/polyfill) | Luxon |
---|---|---|
표준 여부 | ⏳ 미래의 ECMAScript 표준 (ES 규격 예정) | ❌ 표준 아님 (사설 라이브러리) |
시간대 지원 | ✅ IANA 시간대 지원 (America/New_York, Asia/Seoul 등) | ✅ IANA 시간대 지원 |
DST(서머타임) 처리 | ✅ 자동 처리 | ✅ 자동 처리 |
브라우저 지원 | ❌ Polyfill 필요, Node.js 20+ 지원 | ✅ 모든 브라우저 & Node.js 지원 |
성능 | ✅ 빠름 (ECMAScript 내부 표준 설계) | ⏳ 상대적으로 무거움 |
ISO 8601 지원 | ✅ 기본 지원 (toString() 등) | ✅ 기본 지원 |
학습 난이도 | ⏳ 기존 Date와 다름 (새로운 API 학습 필요) | ✅ DateTime.fromISO() 등 직관적 |
유지보수 가능성 | ✅ 장기적으로 안정적 (ECMA 표준화 예정) | ⏳ Temporal 표준화되면 사용량 줄어들 가능성 |
추가 의존성 | ✅ 단일 Polyfill (@js-temporal/polyfill) | ⏳ 여러 유틸 포함 (~60KB) |
상태 (2025.03.02기준) | 실험적 (Stage 3) | 안정적 |
Temporal 도입을 추천할 시기…?!#
[Temporal](https://github.com/tc39/proposal-temporal)
이 Stage 4에 도달하고 브라우저에 기본 탑재가 되면 의존성 없이 바로 사용할 수 있습니다.
그 시기는 대략 2025년 말로 예상하고 있습니다.