AI 코딩 도구를 게임 개발에 붙일 때 가장 위험한 작업은 의외로 새 기능 구현이 아니라 리팩터링이다. Claude Code, Cursor, Copilot 같은 도구는 파일을 빠르게 읽고 고치지만, 게임 프로젝트에서는 작은 구조 변경 하나가 프리팹 참조, 직렬화 필드, Addressables 키, 애니메이션 이벤트까지 건드릴 수 있다.
그래서 AI에게 “이 코드 정리해줘”라고 던지는 방식은 좋지 않다. 대신 변경 범위, 금지 영역, 검증 명령을 먼저 정해두고, AI가 그 안에서만 움직이게 만드는 워크플로우가 필요하다. 핵심은 AI를 똑똑한 개발자로 믿는 것이 아니라, 빠른 작업자에게 명확한 작업 계약서를 주는 것이다.
1. 리팩터링 전에 변경 범위 계약서를 만든다
AI에게 바로 코드를 수정시키기 전에 짧은 작업 계약을 먼저 작성한다. 이 문서는 프롬프트에 그대로 넣어도 되고, 프로젝트 루트에 AI_REFACTOR_SCOPE.md 같은 이름으로 둬도 된다.
# Refactor Scope
Goal:
- PlayerHealth의 체력 계산 로직을 테스트 가능한 순수 C# 클래스로 분리한다.
Allowed:
- Assets/Scripts/Player/PlayerHealth.cs
- Assets/Scripts/Player/HealthModel.cs
- Assets/Tests/EditMode/HealthModelTests.cs
Forbidden:
- Prefab, Scene, Animator, Addressables 설정 변경
- public serialized field 이름 변경
- 게임 밸런스 수치 변경
Validation:
- Unity EditMode Test 통과
- PlayerHealth의 Inspector 참조 유지
이 정도만 있어도 AI의 작업 품질이 크게 달라진다. 특히 Forbidden이 중요하다. Unity 프로젝트에서는 코드상으로 더 예쁜 이름이더라도 [SerializeField] private int maxHp; 같은 필드명을 바꾸면 기존 프리팹 데이터가 끊길 수 있다.
2. MonoBehaviour에서 순수 로직을 분리한다
AI에게 맡기기 좋은 리팩터링은 MonoBehaviour 안에 섞인 게임 규칙을 순수 클래스로 빼는 작업이다. 예를 들어 체력 감소, 회복, 사망 판정은 Unity API가 없어도 계산 가능하다.
using System;
public sealed class HealthModel
{
public int Current { get; private set; }
public int Max { get; }
public bool IsDead => Current <= 0;
public HealthModel(int max)
{
Max = Math.Max(1, max);
Current = Max;
}
public void Damage(int amount)
{
if (amount <= 0 || IsDead)
return;
Current = Math.Max(0, Current - amount);
}
public void Heal(int amount)
{
if (amount <= 0 || IsDead)
return;
Current = Math.Min(Max, Current + amount);
}
}
이런 형태는 Claude Code나 Cursor가 수정하기 쉽고, Copilot의 보완 제안도 비교적 안정적이다. Unity 생명주기 함수, 씬 오브젝트, 애니메이션 호출은 그대로 두고 계산 로직만 이동했기 때문이다.
3. Unity 쪽 클래스는 어댑터처럼 얇게 둔다
PlayerHealth는 게임 오브젝트와 순수 로직을 연결하는 역할만 맡긴다. 기존 직렬화 필드 이름은 유지하고, 외부 이벤트 호출 위치도 바꾸지 않는다.
using UnityEngine;
using UnityEngine.Events;
public sealed class PlayerHealth : MonoBehaviour
{
[SerializeField] private int maxHp = 100;
[SerializeField] private UnityEvent onDead;
private HealthModel health;
private void Awake()
{
health = new HealthModel(maxHp);
}
public void TakeDamage(int amount)
{
if (health.IsDead)
return;
health.Damage(amount);
if (health.IsDead)
onDead.Invoke();
}
}
AI에게 이 작업을 시킬 때는 “MonoBehaviour의 public API와 serialized field 이름을 유지하라”고 명시해야 한다. 게임 코드에서 API 안정성은 빌드 성공만큼 중요하다. 다른 스크립트, 타임라인, UnityEvent가 이 메서드 이름을 참조할 수 있기 때문이다.
4. 테스트를 먼저 요구하면 수정 폭이 줄어든다
리팩터링 요청에 테스트를 포함하면 AI가 구조를 더 보수적으로 잡는다. 아래처럼 순수 클래스에 대한 EditMode 테스트를 붙이면, 게임 실행 없이도 핵심 규칙을 확인할 수 있다.
using NUnit.Framework;
public sealed class HealthModelTests
{
[Test]
public void Damage_Clamps_Current_To_Zero()
{
var health = new HealthModel(100);
health.Damage(150);
Assert.AreEqual(0, health.Current);
Assert.IsTrue(health.IsDead);
}
[Test]
public void Heal_Does_Not_Revive_Dead_Character()
{
var health = new HealthModel(100);
health.Damage(100);
health.Heal(10);
Assert.AreEqual(0, health.Current);
}
}
여기서 중요한 점은 테스트가 많아야 한다는 뜻이 아니다. AI가 바꾸면 안 되는 게임 규칙을 테스트 이름으로 박아두는 것이다. “죽은 캐릭터는 회복으로 부활하지 않는다” 같은 규칙은 기획 의도이자 리팩터링 안전장치다.
5. 마지막은 diff gate로 막는다
AI가 작업을 끝냈다면 바로 머지하지 말고 변경 파일 목록을 먼저 본다. 계약서의 Allowed 밖 파일이 바뀌었다면 내용이 좋아 보여도 되돌리고 이유를 확인해야 한다.
실무에서는 다음 순서가 단순하고 효과적이다.
- AI에게 변경 계획만 먼저 받는다.
- 허용 파일을 지정하고 수정시킨다.
- 테스트와 컴파일을 돌린다.
- 변경 파일 목록을 확인한다.
- public API, serialized field, 씬 파일 변경 여부를 확인한다.
AI 도구는 리팩터링 속도를 크게 올려주지만, 프로젝트 구조 전체를 책임지는 주체는 여전히 개발자다. 변경 범위 계약, 순수 로직 분리, 테스트, diff gate를 묶으면 AI는 위험한 자동 수정기가 아니라 반복 작업을 줄여주는 실전 도구가 된다.
'AI 보조 게임 개발' 카테고리의 다른 글
| Claude Code, Cursor, Copilot을 갈아타도 작업이 이어지는 Unity 인수인계 규칙 5가지 (0) | 2026.07.15 |
|---|---|
| AI 코드 생성 도구로 Unity 테스트 보일러플레이트 없애기 (0) | 2026.07.10 |
| AI 에이전트로 Unity BatchMode 점검 봇 만들기: 씬 품질 리포트를 매일 자동 생성하기 (1) | 2026.07.03 |
| AI에게 Unity 성능 실험 루프 맡기기: 로그 수집부터 패치 후보까지 (0) | 2026.07.01 |
| AI 에이전트로 ScriptedImporter 만들기: 외부 포맷을 Unity 에셋으로 자동 변환하기 (0) | 2026.06.26 |