13. 리전 간 벽시계 타임스탬프로 이벤트 순서를 재구성하는 결함

난이도 상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 시나리오 (서버-서버): 여러 리전(지역)에 배치된 게임 서버들이 각각 발생시킨
// 이벤트(예: 길드 자원 기여, 크로스 리전 경매 입찰)를 중앙 집계 서버가 모아
// 순서대로 재구성해 처리해야 한다.
//
// 각 리전 서버는 이벤트를 생성할 때 자신의 시스템 시각(wall-clock)으로
// 타임스탬프를 찍어 보낸다. 중앙 집계 서버는 도착한 이벤트들을 이 타임스탬프
// 기준으로 정렬해 "일어난 순서"로 간주하고 처리한다.
//
// 서로 다른 리전의 서버 시각은 NTP 로 동기화되어 있지만, 네트워크 상황에
// 따라 수십~수백 밀리초 수준의 드리프트(오차)가 생길 수 있다.
//
// 요구사항:
//   - 실제 인과관계가 있는 이벤트(예: "입찰 A 가 있었기 때문에 그에 대한 응답
//     이벤트 B 가 발생")는 그 인과관계에 맞는 순서로 처리되어야 한다.
//   - 리전 간 시계 오차가 있더라도 인과관계가 있는 이벤트의 순서가 뒤바뀌면
//     안 된다.
//
// 과제: (A)(B) 지점을 검토해 위 요구사항이 깨지는 경로를 찾고 수정하라.

using System;
using System.Collections.Generic;
using System.Linq;

public sealed class RegionEvent
{
    public string RegionId;
    public string EventId;
    public DateTime WallClockTimestamp; // 발생 리전의 시스템 시각
    public string Description;
}

public sealed class GlobalEventAggregator
{
    private readonly List<RegionEvent> _buffer = new();

    // 각 리전 서버로부터 이벤트를 수신할 때마다 호출된다.
    public void OnEventReceived(RegionEvent evt)
    {
        _buffer.Add(evt); // (A) 수신 순서와 무관하게 일단 버퍼에 쌓는다.
    }

    // 일정 주기로 호출되어, 지금까지 쌓인 이벤트를 "일어난 순서"로 처리한다.
    public List<RegionEvent> DrainInOrder()
    {
        // (B) 리전별 시스템 시각(wall-clock) 만으로 전역 순서를 재구성한다.
        var ordered = _buffer.OrderBy(e => e.WallClockTimestamp).ToList();
        _buffer.Clear();
        return ordered;
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.