본문 바로가기
개발 노트/실무 프로젝트

분산 시스템 시간 정합성: UTC, NTP, 그리고 관용

by 시뮬레이션 프로그래머 2025. 12. 23.

Kafka 기반 분산 시스템에서 transactional outbox 테이블에 메시지가 분명 존재하는데도 발행되지 않는 문제를 겪었습니다.
 
원인은 Producer와 Poller(Message Relay: Polling)가 서로 다른 시간을 기준으로 이벤트를 판단하고 있었던 것이었습니다.
 
이 글은 이 경험을 바탕으로, 왜 분산 환경에서는 UTC를 공통 시간 기준으로 삼아야 하고,
그것만으로는 왜 충분하지 않은지를 정리한 글입니다.
 

목차

  1. 문제 정의
  2. 원인: “모든 서버의 시계는 같을 것이다”라는 착각
  3. 해결책
  4. 요약

1. 문제 정의

이벤트 기반 아키텍처의 분산 시스템(Producer–Consumer)에서는
물리적 시간 불일치(Clock Skew / Drift)와
타임존 해석 차이로 인해 다음과 같은 문제가 발생할 수 있습니다.

  • 이벤트가 발행되지 않음
  • 이벤트 순서가 뒤바뀜
  • 재시도·중복 처리 로직이 오작동함

이를 방지하려면, 시스템 전반에서 시간을 다루는 방식 자체를 표준화해야 합니다.


2. 원인: “모든 서버의 시계는 같을 것이다”라는 착각

문제의 직접적인 트리거는 단순한 조건식이었습니다.

created_at <= now()

 
이 조건이 실패한 이유는 하나입니다.

분산 시스템에서 모든 서버의 시계는 동일하지 않다는 전제를 놓쳤기 때문입니다.

 
쉽게 비유하면 이런 상황입니다.

여러 사람이 각자 시계를 들고 약속 장소에 모이는데,
누구의 시계도 정확히 같은 시간을 가리키지 않습니다.
그런데 “정각 3시에 온 사람만 입장”이라는 규칙을 적용하면,
누군가는 제시간에 와도 입장하지 못합니다.

 
분산 시스템에서도 다음과 같은 3가지 이유로 같은 일이 벌어집니다.
 

1) Clock Drift (클럭 드리프트)

하드웨어 시계는 완벽하지 않습니다. 온도, 전압, 환경 차이로 인해 시간은 항상 조금씩 어긋납니다.
 
[사례]
Producer(DB)가 transaction outbox 테이블에 기록한 created_at 이
Consumer의 현재 시간보다 단 1ms라도 미래라면, Consumer는 이를 “아직 처리하면 안 되는 이벤트”로 판단합니다.
이 사례는 이벤트 우선순위 적용을 위해 이런 로직을 구현했고, 그 결과 정상 이벤트가 처리되지 않는 문제가 발생했습니다.
 

2) Timezone Misinterpretation (타임존 해석 오류)

Producer는 이벤트를 UTC 기준으로 저장했는데,
Consumer는 로컬 타임(KST 등) 기준 now()로 비교하고 있었습니다.
이 경우 최대 9시간의 시간 차이가 발생하며, 해당 로직은 사실상 완전히 붕괴됩니다.
 

3) Network Latency (네트워크 지연)

NTP(Network Time Protocol)로 동기화하더라도 네트워크 RTT(Round Trip TIme), 스케줄링, VM/컨테이너 환경으로 인해 수~수십 ms 오차는 필연적입니다.


3. 해결책

해결책은  UTC 표준화 + NTP 동기화 + 소프트웨어적 관용(Tolerance) 이 세 가지를 함께 적용해야 합니다.

 

UTC(Universal Time Coordinated)란 무엇인가

UTC(Universal Time Coordinated)

UTC(Coordinated Universal Time)는
지구 자전이 아니라 세슘 원자의 진동수를 기준으로 정의된 국제 표준시입니다.

  • 서머타임(DST)이 없음
  • 지역·정치적 변경의 영향을 받지 않음
  • 전 세계 어디서나 동일하게 해석됨

UTC가 필요한 이유

  • 시간 비교·정렬·연산을 단순화하기 위해
  • “이 시간이 무슨 의미인가”를 두고 더 이상 해석 싸움을 하지 않기 위해

UTC는 사람을 위한 시간이 아니라, 시스템이 판단하기 위한 시간입니다.
 

UTC만으로 부족한 이유

UTC는 표현 기준이지 동기화 수단이 아닙니다.
모든 시스템이 UTC로 시간을 표시하더라도, 각 시스템의 시계가 실제로 같은 시점을 가리킨다는 보장은 없습니다.
즉, UTC는 형식을 통일할 뿐 시계를 맞춰주지는 않습니다.
 


NTP(Network Time Protocol)란 무엇인가

UTC가 “어떤 시간으로 말할 것인가”에 대한 약속이라면

NTP(Network Time Protocol)

NTP는 “그 시간을 실제로 어떻게 맞출 것인가”에 대한 방법입니다.
NTP는 네트워크를 통해 여러 컴퓨터 시스템의 시간을 하나의 기준 시계에 맞춰 동기화하는 프로토콜입니다.
 
쉽게 비유하면 이렇습니다.

회의 시작 전에 모두가 각자 시계를 보는 대신,
“이 벽에 있는 시계를 기준으로 맞추자”라고 합의하는 것과 같습니다.

 

NTP가 필요한 이유

  • 하드웨어 시계는 항상 조금씩 느려지거나 빨라짐 (Clock Drift)
  • 서버를 오래 켜둘수록 오차가 누적됨
  • VM·컨테이너·클라우드 환경에서는 더 쉽게 어긋남

즉, UTC로 저장한다고 해서 시간이 자동으로 맞는 것은 아닙니다.
 
NTP는 이 문제를 해결하기 위해

  • 외부의 정확한 기준 시계와 주기적으로 통신하고
  • 현재 서버 시간이 얼마나 어긋났는지를 계산한 뒤
  • 시간을 갑자기 바꾸지 않고 서서히 보정(slew) 합니다

(NTP의 세부 동작은 이 글에서 다루지 않습니다)
 


그래도 오차는 발생한다 → 소비 로직 개선

NTP를 적용해도 수 ms~수십 ms 오차는 남습니다.
 
그래서 소비 로직에서 다음과 같은 엄격 비교는 위험합니다.

eventTime <= now()

 
대신, 오차를 전제로 한 Grace Period(관용)를 둡니다.

eventTime <= now() + tolerance

4. 요약

분산 시스템에서는 서로 다른 노드의 시간은 항상 조금씩 다릅니다.
 
이런 시간 관련 문제는 다음 이유로 발생합니다.
 

  • Clock Drift
    서버마다 물리적 시계가 완벽히 같지 않아 시간이 조금씩 어긋납니다.
  • Timezone Misinterpretation
    타임존 해석 차이로 같은 시각이 서로 다르게 비교됩니다.
  • Network Latency
    네트워크 지연, 스케줄링, 실행 환경 차이로 미세한 ms 단위 오차는 피할 수 없습니다.

 
 
이를 해결하려면
UTC 표준화 + NTP 동기화 + 소프트웨어적 관용(Tolerance)
이 세 가지를 함께 적용해야 합니다.

  • UTC시스템이 판단하기 위한 시간 기준입니다. (동기화 용도 아님)
  • NTP는 UTC를 기준으로 각 서버의 물리적 시간을 동기화합니다.
  • UTC + NTP를 적용해도 오차는 존재합니다.
    → 따라서 소비 로직에는 관용(Grace Period) 이 필요합니다.