한국 사람은 익숙하지 않은 썸머타임. 썸머타임이 있는 나라는 하루가 25시간이나 23시간일 때도 있다. 하루는 24시간인데 왜 들쑥날쑥하는 걸까?
전 세계의 다양한 시간대를 표시하는 방법으로 타임존이 있다. 브라우저는 타임존을 지원하기 위해 몇 가지 방법을 제공한다. 그러나 이 방법만으로는 우리의 웹 서비스가 전 세계 사용자들의 다양한 타임존을 만족시키는 어렵다.
이 글은 타임존이 필요한 이유와 역사를 알아보고 프런트에서 타임존을 지원하는 방법을 정리한다. 타임존, 개발자라면 꼭 한 번은 부딪치게 마련이다. 이번 기회에 타임존을 확실히 알고 가자.
지구에서 시간은 절대적인 시간이다. 뭔가 어벤저스의 타임스톤 이야기가 나올 것 같지만, 시간은 하나밖에 없다고 생각하면 된다. 그런데 한국과 미국, 영국 등의 시간은 다르다. 왜 그럴까? 11살 난 아들에게 타임존의 개념을 다음과 같이 설명했다. "아들아, 왜냐하면 지역 별로 낮과 밤의 시각이 다르기 때문이야. 영국은 아침 출근 시각이 9시인데, 우리는 아침 출근 시각이 18시이면 이상하지 않겠니? 그래서 각 지역별로 (진짜 해가 밝은)아침 9시 출근으로 맞추려면 시간대가 여러 개 생길 수 밖에 없었어."
지구의 자전에 따라서 지역 별로 생기는 낮과 밤의 차이를 인위적으로 지정하기 위해 고안된 시간의 구분선이 바로 타임존이다. 영국이 아침 9시에 출근하고, 우리도 아침 9시에 출근하려면 우리나라의 시간을 영국보다 9시간이 더 빠르게 조정해 버리면 된다. 그래서 한국 시간이 +09:00
이라고 이야기하는 것이다. 영국 그리니치 타임(GMT)가 +00:00으로 기준점이 되고 법이 1675년부터 제정되었다니 이미 그 역사가 길다.
그런데 말입니다. 타임존은 고정이 아니다. 실제로 타임존은 지역별 차이를 인위적으로 조정할 수 있기 때문에 지역의 특수성에 따라 역사적으로 변경되어 왔다. 경도에 따라서 +1시간, -6시간 등으로 고정시켜두면 깔끔할텐데 왜 그랬까? 굳이 바꿀 이유도 없을 것 같은데 말이다.
타임존을 진짜 정확하게 보자면 경도에 따라서 시간대가 같은 곳이 하나도 없다. 서울과 강릉도 시간대가 달라질 수 있다. 그래서 국가 혹은 지역을 구분해서 대략적인 시간대를 통일하게 된다. 그러나 나라마다 지역마다 역사적인 이유, 정치적인 이유 때로는 경제적인 이익 등의 이유로 타임존은 계속 바뀌었다.
네덜란드의 경우 +00:19:32.13이라는 정확한 오프셋을 사용하다가 결국 +01:00이라는 기준으로 통일해서 사용하도록 변경이 되었다.
우리나라 땅은 가로 너비가 좁다. 시간대를 매우 정확하게 나누지 않더라도 불편함이 없다. 그러면 넓은 땅을 가진 중국은 어떨까? 중국도 우리나라처럼 하나만 쓸까 아니면 나라 안에서 지역을 구분해서 타임존을 구분할까? 정답은 하나만 쓴다다. 중국은 그 넓은 면적에도 불구하고 하나의 타임존을 사용하고 있다. 그래서 중국 서쪽 지역에는 오전 10시는 되어야 해가 뜨는 것을 볼 수 있다.
반면에 땅이 넓은 미국은 한 나라 안에서 타임존을 몇 개로 나누어서 쓰고 있다. 같은 나라라도 미국 서부 지역과 동부 지역은 3시간 차이나는 것을 알 수 있다.
(출처: 나무위키 타임존)
사모아의 경우는 -10:00의 시간대를 사용했다가 무역 상대국인 오스트레일리아, 뉴질랜드와의 거래에서 날짜 차이에 따른 손실을 줄이기 위해서 +14:00로 변경하면서 하루를 앞당겼다. 그래서 2011년 12월 30일이 사라져서 생일을 맞이할 수 없는 사람이 생겨나기도 했다는 웃픈 일이 있다.
나라 및 지역마다 다른 것이 타임존이라고 했다. 그런데 이 타임존은 경도에 따라 절대 바뀌지 않는 시간 오프셋을 지정하는 다른 표현이다. 그래서 타임존이라는 말은 어떤 오프셋을 쓸 것인가를 정하는 일종의 alias같은 역할을 한다. 또한 타임존은 하나의 오프셋을 가지는 것이 아니라 여러 개의 오프셋을 가질 수도 있다. 대표적으로 썸머타임이다.
썸머타임은 같은 타임존을 사용하는 지역에서 두 개의 오프셋을 사용한다. 겨울 동안에 미국 서부 쪽은 태평양 표준시 즉 PST(Pacific Standard Time)를 사용한다. 그리고 3월부터 11월까지는 썸머타임이 적용되어서 태평양 연안 표준시, PDT(Pacific Daylight Time)를 사용한다. 즉 3월부터 11월까지는 미국 서부에서 갑자기 1시간 앞당겨진 오프셋을 사용한다는 말이다. 썸머타임을 쓰는 이유는 해가 길어지면서 변경되는 낮과 밤의 시각을 임의로 조정하는 것이다.
필자처럼 한국에서 태어나서 유학도 한 번 안 가본 사람에게는 전혀 생소한 것이 바로 썸머타임이다. 해외여행을 다닐 때 "한국과 몇 시간이 차이 난다", "그러니까 여기는 밤이고 한국은 아침이야" 이런 말은 시차를 표현하는 말인데, 여름과 겨울에는 썸머타임 때문에 또 달라지니 뭔가 더 복잡하다고 느껴진다.
그러면 브라우저에서, 특히 자바스크립트에서 타임존을 지원하려면 어떻게 해야 할까? 다들 아는 것처럼 자바스크립트는 Date
라는 날짜를 표현하기 위한 타입이 있다. 브라우저는 ECMAScript 명세를 구현하고 있고 명세는 타임존과 썸머타임에 대해서도 정의가 되어 있다. 문제는 그 정의가 내용도 짧고 모호하다는 것이다. 브라우저가 최선을 다해서 정확하게 구현하기를 바란다는 정도로만 작성되어 있으니 브라우저 벤더들도 난감했을 거라고 짐작한다. 그래서 브라우저마다 Date
기능이 조금씩 다르게 동작한다. 또한 타임존을 변경하는 기능은 ECMAScript 명세에도 없다. 그래서인지 브라우저나 Node.js 등은 설치된 OS에 설정된 타임존을 따르도록 구현되어 있다. 즉 우리나라에 있는 컴퓨터의 브라우저에서 시간대는 Asia/Seoul로 될 것이고, 여기서 다른 나라의 타임존을 표시하기 위해 Date 객체를 쓰는 것만으로는 어려움이 있다. 만약 브라우저에서 다른 나라의 타임존으로 바꾸려면 OS설정에서 바꾸어야 하는 수 밖에 없을 것이다.
앞서 타임존은 여러 개 오프셋을 가질 수 있고, 필요에 따라 어떤 오프셋을 사용할지 바꿀 수 있다고 했다. 반면에 대한민국의 타임존 Asia/Seoul과 일본의 타임존 Asia/Tokyo는 타임존 이름은 다르지만 두 타임존 모두 +09:00을 오프셋으로 사용하는 경우도 있다. 그 외에도 나라 상황에 맞게 변경하는 등 역사적인 히스토리도 고려해야 하기 때문에 일정한 규칙(경도)에 따라서 프로그래밍적으로 타임존과 오프셋을 계산하기가 거의 불가능하다.
그래서 타임존은 데이터베이스를 기반으로 변경 내역을 관리해야 한다. 현재 가장 신뢰할 만한 표준 데이터베이스는 IANA Time Zone Database이다. Windows는 자체 데이터베이스로 관리하고 있지만 자바의 VM는 IANA 데이터베이스를 사용하며 정기적으로 업데이트하고 있다.
이 문제점이 바로 자바스크립트에서 각기 다른 타임존을 구현하기가 어려운 이유다. ECMAScript가 타임존에 대한 정의가 모호하고 또한 브라우저가 이 데이터베이스를 가지고 있지 않기 때문에 Date
타입만으로는 타임존을 변경할 수가 없다.
그렇다면 해결 방법은 무엇이 있을까? 크게 두 가지 방법이 있다. 아예 웹 페이지에서 타임존 데이터베이스를 내장하는 것과 ECMAScript에서 이런 문제를 해결하기 위해 추가된 명세 Intl.DateTimeFormat
을 사용하는 방법이다.
우리 서비스가 오래된 브라우저를 포함하여 다양한 브라우저를 지원해야 한다면 Intl.DateTimeFormat
이 없는 브라우저에서도 동작해야 한다. 이 경우는 타임존의 변경 내역을 모두 담고 있는 데이터베이스 파일을 내장하는 수 밖에 없다. 예를 들어 2020년 7월 3일 17:00가 다른 타임존에서는 시차가 얼마나 나는지 확인하기 위해서는 데이터베이스에서 조회해야 한다. 그 타임존이 썸머타임을 쓰는지 안 쓰는지, 지금이 썸머타임 적용 기간인지 아닌지를 모두 데이터베이스를 조회해야 오프셋을 계산할 수 있다.
moment.js는 다음과 같이 json 타입으로 데이터베이스에 타임존에 따른 오프셋을 정의하고 있다.
{
name : 'America/Los_Angeles', // the unique identifier
abbrs : ['PDT', 'PST'], // the abbreviations
untils : [1414918800000, 1425808800000], // the timestamps in milliseconds
offsets : [420, 480] // the offsets in minutes
}
출처: Zone object - https://momentjs.com/timezone/docs/
필자가 찾아본 라이브러리 중에서 moment.js와 js-joda 두 라이브러리가 타임존 데이터베이스를 모두 가지고 있다. 데이터베이스 용량이 크기 때문에 10년치 데이터나 전체 데이터 등으로 선택하여 용량을 줄이는 방법을 지원한다. 타임존 데이터베이스를 모두 가지고 있어야 하기 때문에 용량이 커서 그렇지 오래된 브라우저를 포함한 타임존 지원을 위해서는 아직까지는 대안이 없어 보인다.
자바스크립트의 Date
와 Intl.DateTimeFormat
으로는 타임존을 바꿀 수 있는 방법이 없지만, moment.js나 js-joda와 같은 라이브러리는 가능하기 때문에 글로벌 서비스에서 오래된 브라우저 지원과 타임존을 직접 구현해야 하는 어려움을 동시에 해결할 수 있는 방법이다.
지난주에는 수많은 개발자들이 애용하던 moment.js가 아쉽게도 더 이상 추가 개발을 하지 않고 유지관리만 하겠다고 발표했다. 아직도 많이 그리고 잘 쓰이고 있는 라이브러리를 더 이상 개발하지 않는다고 해서 의아할 수도 있겠다. 그러나 1년 안에 Internet Explorer의 지원도 끊길 것이므로 때가 되었다고 생각한다. 웹이 좀 더 적극적으로 레거시를 끊고 표준화된 방향으로 나아가기 위해서는 이런 영향력 있는 라이브러리의 결단이 옳은 방향이라고 생각한다. 표준화된 웹은 차별 없는 서비스를 사용자에게 제공할 수 있기 때문이다.
ECMA-402 명세에서 국제화를 위한 Intl.DateTimeFormat
이 추가되었고 IANA의 데이터베이스를 사용하는 기능이 추가되었다. 언어에 맞는 날짜 및 시간 서식을 지원하는 기능이다. 그러나 이마저도 특정 타임존의 오프셋을 직접 반환하는 기능은 없다. 타임존을 지정한 후 해당 언어에 맞도록 문자열을 출력하는데, 이 때 문자열에 오프셋이 포함되어 있다. 이것을 파싱해서 오프셋을 알아내는 방식이라서 약간 우회하는 방법이다.
const date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
const options = {
timeZone: "America/Los_Angeles",
timeStyle: "long"
};
console.log(new Intl.DateTimeFormat("ko-KR", options).format(date));
// 오후 7시 0분 0초 GMT-8
Intl.DateTimeFormat
의 옵션에 IANA 데이터베이스의 타임존 이름을 지원한다. format()
함수에서 반환하는 문자열(GMT-8
)을 다시 파싱해서 오프셋을 알아내야 한다. 직접 구현하려면 다소 번거로운 부분일 수 있다. 그래서 우리가 라이브러리를 쓰는 것이 아닐까. dayjs, luxon, date-fns 등이 Intl
를 사용하여 날짜 관련 각종 편의 기능과 타임존 기능을 제공한다. moment가 굿바이하면서 대안으로 제시한 라이브러리다.
프런트엔드에서 썸머타임을 고려한 타임존을 다양하게 지원하기 위해서는 고민할 거리가 산더미였다. 그래서 타임존의 데이터베이스를 가지고 있는 moment.js를 쓰게 되면 이런 고민거리와 구현 난이도가 해결되었다. 기승전 moment.js인 시절이었다고 할 수 있다. moment.js의 과감한 결단으로 이제 어쩔 수 없이(?) 레거시를 끊어내고 표준화된 웹으로 더 나아갈 수 있으리라고 생각한다.
타임존은 필자와 같이 한 지역에서 태어나고 자란 사람에게는 생소할 수 있다. 타임존이 어떤 것이고 일반적인 규칙에 의해서 프로그래밍할 수가 없는 이유, 데이터베이스가 필요한 이유를 알고 접근한다면 글로벌 서비스를 만드는데 유용하리라 생각한다. 많은 도움이 되었길 바란다.