2부 분류 글에서 현실의 가장 흥미로운 시뮬레이션은 동적·이산·확률적의 조합, 즉 이산사건 시뮬레이션(Discrete-Event Simulation, DES)이라고 했다. 이제 그 DES가 실제로 어떻게 시간을 전진시키고 시스템을 모방하는지, 그 내부 메커니즘과 사고방식으로 들어간다. 이 글은 3부 전체(직접 구현·SimPy)의 개념적 토대다.

핵심 아이디어: 시간은 사건 단위로 점프한다

DES의 출발점은 단순한 관찰이다. 대부분의 시간 동안 시스템에는 아무 일도 일어나지 않는다. 은행 창구를 생각해 보자. 손님이 도착하는 순간, 서비스가 끝나는 순간 — 이런 *사건(event)*이 일어날 때만 시스템의 상태가 바뀐다. 그 사이 1초, 1분이 흐르는 동안 큐의 길이도 서버의 상태도 그대로다.

그렇다면 시간을 1초씩 꼬박꼬박 흘려보내며 “지금 무슨 일 있나?”를 매번 확인하는 것(이를 fixed-increment time advance라 한다)은 낭비다. 대신 DES는 다음 사건이 일어나는 시각으로 시계를 곧장 점프시킨다. 이것을 next-event time advance라 하며, DES의 심장이다. 아무 일도 없는 구간은 건너뛰고, 상태가 바뀌는 순간들만 골라 처리한다.

DES를 이루는 요소들

하나의 DES 모델은 다음 요소들로 기술된다. 은행 창구 예와 함께 보자.

  • entity(개체): 시스템을 흘러 다니는 객체. 손님, 작업(job), 부품 등. 각자 속성(attribute) — 도착 시각, 우선순위 등 — 을 가질 수 있다.
  • 사건(event): 시스템 상태를 바꾸는 순간적인 발생. “손님 도착”, “서비스 종료”처럼 시간 폭이 없다.
  • 활동(activity): 시간이 걸리는 과정. “서비스를 진행하는 중”은 시작 사건과 종료 사건 사이의 활동이다.
  • 자원(resource): entity가 점유하는, 용량이 제한된 것. 창구 직원(서버)이 대표적이다.
  • 큐(queue): 자원이 바빠 기다리는 entity들이 머무는 곳. FIFO·우선순위 등 규율(discipline)을 가진다.
  • 상태 변수(state variable): 시스템의 현재 상황을 담는 값. “큐에 몇 명 있나”, “서버가 바쁜가” 등.
  • 시뮬레이션 시계(simulation clock): 현재 모의 시각.
  • 미래사건 리스트(future event list, FEL): 앞으로 일어날 사건들을 시각 순으로 정렬해 둔 목록. DES 엔진의 핵심 자료구조다.

엔진의 동작은 이 한 문장으로 요약된다. FEL에서 가장 이른 사건을 꺼내 → 시계를 그 시각으로 옮기고 → 그 사건을 처리하며 상태를 바꾸고 새 사건을 FEL에 등록한다 → 이를 반복한다.

가장 단순한 예: 단일 서버 대기열

서버 하나짜리 대기열(M/M/1)을 보자. 사건은 단 두 종류다.

도착(arrival) 사건이 일어나면:

  1. 시스템 내 손님 수를 1 늘린다.
  2. 다음 도착 사건을 FEL에 등록한다(도착 간격만큼 뒤에).
  3. 서버가 비어 있으면 → 이 손님의 서비스를 시작하고, 그 종료(departure) 사건을 FEL에 등록한다(서비스 시간만큼 뒤에).
  4. 서버가 바쁘면 → 손님을 큐에 넣는다.

종료(departure) 사건이 일어나면:

  1. 시스템 내 손님 수를 1 줄인다(서비스 완료).
  2. 큐에 기다리는 손님이 있으면 → 다음 손님의 서비스를 시작하고 그 종료 사건을 등록한다.
  3. 큐가 비어 있으면 → 서버를 유휴(idle) 상태로 둔다.

여기서 도착 간격과 서비스 시간은 확률분포에서 샘플링한 난수다. 이 두 사건 처리 규칙만 있으면, 엔진이 FEL을 따라 사건을 꺼내 처리하며 시스템을 끝없이 모방한다. 이것을 코드로 옮기는 것이 다음다음 글이다.

세 가지 관점 (world view)

같은 시스템도 무엇을 중심으로 모델을 기술하느냐에 따라 세 가지 방식이 있다. 이것을 world view라 부른다.

  • 사건 중심(event-scheduling): 위 예처럼 사건마다 “이 사건이 일어나면 무엇을 할지”를 기술한다. FEL을 직접 다루는 가장 기본적인 방식으로, 엔진의 작동 원리가 그대로 드러난다. 8번 글에서 이 방식으로 직접 구현한다.
  • 프로세스 중심(process-interaction): entity 하나의 생애 전체를 하나의 흐름으로 기술한다. “손님은 도착해서 → 줄 서서 기다리고 → 서비스를 받고 → 떠난다”를 한 편의 시나리오처럼 적는다. 사람이 읽기에 가장 자연스러워 현대 도구(SimPy 등)가 채택한 방식이며, 9번 글에서 다룬다.
  • 활동 중심(activity-scanning): “어떤 조건이 만족되면 어떤 활동을 시작한다”는 규칙들로 기술한다. 조건 기반이라 유연하지만 매 시점 조건을 훑어야 해 비효율적일 수 있고, 오늘날 상대적으로 덜 쓰인다.

세 관점은 표현 방식이 다를 뿐, 내부에서는 모두 같은 next-event 엔진으로 귀결된다. 프로세스 중심의 기다린다도 결국 FEL에 사건을 등록하고 깨어나는 것으로 구현된다.

통계는 어떻게 모으나

DES의 목적은 결국 성능 지표를 얻는 것이다. 그런데 1부에서 강조했듯, 결과는 하나의 표본이라 신중히 모아야 한다. 두 종류의 양을 구분하면 편하다.

  • 시간 평균(time-average): “평균 큐 길이”처럼 시간에 대해 평균 내는 양. 큐 길이가 값 인 채로 머문 시간을 모두 누적해(상태 변수 × 머문 시간의 합), 총 시간으로 나눈다. 즉 시간-상태 그래프 아래의 면적을 시간으로 나눈 것이다.
  • 개체 평균(observation-based): “평균 대기시간”처럼 entity마다 하나씩 관측해 평균 내는 양. 떠나는 손님마다 체류시간을 기록해 평균한다.

이 둘은 다음 글의 큐잉 이론에서 각각 (시간 평균 손님 수)과 (개체 평균 체류시간)로 등장하며, 둘을 잇는 것이 그 유명한 Little’s law다.

정리

  • DES는 상태가 사건에서만 바뀐다는 관찰에 기반해, 시계를 다음 사건 시각으로 점프시키는 next-event time advance로 동작한다.
  • 모델은 entity·사건·활동·자원·큐·상태 변수·시뮬레이션 시계·미래사건 리스트(FEL)로 기술된다. 엔진은 “FEL에서 가장 이른 사건을 꺼내 처리하고 새 사건을 등록”하기를 반복한다.
  • 단일 서버 대기열은 도착·종료 두 사건의 처리 규칙만으로 모델링된다.
  • 같은 시스템을 사건 중심 / 프로세스 중심 / 활동 중심으로 기술할 수 있으며, 모두 같은 엔진으로 귀결된다.
  • 통계는 시간 평균(면적 기반)과 개체 평균(관측 기반)으로 나눠 모은다.

다음 글에서는 이렇게 만든 시뮬레이터가 맞게 동작하는지 검증할 기준선을 주는 큐잉 이론을 최소한으로 짚는다.