How long is a second in JavaScript?(번역)

created:
last-updated:

저는 뭔가 늘 시스템의 구멍이나 표준의 미세한 오차 같은 것에 흥미가 많습니다. 그리고 완벽해보이는 시간 단위 같은 것들이 역사, 과학, 문화적인 배경과 연관이 깊고 어쩔때는 단지 인간이 그렇게 하기로 정한 것이라는 사실 같은게 늘 재미있어요.

2023년 토성의 위성이 145개라 태양계에 위성부자라는 기사[1]가 났는데, 이번 달에 또 발견돼 274개가 됐다는 소식[2]을 들으면 괜히 또 세상에 내가 알던게 아는게 아닌 순간이 또 오겠구나 싶은 묘한 마음에 공상에 빠지기도 합니다.

아무튼 토성이랑은 상관없는 얘기지만, 자바스크립트가 시간을 다루는 방식에 어떤 배경이 있는지, 그에 관한 간단한 소개글[3] 을 흥미롭게 읽고 번역합니다.


자바스크립트에서 1초는 얼마나 길까?

2025년 1월 26일 · 7분 소요
Iago Lastra Cofounder | TimeTime. in

"자바스크립트에서 1초는 얼마나 길까?"라는 질문은 겉보기에 단순한 것처럼 보이지만, 이를 깊이 탐구해 보면 역사, 과학, 그리고 현대 컴퓨팅의 기초와 얽혀 있는 복잡한 이야기들이 드러납니다. 이번 글에서는 시간이 측정되는 방식과 자바스크립트의 시간 개념이 어떻게 연결되는지 알아보겠습니다.


시간 측정의 역사

고대의 시간 측정

시간 측정은 자연 현상의 주기적 패턴을 관찰하는 것에서 시작되었습니다. 고대 문명은 달의 위상 변화와 태양의 이동을 관찰하며 시간을 나누었고, 이를 통해 일(day), 월(month), 년(year) 이라는 개념이 탄생했습니다.

인류의 필요에 따라 더 세분화된 시간 개념이 요구되면서 고대 이집트인과 바빌로니아인은 하루를 24시간으로 나누었습니다. 이들은 12진법을 사용했는데, 이 시스템이 현재까지도 1시간을 60분으로, 1분을 다시 60초로 나누는 방식으로 이어져 오고 있습니다.

원자 시계의 등장

수세기 동안 이러한 방식으로 시간을 측정했지만, 정밀성이 부족한 문제가 있었습니다. 20세기 중반, 기술이 발전하면서 보다 정확한 시간 측정이 필요해졌고, 1950년대에 원자 시계(Atomic Clock) 가 등장하면서 시간 측정이 혁신적으로 발전했습니다.

원자 시계는 세슘-133(Cs-133) 원자의 진동 주기를 기반으로 시간을 측정하며, 다음과 같이 정의됩니다.

"세슘-133 원자의 바닥 상태에서 두 개의 초미세(hyperfine) 에너지 준위 간 전이에 해당하는 복사선의 주기가 9,192,631,770번 반복되는 동안의 시간"을 1초로 정의한다.

이 정의는 현재 우리가 사용하는 국제 원자시(International Atomic Time, TAI) 의 기초가 되었습니다.


여러 가지 시간 체계

UT (Universal Time, 협정 세계시)

지구의 자전 주기에 기반을 둔 시간입니다. 직관적이고 우리가 일상에서 경험하는 낮과 밤의 개념과 연결되어 있지만, 지구 자전 속도가 일정하지 않다는 점에서 오차가 발생합니다.

TAI (International Atomic Time, 국제 원자시)

원자 시계를 기반으로 하는 시간으로, 물리적 현상에 의해 측정되기 때문에 매우 정밀하고 일정한 시간을 유지합니다. 현재 모든 현대 시간 측정 시스템의 기반이 됩니다.

UTC (Coordinated Universal Time, 협정 세계시)

1970년대에 UT와 TAI 간의 차이를 조정하기 위해 도입된 시간 체계입니다. UTC는 UT에 맞추기 위해 가끔씩 윤초(Leap Second) 를 추가하거나 제거합니다.


윤초(Leap Second)란?

윤초는 UTC와 지구 자전 속도를 맞추기 위해 가끔씩 1초를 추가하거나 삭제하는 조정 작업입니다.

이는 UTC가 UT(지구 자전 기반)와 0.9초 이상 차이가 나지 않도록 유지하기 위한 것이지만, 윤초가 추가될 때 컴퓨터 시스템에서는 시간이 순간적으로 멈추거나 거꾸로 가는 현상이 발생할 수 있습니다.

예를 들어, 다음과 같은 문제가 발생할 수 있습니다.


자바스크립트의 시간 개념

ECMAScript와 POSIX 시간

자바스크립트에서 시간은 POSIX 시간을 따릅니다. 이는 1970년 1월 1일 00:00:00 UTC부터 경과한 밀리초(ms) 단위의 값으로 날짜와 시간을 표현하는 방식입니다.

하지만 POSIX 시간은 윤초를 무시합니다. 즉, 모든 하루는 무조건 86,400초(24시간) 로 계산됩니다.

POSIX 시간 ≠ UTC

POSIX 시간과 UTC는 비슷해 보이지만 다음과 같은 차이점이 있습니다.

  1. 윤초를 무시함
    UTC에서는 윤초가 추가될 수 있지만, POSIX 시간에서는 하루가 항상 86,400초로 고정됩니다.
  2. 단순화된 연산
    POSIX에서는 모든 초가 동일한 길이를 가지므로 시간 차이를 계산하는 것이 단순하지만, UTC와 비교할 때 윤초가 발생하는 순간의 시간이 다르게 측정될 수 있습니다.

윤초(Leap Second)를 처리하는 방법

Step Adjustment (단계 조정) - 전통적인 방식

전통적으로 윤초를 처리하는 방법은 단계 조정(step adjustment) 입니다. 즉, 윤초가 추가되는 순간, 시간을 그냥 건너뛰어버립니다.

예를 들어,

UTC POSIX(단계 조정)
23:59:58 315619198.00
23:59:59 315619199.00
23:59:60 315619199.00 (동일 값)
00:00:00 315619200.00

이 방법의 문제는 같은 POSIX 초에 2개의 서로 다른 UTC 시간이 존재할 수 있다는 점입니다. 즉, 시간이 거꾸로 흐르는 오류가 발생할 수 있습니다.


Smearing (시간 분산 조정, 스미어링) - 실용적인 방식

구글과 같은 대형 시스템에서는 스미어링(smearing) 방식을 사용하여 윤초를 부드럽게 처리합니다.

스미어링 방식에서는 윤초를 특정 기간 동안 조금씩 분산하여 조정합니다. 예를 들어, 24시간 동안 초 단위를 아주 미세하게 조정하여 윤초를 자연스럽게 반영하는 방식입니다.

UTC POSIX(단계 조정) POSIX(스미어링)
23:59:58 315619198.00 315619197.75
23:59:59 315619199.00 315619198.50
23:59:60 315619199.00 315619199.25
00:00:00 315619200.00 315619200.00

이 방식은 시간이 점진적으로 변하므로 시스템이 오류를 덜 일으키며, 윤초로 인해 시간이 갑자기 멈추거나 거꾸로 흐르는 문제가 방지됩니다.

구글의 NTP 서버는 스미어링 방식을 사용하여 윤초를 24시간 동안 분산시킵니다. 자세한 내용은 여기에서 확인할 수 있습니다.


애플리케이션에 미치는 영향

대부분의 경우 문제가 되지 않는 이유

이벤트 일정 관리, 나이 계산, 사용자 인터페이스에서 시간 표시 등의 작업에서는 JavaScript(및 POSIX) 시간이 충분히 정밀하며, 대부분의 문제(99%)는 시간대(Timezone)로 인해 발생합니다.

정밀도가 중요한 경우

과학 연구나 금융 시스템과 같이 높은 정밀도가 요구되는 애플리케이션에서는 윤초(Leap Second)와 스미어링(Smearing)으로 인한 시간 차이가 심각한 오류를 초래할 수 있습니다. 정확한 시간 동기화는 측정값과 거래의 신뢰성을 보장하는 데 필수적입니다. 윤초가 발생하는 순간, 하나의 POSIX 타임스탬프가 UTC 기준으로 서로 다른 두 개의 순간을 가리킬 수 있습니다. 이는 정밀한 시간 동기화가 필요한 시스템에서 모호성을 유발하고, 심각한 오류로 이어질 수 있습니다.


핵심 정리


  1. https://m.dongascience.com/news.php?idx=59795 ↩︎

  2. https://www.dongascience.com/news.php?idx=70506 ↩︎

  3. https://docs.timetime.in/blog/how-long-is-a-second-in-js/ ↩︎