게임 출시일 예측을 위한 몬테카를로 시뮬레이션: 마일스톤 일정의 불확실성과 신뢰구간 계산

마일스톤별 낙관·최빈·비관 기간을 몬테카를로 시뮬레이션으로 조합해 P50·P80·P90 출시일을 계산하고 일정 리스크와 우선순위를 운영에 반영하는 방법을 설명합니다.

✓ 복사 완료!
챕터마일스톤 & 스코프 관리
난이도중급
상태● 검토 완료
대상 엔진
Engine Agnostic
최종 업데이트
게임 출시일 예측을 위한 몬테카를로 시뮬레이션: 마일스톤 일정의 불확실성과 신뢰구간 계산

핵심 요약

마일스톤의 완료일을 하나의 확정값으로 적지 말고 각 작업의 낙관값·최빈값·비관값으로 확률분포를 만든 뒤 몬테카를로 시뮬레이션으로 전체 출시일을 계산합니다. 반복 실행 결과의 P50·P80·P90 백분위수를 함께 제시하면 “가장 가능성 높은 날짜”와 “이 날짜까지 끝날 확률”을 구분해 의사결정할 수 있습니다.

실무에서 이를 출시일 신뢰구간이라고 부르지만 단일 프로젝트의 미래 완료일을 설명하는 값은 엄밀히 말해 예측구간에 가깝습니다. 따라서 “8월 30일에 출시한다”보다 “8월 30일까지 출시할 확률은 80%”처럼 확률과 가정을 함께 기록해야 합니다.

마일스톤 일정은 왜 한 날짜가 아니라 확률분포인가?

게임 개발 일정의 오차는 단순히 작업 속도가 느려서만 생기지 않습니다. 기능의 완료 조건이 바뀌거나 외부 SDK 연동이 지연되고 QA에서 재작업이 발생하거나 특정 담당자에게 의존한 작업이 밀리면서 여러 오차가 누적됩니다.

예를 들어 전투 튜토리얼 작업을 5일로 적었다고 하겠습니다. 실제로는 다음과 같은 범위를 가질 수 있습니다.

값의미예시
낙관값 O막힘 없이 진행될 때의 기간3일
최빈값 M현재 정보에서 가장 가능성이 높은 기간5일
비관값 P알려진 리스크가 발생했을 때의 기간10일

이 세 값을 하나의 숫자로 평균 내면 일정의 꼬리 위험이 사라집니다. 반면 확률분포로 유지하면 “대부분의 작업은 5일이지만 10일까지 늘어날 가능성도 있다”는 정보를 전체 계획에 전달할 수 있습니다.

특히 다음 조건에서는 확률 기반 일정이 효과적입니다.

  • 신규 시스템이나 처음 사용하는 엔진 기능이 포함되어 있을 때
  • 기획·아트·클라이언트·서버·QA 사이에 의존성이 있을 때
  • 외부 인증, 스토어 심사, SDK, 번역처럼 팀 밖의 일정이 있을 때
  • 출시 전 버그 수정과 회귀 테스트의 양을 미리 확정하기 어려울 때
  • 경영진이나 퍼블리셔에게 목표일과 리스크를 함께 설명해야 할 때

몬테카를로 일정 예측은 어떻게 동작하는가?

몬테카를로 시뮬레이션은 각 작업의 기간분포에서 무작위 표본을 뽑고 전체 일정을 여러 번 계산하는 방법입니다. 한 번의 계산은 특정한 시나리오 하나를 뜻합니다. 수천에서 수만 개의 시나리오를 모으면 출시일의 분포를 얻을 수 있습니다.

작업 i의 기간을 삼각분포로 모델링하면 다음처럼 쓸 수 있습니다.

Xi∼Triangular⁡(Oi,Mi,Pi)X_i \sim \operatorname{Triangular}(O_i, M_i, P_i)

의존성이 순차적인 작업들의 총 기간은 다음과 같이 계산합니다.

T=T0+∑i=1nXi+BT = T_0 + \sum_{i=1}^{n} X_i + B

여기서 T0T_0는 시뮬레이션 시작일이고 BB는 명시적으로 분리한 버퍼 또는 외부 대기 기간입니다. 시뮬레이션 결과 TT를 오름차순으로 정렬한 뒤 특정 백분위수의 날짜를 읽으면 P50, P80, P90을 얻을 수 있습니다.

지표해석운영 용도
P50이 날짜 이전에 끝날 확률이 50%기준 시나리오, 내부 계획
P80이 날짜 이전에 끝날 확률이 80%대외 약속 후보, 리스크가 큰 프로젝트
P90이 날짜 이전에 끝날 확률이 90%보수적 약속, 출시 창구와 심사 일정 반영

P80은 “80% 확률로 정확히 그날 출시된다”는 뜻이 아닙니다. “시뮬레이션의 가정이 유지될 때 그 날짜 또는 그 이전에 완료될 확률이 80%”라는 뜻입니다.

출시일 예측을 어떻게 모델링할까?

1단계: 일정의 기본 단위를 정한다

먼저 에픽이나 거대한 마일스톤을 그대로 확률화하지 말고 0.5~5일 정도로 추정 가능한 작업 패키지로 나눕니다. 예를 들면 “온라인 협동 기능 완성” 대신 다음처럼 나눌 수 있습니다.

  • 세션 생성과 참가 API
  • 매치 상태 동기화
  • 연결 종료 처리
  • 실패 케이스 로깅
  • QA 테스트 케이스 작성과 실행

작업이 너무 크면 낙관값·최빈값·비관값의 근거를 설명하기 어렵습니다. 반대로 너무 작게 쪼개면 모든 작업을 독립 사건으로 가정하는 오류가 커지고 유지 비용이 늘어납니다.

2단계: 세 점 추정값과 근거를 기록한다

각 작업에 O, M, P를 입력하되 숫자만 저장하지 않습니다. 왜 비관값이 커졌는지 함께 기록해야 다음 스프린트에서 분포를 조정할 수 있습니다.

작업OMP주요 리스크의존성
세션 생성 API1일2일5일인증 토큰 규격 변경서버 인증
상태 동기화2일4일8일패킷 손실 재현 난이도세션 생성
연결 종료 처리1일2일4일모바일 백그라운드 전환상태 동기화
회귀 테스트2일4일9일기존 모드 영향전체 기능

세 점 추정은 근거 없는 낙관을 줄이는 데 유용하지만 만능은 아닙니다. P 값에 “상당히 드문 최악의 경우”를 넣으면 분포가 과도하게 넓어지고 팀이 날짜를 해석하기 어려워집니다. P는 알려진 리스크가 현실화된 합리적인 비관 시나리오로 정의하는 편이 좋습니다.

3단계: 작업 의존성과 병렬 실행을 반영한다

모든 기간을 단순 합산하면 병렬로 진행할 수 있는 작업을 놓칩니다. 작업 그래프의 선행 조건을 반영해 각 시나리오에서 작업의 시작일과 종료일을 계산해야 합니다.

예를 들어 기획 검토가 끝난 뒤 클라이언트 구현과 서버 구현을 병렬로 시작할 수 있다면 두 작업의 기간을 더하지 않고 더 긴 쪽을 다음 단계의 선행 기간으로 사용합니다.

Finish(k)=Duration(k)+max⁡p∈Predecessors(k)Finish(p)Finish(k) = Duration(k) + \max_{p \in Predecessors(k)} Finish(p)

여기서 Predecessors(k)Predecessors(k)는 작업 k의 선행 작업 집합입니다. 실제 운영에서는 작업별 담당자 수와 공유 자원도 함께 확인해야 합니다. 서버 담당자가 여러 작업을 동시에 수행할 수 없다면 겉보기에는 병렬인 작업도 자원 제약 때문에 순차화될 수 있습니다.

4단계: 외부 대기와 출시 준비를 별도 항목으로 둔다

스토어 심사, 콘솔 인증, 번역 납품, 법무 검토, 마케팅 빌드 전달은 개발 작업과 분포 특성이 다릅니다. 이 항목을 개발 작업의 비관값에 몰아넣으면 어떤 리스크를 줄여야 하는지 보이지 않습니다.

다음과 같이 분리하면 운영이 쉬워집니다.

  • 개발 완료까지의 분포
  • 콘텐츠 락 이후의 버그 수정 분포
  • 플랫폼·스토어 심사 대기 분포
  • 출시 후보 빌드 승인 대기 분포

출시일은 마지막 개발 작업의 완료일이 아니라 이 모든 게이트를 통과한 날짜로 정의해야 합니다.

TypeScript로 일정 몬테카를로 시뮬레이션 구현하기

아래 예시는 작업들이 순차적으로 진행되는 단순한 경우입니다. 실제 프로젝트에서는 DAG 형태의 의존성 계산과 휴일·근무일 캘린더를 추가해야 합니다.

type Estimate = {
  name: string;
  optimistic: number;
  mostLikely: number;
  pessimistic: number;
};

function triangularSample(o: number, m: number, p: number): number {
  const u = Math.random();
  const split = (m - o) / (p - o);

  if (u < split) {
    return o + Math.sqrt(u * (p - o) * (m - o));
  }

  return p - Math.sqrt((1 - u) * (p - o) * (p - m));
}

function percentile(values: number[], q: number): number {
  const sorted = [...values].sort((a, b) => a - b);
  const index = Math.ceil(q * sorted.length) - 1;
  return sorted[Math.max(0, index)];
}

function simulate(tasks: Estimate[], iterations = 10000) {
  const totals: number[] = [];

  for (let i = 0; i < iterations; i += 1) {
    const total = tasks.reduce(
      (sum, task) =>
        sum + triangularSample(
          task.optimistic,
          task.mostLikely,
          task.pessimistic,
        ),
      0,
    );

    totals.push(total);
  }

  return {
    p50: percentile(totals, 0.5),
    p80: percentile(totals, 0.8),
    p90: percentile(totals, 0.9),
    samples: totals,
  };
}

이 코드에서 Math.random()은 재현 가능한 난수 생성기가 아닙니다. 운영 리포트나 일정 변경 전후 비교가 필요하다면 시드(seed)를 지원하는 의사난수 생성기를 사용하고 시뮬레이션 입력과 시드를 함께 저장하는 편이 좋습니다. 또한 실제 날짜로 변환할 때는 주말, 공휴일, 팀별 근무일, 휴가를 별도의 캘린더 규칙으로 처리해야 합니다.

삼각분포가 적합하지 않은 경우도 있습니다. 과거 작업 데이터가 충분하다면 실제 완료 기간의 경험적 분포를 사용하는 편이 더 낫습니다. 데이터가 적고 전문가 추정만 가능한 초기 단계에서는 삼각분포나 PERT 분포를 사용하되 어떤 분포를 선택했는지 문서화해야 합니다.

결과를 출시 의사결정에 어떻게 연결할까?

시뮬레이션 결과는 날짜 하나로 끝내지 말고 분포와 민감도를 함께 봐야 합니다. 예를 들어 다음과 같은 결과가 나왔다고 가정해 보겠습니다.

결과날짜 또는 기간해석
P509월 12일절반의 시나리오가 이 날짜 이전에 완료
P809월 26일80%의 시나리오가 이 날짜 이전에 완료
P9010월 3일보수적 출시 창구
P90-P5021일일정 꼬리 위험의 크기

이 경우 9월 12일을 목표일로 사용할 수는 있지만 9월 12일을 확정 약속으로 표현하면 안 됩니다. 외부 공개일이 반드시 필요하다면 P80 또는 P90을 기준으로 정하고 남은 기간에 어떤 범위의 스코프를 보장할지 함께 정해야 합니다.

일정 분산을 키우는 작업을 찾는다

각 작업을 제거하거나 기간을 줄였을 때 P80이 얼마나 변하는지 비교하면 우선순위를 정할 수 있습니다. 이를 민감도 분석이라고 합니다.

분석 질문의사결정 예시
어떤 작업을 먼저 검증하면 P80이 가장 줄어드는가?기술 스파이크를 먼저 배치
어떤 작업의 P 값이 전체 분포를 가장 넓히는가?전담 인력 배정 또는 범위 축소
어떤 외부 대기가 출시일을 지배하는가?심사 제출일을 앞당김
어떤 기능을 제외해도 핵심 경험이 유지되는가?출시 후 업데이트로 이동

단순히 기간이 가장 긴 작업이 항상 가장 중요한 것은 아닙니다. 이미 병렬 경로에 묻힌 긴 작업보다 크리티컬 패스에 있는 불확실한 작업이 출시일에 더 큰 영향을 줄 수 있습니다.

확률을 스코프와 교환한다

일정이 목표를 벗어날 가능성이 높다면 팀에 “더 빨리 해 달라”고 요청하는 것만으로는 분포가 좁아지지 않습니다. 다음 세 가지 중 무엇을 바꿀지 결정해야 합니다.

  1. 스코프를 줄여 작업 수와 의존성을 낮춘다.
  2. 불확실한 작업을 기술 검증과 프로토타입으로 앞당긴다.
  3. 출시일을 유지하고 P80 기준의 보수적 출시 창구를 선택한다.

이 결정을 문서에 남길 때는 변경 전후의 P50·P80·P90을 함께 기록합니다. 예를 들어 “랭크전 시즌 보상을 출시 후 업데이트로 이동한 결과 P80이 18일에서 11일로 줄었다”처럼 쓰면 우선순위의 효과를 검토할 수 있습니다.

마일스톤별 완료 기간 분포와 P50·P80·P90 출시일을 보여주는 일정 리스크 대시보드

운영 문서에는 무엇을 기록해야 하는가?

몬테카를로 결과는 입력이 바뀌면 달라집니다. 따라서 결과보다 가정의 변경 이력을 관리하는 것이 중요합니다.

최소한 다음 항목을 문서화합니다.

  • 시뮬레이션 기준일과 출시일 정의
  • 작업 목록, 작업 간 의존성, 담당 역할
  • 각 작업의 O·M·P 추정값과 추정 근거
  • 사용한 분포와 난수 시드
  • 반복 횟수와 날짜 변환 규칙
  • 외부 대기와 휴일·휴가 처리 방식
  • P50·P80·P90 결과
  • 민감도 분석 결과
  • 스코프 변경 전후 비교
  • 다음 업데이트 조건과 담당자

스프레드시트로 시작해도 괜찮지만 수동 복사로 날짜를 갱신하면 입력과 결과가 분리됩니다. 가능하면 작업 데이터는 CSV나 JSON으로 관리하고 시뮬레이션 스크립트가 결과 리포트를 생성하도록 구성합니다. 중요한 것은 도구의 규모가 아니라 같은 입력으로 같은 해석을 재현할 수 있는가입니다.

일정 예측이 실패하는 대표적인 이유는 무엇인가?

모든 작업을 독립적으로 가정한다

아트 검수 지연이 클라이언트 구현 지연을 유발하는 것처럼 작업 기간 사이에는 상관관계가 있습니다. 모든 작업을 독립 표본으로 뽑으면 이런 공동 위험을 과소평가할 수 있습니다. 공통 리스크가 있다면 별도의 리스크 변수로 모델링하거나 관련 작업의 기간을 같은 시나리오 요인에 연결해야 합니다.

버퍼를 이중으로 더한다

각 작업의 비관값에 이미 알려진 재작업이 포함되어 있는데 마지막에 큰 버퍼를 다시 더하면 일정이 과도하게 보수적으로 변합니다. 버퍼는 작업 분포에 포함된 위험과 별도로 어떤 불확실성을 담당하는지 명확히 해야 합니다.

추정값을 업데이트하지 않는다

프로토타입이 끝나고 기술 리스크가 줄었다면 P 값을 낮출 수 있습니다. 반대로 플랫폼 요구사항이 바뀌었거나 테스트 범위가 늘었다면 분포를 넓혀야 합니다. 매주 같은 숫자를 재사용하는 것은 시뮬레이션이 아니라 오래된 계획의 반복입니다.

P90을 확정일로 오해한다

P90도 10%의 시나리오에서는 넘을 수 있습니다. 특히 아직 발견하지 못한 리스크와 정책 변경은 기존 추정만으로 표현되지 않습니다. 공개 커뮤니케이션에서는 확률, 기준일, 제외 범위를 함께 말해야 합니다.

자주 묻는 질문 (FAQ)

몬테카를로 시뮬레이션에는 작업이 몇 개나 필요한가?

정해진 최소 개수는 없습니다. 핵심 마일스톤을 구성하는 작업과 외부 대기 항목부터 시작하고 추정 근거가 없는 세부 작업은 억지로 추가하지 않는 것이 좋습니다. 작은 모델로 시작해 실제 완료 데이터가 쌓일 때 확장하세요.

삼각분포와 PERT 분포 중 무엇을 사용해야 하는가?

초기 계획에서 낙관·최빈·비관값을 직관적으로 검토하려면 삼각분포가 간단합니다. 최빈값 주변에 더 많은 확률을 두고 싶다면 PERT 분포를 고려할 수 있습니다. 어느 쪽이든 팀의 과거 완료 데이터로 보정하고 선택한 이유를 기록해야 합니다.

출시일은 P50, P80, P90 중 무엇으로 약속해야 하는가?

내부 탐색 계획은 P50을 참고할 수 있지만 외부 약속은 실패 비용과 스코프 고정 수준에 따라 P80 또는 P90을 선택하는 편이 안전합니다. 단일 백분위수를 정답처럼 사용하지 말고 출시 창구, 스코프, 심사 일정과 함께 결정해야 합니다.

정리

몬테카를로 일정 예측의 핵심은 복잡한 수학이 아니라 불확실성을 숨기지 않는 운영 방식입니다. 작업을 적절한 단위로 나누고 O·M·P 근거를 기록한 뒤 의존성, 외부 대기, 공통 리스크를 반영하면 출시일을 단일 약속이 아닌 확률분포로 설명할 수 있습니다.

매주 입력값과 P50·P80·P90을 갱신하고 민감도가 큰 작업을 먼저 줄이세요. 그러면 일정 회의는 “왜 또 늦어졌는가?”를 추궁하는 자리가 아니라 “어떤 리스크와 스코프를 바꾸면 출시 확률이 개선되는가?”를 결정하는 운영 회의가 됩니다.