서버시간 & 네트워크

클라이언트시간 vs 서버시간: 수강신청에서 누구 시계가 기준인가

내 컴퓨터 시간과 서버 시간은 왜 다를까. 수강신청·티켓팅·결제에서 실제 기준이 되는 시간이 무엇인지 코드 레벨에서 설명합니다.

이 글의 요점
  • 거의 모든 웹 시스템은 “서버 시계”를 기준으로 판단한다 — 클라이언트 시계는 신뢰되지 않는다
  • JavaScript의 Date.now()는 사용자 PC 시계에 의존하므로 임의로 5분 빠르게 만들 수 있다
  • 그래서 수강신청·예매·결제 시스템은 항상 서버 시계를 기준으로 시점 판정을 한다

“수강신청 시간”은 누구의 시계인가

학교 포털에 09:00:00이라는 수강신청 시작 시각이 표시되어 있을 때, 그 “09:00:00”은 누구의 시계 기준일까. 답은 분명하다 — 학교 서버의 시계다. 학생의 PC가 아무리 정확해도 학교 서버가 아직 09:00:00을 알리지 않았다면, 신청은 거절된다.

이 단순한 사실이 의외로 많은 학생을 헷갈리게 한다. “내 시계는 정확한데 왜 안 되지?”라는 질문이 매년 반복되는 이유다. 모든 분산 시스템에서 시간 판정의 기준이 “서버 시계”인 이유를 코드 레벨에서 살펴보자.

클라이언트 시계는 왜 신뢰되지 않는가

웹 브라우저에서 시간을 얻는 가장 간단한 방법은 다음과 같다.

const now = Date.now(); // 1972년 부터의 ms

이 값은 사용자의 OS 시계가 알려준 시각이다. 문제는 OS 시계가 어떤 검증도 받지 않는다는 점이다. 사용자는 시스템 설정에서 시계를 임의로 5분 빠르게 만들 수 있고, 일부러 5초 빠르게 맞춰 두고 “수강신청을 5초 일찍 클릭”할 수도 있다.

만약 학교 시스템이 클라이언트 시계를 기준으로 판단한다면 어떤 일이 벌어질까.

  • 모든 학생이 시스템 시계를 빠르게 맞추려 할 것이다.
  • 0.001초 단위 경쟁이 시스템 설정 경쟁으로 변질된다.
  • 학사 행정은 “시계가 정확한 학생”에게만 유리해진다.

이런 사태를 막기 위해, 거의 모든 분산 시스템은 다음의 단순한 원칙을 따른다 — “클라이언트가 보내는 시간은 절대 신뢰하지 않고, 모든 시점 판정은 서버 시계로 한다.”

HTTP 요청에 시간을 담아도 무시된다

HTTP 요청 헤더에는 Date: 필드가 있다. 클라이언트가 “지금 몇 시에 요청했다”를 보낼 수 있는 자리다. 그러나 이 필드는 보안·인증 목적의 일부 시스템(예: AWS Signature)을 제외하면, 일반적으로는 서버가 무시한다.

대신 서버는 자신이 요청을 “받은 시각(T2)”을 기록하고, 다음 형태의 코드로 시점을 판정한다.

// 의사 코드
$now = microtime(true);
$start = strtotime($courseSchedule->open_at);
if ($now < $start) {
    return error("아직 신청 시작 전입니다.");
}
// 신청 처리...

이 코드의 microtime(true)가 곧 “서버 시계”다. 클라이언트가 무엇을 보내든, 결과는 이 값에 의해 결정된다.

그러면 클라이언트 시계는 무엇에 쓰는가

클라이언트 시계가 완전히 쓸모없는 것은 아니다. 사용자에게 보여주는 “남은 시간 카운트다운”, “마감까지 5초” 같은 UI 요소는 모두 클라이언트 시계로 그린다. 다만 다음의 두 단계로 운영하는 것이 일반적이다.

  1. 페이지가 처음 로드될 때, 서버가 “현재 서버 시각”을 응답에 담아 보낸다.
  2. 클라이언트는 이 서버 시각을 기준점으로 잡고, 자기 시계의 흐름만 사용해 카운트다운을 그린다.

이 방식이 “클라이언트 시계의 절대값은 무시하지만, 클라이언트 시계의 진행 속도는 활용”하는 패턴이다. 아래는 단순화한 패턴이다.

// 페이지 로드 시
const serverTimeAtLoad = parseInt(document.body.dataset.serverTime); // 서버에서 받음
const clientTimeAtLoad = Date.now();

function getServerNow() {
    return serverTimeAtLoad + (Date.now() - clientTimeAtLoad);
}

수강타임이 각 대학교 페이지에서 보여주는 “서버시간 시계”도 본질적으로 이 패턴을 따른다. 서버에서 측정한 시계 차이를 기준점으로 잡고, 클라이언트의 진행 속도를 그대로 사용한다.

시간 동기화 오차는 언제 문제가 되는가

서버 시계가 기준이라고 해도, 사용자가 “남은 시간”을 잘못 추정하면 결국 클릭이 늦거나 빠르다. 다음의 시나리오를 보자.

상황표시되는 시간실제 결과
내 시계 +0.5초 빠름09:00:00에 클릭서버는 아직 08:59:59.5 — 거절
내 시계 정확하지만 ping 200ms09:00:00에 클릭서버 도달 시각 09:00:00.2 — 안전
내 시계 정확, 서버 시계 +1초 느림09:00:00에 클릭서버는 08:59:59 — 거절

이 표가 보여주는 메시지는 분명하다. “내 시계의 정확도”와 “서버 시계의 정확도”는 따로 관리해야 한다. 우리가 직접 통제할 수 있는 것은 자기 PC의 시계뿐이지만, 서버 시계가 KST와 얼마나 차이 나는지 미리 측정해 두면 클릭 타이밍을 보정할 수 있다.

실전 — 수강신청 서버 시각을 “보이는 그대로” 측정하기

학교 서버에 직접 “지금 몇 시야?”를 묻는 API는 없는 경우가 많다. 그러나 다음 방법으로 “서버가 응답할 때 알려주는 시각”을 충분히 정확하게 얻을 수 있다.

  1. 서버에 GET 요청을 보낸다.
  2. 응답 헤더의 Date: 필드를 읽는다(서버가 응답을 만든 시점의 시각).
  3. 응답을 받은 클라이언트 시각을 기록한다.
  4. 요청 보낸 시각과 응답 받은 시각의 평균을 “서버가 응답을 보낸 시각”으로 추정한다.
  5. 이 추정값과 KST의 차이를 “서버 시간차”로 본다.

이 측정을 여러 번 반복해 평균을 내면 노이즈가 줄어든다. 수강타임은 같은 학교 서버에 일정 간격으로 측정 요청을 보내고, 평균값을 캐시해 사용자에게 보여준다. 측정 방식의 더 깊은 내용은 NTP가 시간을 동기화하는 원리를 함께 읽으면 좋다.

한 줄 결론

수강신청·예매·결제 시스템에서 클릭의 “정시”는 항상 서버 시계다. 우리가 할 일은 서버 시계와 KST의 차이를 미리 측정해 두고, 그 차이만큼 클릭을 앞뒤로 보정하는 것이다. 이 보정이 “0.1초의 차이가 갈리는 게임”에서 가장 큰 우위를 만든다.

이 글은 수강타임이 작성한 오리지널 콘텐츠입니다. 학사 행정·시스템 동작 원리에 근거해 작성되었으며, 대학·년도에 따라 세부 규정이 다를 수 있으므로 학교 학사일정과 공지를 함께 확인하세요.

같은 카테고리의 다른 글