
스코프 크립 방지: 기능 버리기(Kill List)의 기술
게임의 완성도를 지키려면 새 기능을 잘 고르는 일만큼 이미 잡은 기능을 과감히 버리는 일이 중요하다. Unity와 Unreal 프로젝트에서 바로 적용할 수 있는 Kill List 운영 기준과 기술적 정리 방법을 다룬다.
스코프 크립은 대개 ‘나쁜 아이디어’에서 시작되지 않는다
스코프 크립은 프로젝트의 목표와 작업량이 조금씩 팽창하는 현상이다. 문제는 추가되는 기능이 대개 그럴듯하다는 데 있다. 제작 중인 전투에 날씨 효과를 붙이고 싶고 NPC마다 고유 일과를 주고 싶고 협동 모드도 언젠가는 넣고 싶어진다. 각각만 보면 게임을 더 좋아 보이게 만든다.
하지만 게임은 기능의 합계가 아니다. 플레이어가 반복해서 경험하는 핵심 루프와 그 루프를 완성도 있게 뒷받침하는 콘텐츠의 조합이다. 기능 하나를 추가하면 구현 시간뿐 아니라 UI, 저장 데이터, 밸런싱, QA, 현지화, 튜토리얼, 플랫폼 인증까지 연쇄 비용이 생긴다.
킬 리스트는 이 비용을 무시하지 않기 위한 문서다. ‘절대 만들지 않을 것’의 선언이라기보다 현재 출시 목표를 지키기 위해 의식적으로 보류하거나 제거한 항목의 목록이다.
백로그와 킬 리스트는 역할이 다르다
백로그는 언젠가 할 수 있는 일을 모으는 곳이다. 반면 킬 리스트는 현재 버전에서 하지 않기로 결정한 일을 기록한다. 둘을 구분하지 않으면 보류한 기능이 회의 때마다 다시 살아나고 이미 끝난 논의가 반복된다.
킬 리스트의 각 항목에는 최소한 다음 정보를 남긴다.
- 기능 이름과 한 줄 설명
- 제거 또는 보류한 이유
- 영향을 받는 시스템
- 재검토 조건
- 결정한 날짜와 담당자
예를 들어 “절차 생성 던전”을 단순히 제외라고만 적어 두면 다음 회의에서 다시 논의하게 된다. 대신 “수작업 스테이지 12개를 완성하는 일정과 충돌하며 레벨 디자인 도구가 안정화되지 않았다. 출시 후 콘텐츠 제작 비용이 병목으로 확인될 때만 재검토한다”라고 기록하면 판단의 맥락이 남는다.
먼저 버전의 성공 조건을 한 문장으로 고정한다
Kill List는 기준이 없으면 감정적인 우선순위 표가 된다. 기능을 판단하기 전에 현재 빌드의 성공 조건을 짧고 측정 가능하게 정한다.
예를 들어 로그라이크 액션 게임의 데모 목표를 다음처럼 쓸 수 있다.
신규 플레이어가 10분 안에 전투와 성장 선택의 재미를 이해하고 오류 없이 한 판을 끝낼 수 있다.
이 목표라면 코스튬 제작, 업적, 온라인 순위표는 흥미로운 기능이어도 데모의 핵심 흐름을 직접 강화하지 않는다. 반면 피격 피드백 개선이나 보상 선택 UI는 핵심 경험에 가깝다.
기능의 우선순위를 논의할 때는 “좋은 기능인가?” 대신 “이번 성공 조건을 더 잘 달성하게 하는가?”를 묻는다. 이 질문 하나가 기능 논의를 훨씬 구체적으로 만든다.

무엇을 버릴지 판단하는 기준
모든 기능에 정교한 산정 모델이 필요한 것은 아니다. 다만 기능 요청이 들어올 때 같은 질문을 반복하면 판단의 일관성이 생긴다.
- 이 기능이 현재 버전의 성공 조건에 직접 기여하는가?
- 완료 기준을 명확히 쓸 수 있는가?
- 숨은 의존성과 회귀 테스트 범위를 알고 있는가?
- 지금 만들지 않으면 검증할 수 없는 가설인가?
네 질문 중 하나라도 답이 흐리다면 Kill List 후보로 올린다. 특히 완료 기준을 쓸 수 없는 기능은 위험하다. “전투를 더 손맛 나게 한다”는 목표이고 “첫 타격부터 100ms 안에 명확한 타격음과 피격 애니메이션이 재생된다”는 검증 가능한 완료 기준이다.
간단한 비교가 필요하면 기대 효과와 비용을 같은 척도로 적는다. 수치 자체의 정확성보다 팀이 어떤 가정을 두었는지 드러내는 데 목적이 있다.
점수가 낮다고 자동으로 삭제할 필요는 없다. 다만 낮은 점수의 기능은 명시적으로 보류하고 높은 점수의 기능이 끝난 뒤에만 다시 검토한다.
킬 리스트를 만드는 회의 진행법
회의의 목표는 아이디어를 평가하는 것이 아니라 이번 버전의 범위를 확정하는 것이다. 기획자, 프로그래머, 아트 담당자가 함께 45분에서 60분 정도 시간을 정하고 기능 목록을 빠르게 분류한다.
기능 논의가 길어지는 이유는 대개 기준이 회의 도중에 바뀌기 때문이다. 아래처럼 흐름을 문서에 넣어 두면 요청자가 왜 보류되었는지도 이해하기 쉽다.
flowchart TD
A[기능 제안] --> B{핵심 루프에 직접 기여하는가?}
B -- 예 --> C{출시 일정 안에 검증 가능한가?}
B -- 아니오 --> D[킬 리스트 또는 후속 업데이트 후보]
C -- 예 --> E[현재 범위에 포함]
C -- 아니오 --> F{작게 쪼개도 가치가 남는가?}
F -- 예 --> G[최소 버전으로 축소]
F -- 아니오 --> D
판정이 애매한 기능은 ‘추가’와 ‘삭제’의 이분법으로 다루지 않는 편이 좋다. 최소 버전으로 축소할 수 있는지 먼저 확인한다. 예를 들어 무기 내구도 시스템이 필요해 보인다면 수리 재료와 상점 경제까지 동시에 만들기보다 특정 무기에만 과열 게이지를 적용하는 방식으로 핵심 의도를 시험할 수 있다.
회의가 끝나면 킬 리스트를 팀이 보는 작업 보드나 저장소 문서에 바로 반영한다. 누군가 기능을 다시 제안할 때는 새 문서부터 만들기보다 기존 항목의 재검토 조건이 충족됐는지 확인한다.
‘지금 안 함’과 ‘영원히 안 함’을 구분하라
킬 리스트가 아이디어 묘지가 될 필요는 없다. 보류 항목에는 재검토 시점을 붙일 수 있다. 다만 재검토 조건은 감상이 아니라 관측 가능한 사실이어야 한다.
좋은 조건은 다음과 같다.
- 플레이테스트에서 현재 핵심 루프의 이탈 원인이 반복해서 확인된다.
- 제작 파이프라인이 안정되어 추가 콘텐츠를 만들 여력이 생긴다.
- 데모 또는 얼리 액세스 데이터가 특정 기능에 대한 명확한 수요를 보여 준다.
- 해당 기능에 필요한 외부 서비스나 기술의 비용과 위험이 수용 가능한 수준으로 낮아진다.
반대로 “시간이 나면”, “게임이 더 풍부해 보이면” 같은 조건은 결정을 미루는 표현에 가깝다. 출시 후 업데이트 후보라면 기능 자체가 아니라 플레이어 문제와 검증 방법까지 함께 적어 두는 편이 낫다.
기술 부채까지 함께 계산한다
기능 하나의 비용은 코드 작성 시간으로 끝나지 않는다. 시스템 경계를 흐리게 만드는 기능은 이후 모든 변경의 비용을 올린다.
Unity에서는 임시 분기가 여러 컴포넌트에 퍼지는 순간 위험 신호가 보인다. 다음 코드는 이벤트 기념 규칙을 전투 로직에 직접 섞은 예다.
public int CalculateDamage(int baseDamage)
{
var damage = baseDamage;
if (isHalloweenEvent)
{
damage += 5;
}
if (playerOwnsFounderPack)
{
damage += 3;
}
return damage;
}
이 코드는 당장 동작하지만 이벤트가 끝난 뒤에도 규칙이 남고 테스트 조합이 계속 늘어난다. 해당 기능을 Kill List에 넣거나 독립된 규칙 객체로 분리해야 한다. 정말 필요한 규칙이라면 데이터로 선언하고 전투 코드는 그 데이터를 해석하게 만든다.
using UnityEngine;
[CreateAssetMenu(menuName = "Combat/Damage Modifier")]
public class DamageModifier : ScriptableObject
{
public int flatBonus;
public bool IsActive(PlayerProfile profile) => profile.HasFounderPack;
}
public int CalculateDamage(int baseDamage, DamageModifier[] modifiers, PlayerProfile profile)
{
var damage = baseDamage;
foreach (var modifier in modifiers)
{
if (modifier.IsActive(profile))
{
damage += modifier.flatBonus;
}
}
return damage;
}
Unreal Engine에서도 같은 원칙이 적용된다. 블루프린트 그래프에 기간 한정 규칙과 예외 처리가 계속 추가된다면 Gameplay Tag, Data Asset, Data Table처럼 규칙을 데이터 중심으로 분리할 수 있는지 먼저 검토한다. 분리 비용이 크고 현재 목표와 무관하다면 기능 자체를 보류하는 편이 안전하다.

코드와 데이터도 함께 버려야 한다
기능을 기획에서만 제거하고 코드에 실험용 플래그, 미사용 에셋, 반쯤 연결된 데이터 구조를 남겨 두면 나중에 비용을 다시 낸다. 킬 리스트에 오른 기능이 MVP에 들어가 있었다면 관련 브랜치와 작업 항목을 정리하고 의존성이 남았는지 확인한다.
예를 들어 장비 내구도 기능을 제거했다면 아이템 데이터에서 내구도 값이 선택 사항으로 남아 있는지 검토한다. 출시 버전에서 쓰지 않는다면 데이터를 단순화하는 편이 이후 밸런싱과 저장 파일 검증에 유리하다.
type Item = {
id: string;
name: string;
attack: number;
// 출시 범위에서 내구도 기능을 제외했다면
// durability 같은 필드는 남기지 않는다.
};
이 원칙은 되돌릴 수 없는 삭제를 뜻하지 않는다. 제거한 기능의 설계 메모와 실험 결과는 별도 문서에 보존할 수 있다. 중요한 것은 현재 제품의 코드와 데이터 모델이 현재 범위를 정직하게 반영하도록 만드는 일이다.
스프린트 종료 때 제거 비용을 따로 배정한다
이미 작업을 시작한 기능을 중단할 때는 코드와 에셋을 정리해야 한다. 이 단계를 생략하면 비활성 플래그, 쓰이지 않는 주소 지정 에셋, 죽은 UI 경로가 남아 다음 기능의 판단을 방해한다.
기능을 중단한 뒤에는 다음을 확인한다.
- 연결된 입력, UI 진입점, 튜토리얼 문구를 제거한다.
- 저장 데이터 변경이 있었다면 이전 세이브와 새 세이브의 호환성을 확인한다.
- 더 이상 호출되지 않는 이벤트와 구독 해제를 정리한다.
- 자동 테스트와 수동 테스트 목록에서 폐기된 경로를 제거하거나 수정한다.
- 왜 중단했는지 Kill List에 남긴다.
Git을 사용한다면 실험 기능은 가능한 한 작은 브랜치와 작은 커밋으로 만든다. 실험이 실패했을 때 되돌리기 쉬우며 유지할 부분만 골라 옮길 수도 있다. 다만 공유 브랜치에서 이미 다른 작업이 의존하는 변경을 단순히 되돌리면 충돌과 회귀가 생길 수 있으므로 영향 범위를 먼저 확인해야 한다.
Kill List를 실제 작업 흐름에 활용하기
문서만 만들어 두면 기능은 다시 백로그로 돌아오기 쉽다. 이슈 트래커나 작업 보드에 kill-list 또는 deferred 라벨을 두고 일반 백로그와 분리해서 관리한다.
다음 형식은 작은 팀에서도 충분히 쓸 수 있다.
### 적 처치 연출 카메라
- 상태: 보류
- 이유: 현재 데모의 전투 가독성을 먼저 검증해야 함
- 예상 영향: 카메라 제어, 접근성 옵션, 멀미 대응, 리플레이 테스트
- 재검토 조건: 기본 타격 피드백 테스트에서 타격 인지가 부족하다는 결과가 나올 때
- 결정일: 2026-07-28
재검토 조건이 특히 중요하다. “나중에”는 일정이 없다는 뜻이지만 “접근성 테스트에서 문제 발견 시”는 다시 열어 볼 근거가 된다. 기능을 버렸다는 결정도 나중에 검증할 수 있어야 한다.
킬 리스트를 출시 도구로 쓰는 법
마일스톤마다 킬 리스트를 짧게 검토한다. 이때 질문은 “무엇을 다시 넣을까?”보다 “새로 늘어난 범위는 무엇이며 무엇을 빼서 균형을 맞출까?”가 되어야 한다. 기능 하나가 들어오면 비슷한 규모의 기능 하나가 나가는 교환 규칙도 효과적이다.
훌륭한 킬 리스트는 팀의 창의성을 줄이지 않는다. 아이디어를 거절하는 대신 현재 목표에 맞는 시점으로 옮겨 준다. 작은 팀일수록 모든 좋은 생각을 구현하려 하기보다 가장 중요한 몇 가지를 끝까지 다듬는 편이 게임의 완성도를 높인다.
출시 가능한 범위는 제한이 아니라 선택의 결과다. 킬 리스트는 그 선택을 기록하고 지키는 가장 단순한 장치다.
버리는 능력이 출시 속도를 높인다
Kill List의 목표는 기능 수를 줄이는 데 있지 않다. 플레이어가 실제로 경험하는 핵심 루프에 시간과 테스트를 집중하는 데 있다. 새 기능을 제안할 때마다 성공 조건, 완료 기준, 숨은 비용, 재검토 조건을 함께 적어 보자.
그 과정을 거쳐 보류된 기능은 실패가 아니다. 현재 게임이 끝까지 완성될 가능성을 높인 설계 결정이다.


