- NTP는 네 개의 타임스탬프를 주고받아 서버의 시간과 RTT(왕복 지연)를 동시에 측정한다
- Stratum 계층 구조 덕분에 인터넷의 모든 시계가 원자시계와 연결된다
- NTP는 시간을 “덮어쓰지 않고” 점진적으로 끌어당긴다 — 이게 시스템 안정성의 비결
NTP는 무엇인가
NTP(Network Time Protocol)는 인터넷의 시계를 한 줄로 세우는 프로토콜이다. 1985년 데이비드 밀스(David L. Mills)가 설계해 RFC 958로 처음 발표되었고, 현재의 NTPv4(RFC 5905)는 1초의 1,000분의 1, 즉 밀리초 수준에서 컴퓨터 시계를 동기화한다. LAN 안에서는 0.1ms, 인터넷 전반에서도 통상 1~50ms 정확도를 보장한다.
이 프로토콜이 없으면 어떤 일이 벌어질까. 메일에 찍힌 시간이 보낸 사람과 받는 사람이 다르고, 보안 인증서의 만료 판정이 어긋나며, 분산 데이터베이스가 “이 트랜잭션이 먼저인가 나중인가”를 결정하지 못한다. 그래서 NTP는 인터넷의 보이지 않는 인프라 중 가장 중요한 것 중 하나로 꼽힌다.
네 개의 타임스탬프 — NTP의 심장
NTP의 핵심 아이디어는 의외로 간단하다. 클라이언트와 서버가 패킷 한 번 왕복하면서 다음 네 개의 타임스탬프를 기록한다.
- T1: 클라이언트가 요청을 보낸 시각(클라이언트 시계)
- T2: 서버가 요청을 받은 시각(서버 시계)
- T3: 서버가 응답을 보낸 시각(서버 시계)
- T4: 클라이언트가 응답을 받은 시각(클라이언트 시계)
이 네 값으로 다음 두 가지를 동시에 계산할 수 있다.
- 왕복 지연(Round-trip delay): δ = (T4 − T1) − (T3 − T2)
- 시계 오프셋(Clock offset): θ = ((T2 − T1) + (T3 − T4)) / 2
오프셋 θ는 “내 시계가 서버보다 얼마나 빠르거나 느린가”를, 지연 δ는 “패킷이 서버까지 갔다 오는 데 얼마나 걸렸는가”를 의미한다. 우리가 네트워크 지연이 클릭 타이밍에 미치는 영향에서 더 깊게 다루는 ping과 본질적으로 같은 값이다.
왜 굳이 네 개의 타임스탬프를 쓸까
중간 두 값(T2, T3)을 빼는 이유는 “서버 처리 시간”을 제거하기 위해서다. 만약 두 개의 타임스탬프(보낸 시간, 받은 시간)만으로 오프셋을 계산하면, 서버가 응답을 만드느라 1ms 지연되었다면 그 1ms가 그대로 시계 오차로 들어가 버린다.
NTP는 “네트워크 왕복 시간 = T4 − T1 − (T3 − T2)”로 표현하여 서버 내부 처리 시간을 깔끔하게 빼낸다. 이 단순한 수식 덕분에 NTP는 서버 부하 변동에 영향받지 않는 시간을 얻을 수 있다.
Stratum 계층 — 인터넷의 시계 트리
NTP는 시간을 신뢰성 등급으로 계층화한다. 이 등급을 “Stratum”이라고 부른다.
| Stratum | 설명 | 예시 |
|---|---|---|
| 0 | 원자시계·GPS 등 “레퍼런스 클록” | 세슘 원자시계, GPS 위성 시계 |
| 1 | Stratum 0에 직접 연결된 NTP 서버 | 국가 표준연구소, KRISS, time.nist.gov |
| 2 | Stratum 1과 동기화된 NTP 서버 | 대형 ISP·클라우드 서비스의 NTP 서버 |
| 3 ~ 15 | 하위 계층 NTP 서버 / 일반 클라이언트 | 회사·학교·가정의 NTP 클라이언트 |
| 16 | “동기화되지 않음”을 의미하는 특수 값 | NTP 응답 실패 상태 |
일반적인 데스크탑·서버는 Stratum 2 또는 3에 위치한다. Stratum 1까지 거슬러 올라가면 결국 GPS 또는 원자시계로 연결되며, 그래서 우리 컴퓨터의 시계는 “원자시계의 후손”이라 할 수 있다.
점진적 보정 — “덮어쓰지 않는” 시간 동기화
NTP가 단순히 시계를 매번 “현재 시각으로 덮어쓰는” 방식이라면 큰 문제가 생긴다. 어플리케이션이 “지금 시각”을 읽어 작업을 분기하던 중에 갑자기 시간이 점프해 버리면, 같은 이벤트가 두 번 일어나거나 일어나지 않은 일로 간주될 수 있다.
NTP는 그래서 “slewing(점진적 보정)” 또는 “stepping(즉시 점프)”의 두 모드를 구분해 사용한다.
- Slewing: 시계의 진행 속도를 약간 빠르게 또는 느리게 조정해, 몇 초~몇 분에 걸쳐 정확한 시각으로 끌어간다. 일반적으로 0.5ppm 수준의 클럭 드리프트를 점진적으로 보정한다.
- Stepping: 시간 차이가 너무 크면(보통 128ms 초과) 어쩔 수 없이 즉시 점프시킨다. 부팅 직후나 큰 시간 오류 발생 시에 사용된다.
이 두 모드의 조합 덕분에, NTP는 ‘시간이 갑자기 튀는 사고’를 거의 일으키지 않으면서도 정확도를 유지할 수 있다.
NTP의 내부 알고리즘 — 가장 신뢰할 만한 시간을 찾는 통계
NTP 클라이언트는 단일 서버에만 의존하지 않는다. 일반적으로 4개 이상의 서버에 동시에 질의하고, 그 응답들을 다음 단계로 처리한다.
- 필터링(filter): 같은 서버에서 받은 최근 8개의 응답 중에서 RTT가 가장 작은 것을 선택한다. 네트워크 변동이 작을수록 정확도가 높기 때문이다.
- 선택(select): 여러 서버의 응답 중 “이상치(falseticker)”를 통계적으로 제거한다. 한두 대의 서버가 잘못된 시간을 보내도 다수결로 걸러진다.
- 병합(combine): 살아남은 서버의 시간 응답을 가중평균해 최종 오프셋과 지터를 산출한다.
- 제어(loop filter): 산출된 오프셋을 OS 시계의 진행 속도에 점진적으로 반영한다(slewing).
이 4단계의 통계적 처리 덕분에 NTP는 한두 서버가 잘못된 시간을 보내도 안전하게 동작한다. 보안 측면에서도 “악의적인 시간 서버 한 대” 정도로는 시스템 시간을 조작할 수 없다는 의미다.
왜 학교 서버시간이 KST와 다를까
대학교 수강신청 서버가 KST와 ±수백 ms 차이가 나는 이유는 대부분 다음 중 하나다.
- 서버가 NTP 동기화를 하지 않거나, 매우 드물게 한다(예: 부팅 시 1회).
- NTP는 동기화하지만, HTTP 응답을 만드는 서버 처리 시간이 더해져 결과적으로 “보이는 시간”이 어긋난다.
- 백엔드 시계는 정확하지만, 응답 헤더의
Date:필드를 만드는 시점과 실제 전송 시점에 미세한 차이가 있다.
수강타임은 같은 서버에 여러 번 측정 요청을 보내고, 응답에 포함된 Date: 필드와 클라이언트의 NTP 기반 KST를 비교한다. 위에서 본 4-타임스탬프 모델을 단순화해, 응답 시점을 (요청 보낸 시각 + 받은 시각) / 2로 잡고 KST와 비교한다. 단일 측정에는 노이즈가 많지만 여러 번 측정해 평균 내면 학교 서버의 “실제 보이는 시각”을 ms 단위로 안정적으로 잡을 수 있다.
NTP는 한 번도 본인이 동작하는 모습을 보여주지 않는다. 컴퓨터 부팅 직후 몇 초간, 그리고 매 30초~17분(주기는 polling rate에 따라 변동) 간격으로 조용히 패킷을 주고받을 뿐이다. 그러나 이 작은 동작이 멈추면 인터넷 전체의 신뢰성이 무너진다. 우리가 “내 시계가 정확하다”고 무심코 말할 수 있는 이유는, 보이지 않는 곳에서 NTP가 매분 작동하고 있기 때문이다.
다음 글에서는 클라이언트시간 vs 서버시간의 차이를 코드 레벨에서 설명한다.