Quick Reference
개방-폐쇄 원칙은 switch를 무조건 없애는 규칙이 아니라, 새 variation이 자주 생기는 중심 규칙을 덜 수정하게 하는 구조입니다. Unity에서는 strategy를 Inspector에 넣는 방법도 다릅니다. 일반 interface field는 기본 직렬화되지 않으며, ScriptableObject asset, [SerializeReference] managed object, runtime composition은 서로 다른 lifecycle을 가집니다.
| 확장 방식 | Unity 저장·수명 | 맞는 경우 |
|---|---|---|
| ScriptableObject strategy | asset reference, shared definition | designer가 고르는 읽기 전용 행동 definition |
[SerializeReference] strategy | managed non-UnityEngine.Object reference | object graph를 component 안에 저장 |
| runtime DI/registry | scene·service가 생성 | context·network·async dependency가 필요한 행동 |
| enum/switch | code branch | type 수가 작고 안정적인 규칙 |
public abstract class DamageRule : ScriptableObject
{
public abstract int Calculate(DamageRequest request);
}
public sealed class Weapon : MonoBehaviour
{
[SerializeField] private DamageRule rule;
public int Deal(DamageRequest request) => rule.Calculate(request);
}확장 압력을 먼저 찾기
새 weapon·skill·AI behavior가 추가될 때마다 central switch와 여러 call site를 고쳐야 하면 variation 축을 분리할 후보입니다. 반대로 damage multiplier 숫자만 다른 data change까지 class를 늘리면 file 수만 증가합니다. algorithm이 달라지는지, data만 달라지는지, 새 implementation을 누가 선택하는지가 먼저입니다.
strategy·factory·command·state는 확장을 돕는 도구이고 등록·composition 지점이 없다면 결국 다른 switch로 돌아갑니다. registry가 unknown key를 받으면 fail, fallback, content error 중 무엇을 할지와 asset validation을 함께 둡니다.
Inspector와 runtime의 경계
Unity 기본 serializer는 일반 interface field나 list를 그대로 Inspector에 저장하지 않습니다. [SerializeReference]는 managed non-UnityEngine.Object implementation을 참조형으로 직렬화하는 선택지이며, MonoBehaviour와 ScriptableObject asset을 같은 방식으로 저장하는 기능이 아닙니다. ScriptableObject strategy는 shared authoring definition이므로 actor별 mutable cooldown·target·execution state는 runtime instance에 둡니다.
runtime DI는 context에 따라 behavior를 고를 수 있지만 scene unload·cancel·dispose owner가 필요합니다. Inspector에서 보인다는 이유로 runtime-ready·validation 완료를 보장한다고 가정하지 않습니다.
단순함을 남기기
확장 압력이 없는 작은 switch는 가장 읽기 쉬운 구현일 수 있습니다. variation이 실제로 반복되는 path만 추상화하고, base contract에 새로운 rule을 추가할 때 기존 implementation과 consumer test가 유지되는지 확인합니다. OCP는 변화가 없는 code를 금지하는 원칙이 아닙니다.
interface 목록을 Inspector에 연결할 수 있다고 가정하면 Unity serialization과 runtime lifecycle이 어긋납니다. strategy의 저장 방식과 instance state owner를 먼저 고른 뒤 확장 구조를 만드세요.
참고 링크
2 sources