사전 벽시계
개념

벽시계

gabury1고친 사람 github-actions[bot]

벽시계는 지금이 몇 시인지 알려 주는 시계입니다. 사람이 읽는 시각이 이 시계에서 나옵니다. 다른 기기와 맞대어 보는 시각도 같습니다. 대신 세상의 시각을 따라가느라 값이 앞으로 뛰거나 뒤로 돌아가기도 합니다.

쉽고 빠른 이해

벽시계는 사무실 벽에 걸린 시계와 같은 일을 합니다. 로그 한 줄에 찍히는 시각이 이 시계에서 나옵니다.

기기가 혼자 세는 시각은 놔두면 조금씩 틀어집니다. 여러 기기의 기록을 나란히 놓고 보려면 모두가 같은 기준 시각을 따라가야 합니다.

  1. 기기 안의 시계가 자기 박자로 시각을 셉니다
  2. 바깥의 기준 시각과 견주어 얼마나 어긋났는지 봅니다
  3. 그만큼 값을 옮기거나 박자를 조절해 따라잡습니다

대가는 값이 한 방향으로만 흐른다고 믿을 수 없다는 것입니다. 두 번 읽어 뺀 차이가 음수로 나오기도 해서, 걸린 시간을 재는 데는 못 씁니다.

상세

사무실 벽에 걸린 시계를 떠올려 보십시오. 모두가 그 시계를 보고 회의 시각을 맞춥니다. 조금 느려졌다 싶으면 누군가 바늘을 돌려 맞춰 둡니다. 컴퓨터가 들고 있는 벽시계도 똑같습니다.

벽시계는 세상이 함께 쓰는 시각을 따라가는 시계입니다. 이 시계는 맞고 틀림이 있습니다. 바깥의 기준 시각과 견주어 얼마나 어긋났는지 알아냅니다. 알아내면 맞춰 줍니다. 로그에 찍는 시각, 데이터베이스에 넣는 만료 시각, 인증서의 유효 기간이 전부 벽시계 값입니다.

이 시계가 없으면 기기마다 제각각인 시각을 세게 됩니다. 그러면 두 서버의 기록을 나란히 놓고 어느 것이 먼저인지 가릴 수 없습니다. 벽시계는 그 값을 세상의 시각에 묶어 두어, 남의 기록이나 사람이 보는 달력과 맞댈 수 있게 만듭니다.

이 절은 차례로 봅니다. 벽시계가 들고 있는 값, 그 값이 오는 곳, 값을 맞추는 두 방법과 값이 뒤로 가는 까닭입니다. 성능을 말할 때의 벽시계 시간과 벽시계를 고르는 기준도 뒤에 붙습니다.

벽시계가 들고 있는 값

컴퓨터는 시각을 날짜와 시·분으로 들고 있지 않습니다. 기준으로 삼은 한 시점부터 몇 초가 지났는지를 수 하나로 셉니다. 그 기준 시점을 에포크라고 합니다.

유닉스 계열이 널리 쓰는 에포크는 1970-01-01 0시입니다. 이 기준으로 센 값을 유닉스 시간이라고 부릅니다. 기준이 되는 시각은 온 세상이 함께 쓰는 UTC(Coordinated Universal Time, 협정 세계시)로 잡습니다.

나라마다 다른 시간대는 이 값에 안 들어갑니다. 값은 어디서 읽어도 같습니다. 사람에게 보여 줄 때만 그 나라 몫을 더하고 뺍니다. 그래서 서울에서 찍은 시각과 런던에서 찍은 시각을 저장한 값끼리 바로 견줄 수 있습니다.

flowchart TD
    E["에포크 · 1970-01-01 0시"] --> V["경과 초 하나 · UTC 기준"]
    V --> S["서울에 보일 때 +9시간"]
    V --> L["런던에 보일 때 +0"]

저장하는 칸은 하나입니다. 갈림은 사람에게 보여 주기 직전에만 생깁니다.

값이 오는 곳

기기 안에서 시계의 박자를 만드는 부품은 수정 진동자입니다. 전기를 주면 일정한 횟수로 떱니다. 그 떨림을 세어 시각을 셉니다.

전원이 꺼지면 이 셈이 멈춥니다. 그래서 메인보드에는 작은 배터리로 따로 도는 실시간 시계가 있습니다. 부팅할 때 커널이 그 값을 읽어 벽시계의 출발점으로 삼습니다.

수정 진동자는 온도에 따라 미세하게 빨라지고 느려집니다. 놔두면 기준 시각에서 조금씩 멀어진다는 뜻입니다. 이 벌어짐을 클록 드리프트라고 합니다.

벌어진 것을 메우는 일이 시각 동기화입니다. 바깥의 기준 시각 서버에 물어 자기 시각이 얼마나 어긋났는지 잽니다. 그만큼 되돌립니다.

이 일을 맡는 대표 프로토콜이 NTP(Network Time Protocol, 네트워크 시각 프로토콜)입니다.

flowchart TD
    subgraph inside["기기 안"]
        X["수정 진동자 · 박자를 만든다"] --> K["커널이 들고 있는 벽시계 값"]
        R["실시간 시계 · 전원이 꺼져도 시각을 지킨다"] --> K
    end
    subgraph outside["바깥"]
        S["기준 시각 서버"] --> N["시각 동기화 · 어긋난 만큼 되돌린다"]
    end
    N --> K
    K --> A["프로그램이 읽는 벽시계 시각"]

프로그램이 읽는 값은 맨 아래 칸입니다. 바깥에서 들어오는 화살표가 하나 있다는 것이 벽시계의 성격입니다. 값이 기기 안에서만 자라지 않고 남의 손을 탑니다.

시각을 맞추는 두 방법

어긋난 시각을 되돌리는 방법은 둘입니다. 어느 쪽을 쓰느냐에 따라 값이 뒤로 가기도 하고 안 가기도 합니다.

건너뛰기는 값을 목표 시각으로 곧장 옮깁니다. 한순간에 끝나는 대신 그 순간 시각이 뜁니다. 시계가 앞서 있었다면 값을 뒤로 돌려야 합니다. 그때 벽시계는 지나온 시각을 다시 지나갑니다.

늦추기는 시계의 박자를 잠깐 느리거나 빠르게 해서 서서히 따라잡습니다. 값이 뒤로 가지 않는 대신 다 맞추는 데 오래 걸립니다.

건너뛰기 늦추기
하는 일 값을 곧장 옮긴다 박자를 조절해 서서히 맞춘다
맞춰지는 때 한순간 오래 걸린다
값이 뒤로 가나 간다 안 간다
주로 쓰는 때 많이 어긋났을 때 조금 어긋났을 때

표에 안 담기는 것이 하나 있습니다. 시계가 3초 앞서 있을 때 값이 밟고 지나가는 시각입니다.

flowchart TD
    subgraph skip["건너뛰기 · 값을 곧장 옮긴다"]
        A1["10:00:05"] --> A2["10:00:02 · 뒤로 돌아갔다"] --> A3["10:00:05 · 같은 시각을 다시 지난다"]
    end
    subgraph slew["늦추기 · 박자를 늦춘다"]
        B1["10:00:05"] --> B2["10:00:06 · 한 칸이 좁아진다"] --> B3["10:00:07 · 값은 늘 커진다"]
    end
    skip ~~~ slew

건너뛰기는 벽시계가 같은 시각을 두 번 지나가게 만듭니다. 늦추기는 값을 늘 키우되 한 칸의 폭만 줄입니다.

벽시계가 뒤로 갈 수 있다는 것은 건너뛰기를 허용한 대가입니다.

값이 뒤로 가면 생기는 일

두 시점 사이의 거리를 벽시계로 재면 어떻게 되는지 보겠습니다.

t1 = 벽시계_읽기()   // 10:00:05
// 그 사이 시각 동기화가 값을 뒤로 돌린다
t2 = 벽시계_읽기()   // 10:00:02
경과 = t2 - t1      // -3초

일은 앞으로 흘렀는데 잰 값은 음수입니다. 두 번 읽는 사이에 시각 동기화가 값을 뒤로 돌렸기 때문입니다. 반대로 시계를 앞으로 크게 옮기면 짧은 일이 몇 시간짜리로 잡힙니다.

벽시계를 흔드는 것이 시각 동기화만은 아닙니다. 관리자가 손으로 시각을 고칠 때, 윤초 때문에 1초를 넣거나 뺄 때, 멈춰 두었던 가상 머신을 되살릴 때도 값이 튑니다. 이렇게 벽시계 값을 옮기는 일을 통틀어 시각 보정이라 부릅니다.

기기가 여럿이면 어긋남이 하나 더 있습니다. 같은 순간에 서버 둘이 벽시계를 읽어도 값이 서로 조금 다릅니다. 이 차이를 클록 스큐라고 합니다. 그 때문에 나중에 난 사건이 더 이른 타임스탬프를 달고 나타나기도 합니다.

sequenceDiagram
    participant 가 as 서버 가 · 벽시계가 앞선다
    participant 나 as 서버 나 · 벽시계가 뒤처진다
    Note over 가,나: 두 벽시계는 클록 스큐만큼 어긋나 있다
    가->>가: 사건 하나가 먼저 난다
    Note over 가: 타임스탬프 10:00:05
    나->>나: 사건 둘이 나중에 난다
    Note over 나: 타임스탬프 10:00:02

세로로 내려가는 것이 실제 시간입니다. 나중에 난 사건 둘이 더 이른 타임스탬프를 달고 나왔습니다.

그래서 걸린 시간을 재는 데는 값이 뒤로 가지 않는 단조 시계를 씁니다. 여러 기기 사이의 앞뒤를 가려야 하면 시각 대신 순서만 매기는 논리 시계로 갑니다.

성능을 볼 때 쓰는 벽시계 시간

성능을 볼 때는 벽시계라는 말이 시계가 아니라 시간의 종류를 가리킵니다. 벽시계 시간은 일이 시작해서 끝날 때까지 바깥에서 흐른 시간 전부입니다. 기다린 시간도 여기 들어갑니다.

맞세워지는 것은 CPU 시간입니다. CPU(Central Processing Unit, 중앙처리장치)가 그 일에 매달려 있던 시간만 셉니다. 응답을 기다리며 놀고 있는 동안 CPU 시간은 안 늘고 벽시계 시간만 흐릅니다.

sequenceDiagram
    participant 프로그램
    participant 데이터베이스
    Note over 프로그램: 계산한다 · 벽시계 시간과 CPU 시간이 함께 흐른다
    프로그램->>데이터베이스: 질의를 보낸다
    Note over 프로그램,데이터베이스: 기다린다 · CPU 시간은 안 늘고 벽시계 시간만 흐른다
    데이터베이스-->>프로그램: 결과를 돌려준다
    Note over 프로그램: 다시 계산한다 · 둘 다 흐른다

한 구간 안에서 두 시간이 서로 다른 속도로 흐릅니다. 기다리는 구간에서 벌어진 만큼이 두 값의 차이입니다.

이름은 벽시계지만 잴 때는 단조 시계를 쓰는 것이 보통입니다. 두 번 읽는 사이에 시각 보정이 끼면 잰 값이 어긋나기 때문입니다.

벽시계와 단조 시계를 가르는 기준

기준은 한 줄입니다. 사람이나 다른 기기에 보여 줄 시각이면 벽시계입니다. 두 시점 사이의 거리를 재는 것이면 단조 시계입니다.

하려는 일 고를 시계
로그 한 줄에 시각을 찍는다 벽시계
쿠폰 만료 시각을 데이터베이스에 넣는다 벽시계
두 서버의 기록을 시간순으로 맞춘다 벽시계
요청 하나가 얼마나 걸렸는지 잰다 단조 시계
타임아웃까지 남은 시간을 센다 단조 시계
재시도 간격을 센다 단조 시계

위쪽 셋은 값을 밖으로 내보냅니다. 나중에 사람이 읽거나 다른 기기의 값과 견주므로 벽시계가 아니면 뜻이 안 섭니다. 아래쪽 셋은 값을 밖으로 내보내지 않고 두 시점의 거리만 봅니다. 그 거리는 세상 시각과 상관이 없습니다.

분산 시스템에서는 위쪽마저 벽시계로 부족할 때가 있습니다. 서버마다 벽시계가 조금씩 어긋나 있어서, 아주 가까운 두 사건의 앞뒤를 시각만으로는 못 가리기 때문입니다.

관련 항목

벽시계와 맞세워지는 시계

단조 시계 · 논리 시계 · 벡터 시계 · 하이브리드 논리 시계 · CPU 시간 · 램포트 타임스탬프

벽시계 값이 세는 기준점과 표기 형식

에포크 · 유닉스 시간 · 타임스탬프 · ISO 8601 · RFC 3339 · UTC · 시간대 · 나노초

벽시계 시각을 뒤흔드는 원인

NTP · 윤초 · 클록 드리프트 · 클록 스큐 · 클럭 스텝 · 윤초 문지르기 · 수정 진동자 · 가상 머신

벽시계를 내주는 바탕 소프트웨어와 부품

운영체제 · 커널 · 시스템 콜 · 실시간 시계 · 시스템 클록 · clock_gettime · CLOCK_REALTIME · gettimeofday · 시간과 시계

벽시계 시각을 읽어 값을 정하는 처리

로그 · 만료 · 세션 · 인증서 · 감사 로그 · 스노우플레이크 · 캐시 만료

벽시계가 어긋나도 버티게 하는 기술

분산 시스템 · TrueTime · 리스 · 타임아웃 · 시간 동기화

다른 이름: wall clock · wall-clock time · 벽시계 시각 · 벽시계 시간