
Unity 6.5를 보다 보면 이런 Attribute가 보인다.
[AutoStaticsCleanup]
이건 이름만 봐도 어느 정도 이해가 된다.
static 값을 자동으로 정리해주는 기능이구나.
그런데 반대로 이런 것도 있다.
[NoAutoStaticsCleanup]
처음 봤을 때 조금 이상했다.
아니...
NoAutoStaticsCleanup을 안 붙이면 원래 자동 Cleanup 안 하는 거 아닌가?
실제로 간단한 코드만 보면 그렇게 느껴진다.
Unity에서 Enter Play Mode Options를 사용하면서 Reload Domain을 끄면 Play Mode에 들어갈 때마다 C# Domain을 새로 만들지 않는다.
덕분에 Play Mode 진입 속도는 빨라지지만 한 가지 문제가 생긴다.
바로 static 값이 그대로 남을 수 있다는 것이다.
예를 들어:
public static int Count = 0;
게임 실행 중에
Count = 100;
이 되었다고 해보자.
Domain Reload가 켜져 있다면 다음 Play Mode에서 다시
Count = 0
으로 시작한다.
하지만 Domain Reload를 꺼놓은 경우에는 이전 static 값이 그대로 남을 수 있다.
첫 번째 Play
Count = 0
↓ 실행 중
Count = 100
↓ Stop
↓ 다시 Play
Count = 100
개발 중에는 상당히 귀찮은 문제가 될 수 있다.
AutoStaticsCleanupUnity 6.5에서는 이런 static 값을 자동으로 초기화하기 위해 AutoStaticsCleanup을 사용할 수 있다.
[AutoStaticsCleanup]
public static int Count = 0;
이렇게 선언하면 Unity가 해당 static을 자동 Cleanup 대상으로 관리한다.
그래서 Domain Reload를 꺼놓더라도 다시 Play Mode에 들어가면 초기값으로 돌아간다.
첫 번째 Play
Count = 0
↓ 실행 중
Count = 100
↓ Stop
↓ 다시 Play
Count = 0
즉 간단하게 생각하면:
AutoStaticsCleanup= Domain Reload 없이도 static을 초기 상태로 돌려줘.
라고 보면 된다.
NoAutoStaticsCleanup은 왜 있는 걸까?여기서 조금 의문이 생긴다.
public static int Count;
이렇게 그냥 선언한 static도 기본적으로 AutoStaticsCleanup 대상이 아니다.
그런데 굳이
[NoAutoStaticsCleanup]
public static int Count;
라고 적어야 할 이유가 있을까?
결론부터 말하면,
단독으로 사용하면 런타임 결과는 거의 같아 보인다.
public static int A = 0;
[NoAutoStaticsCleanup]
public static int B = 0;
Domain Reload가 꺼진 상태라면 둘 다 이전 값을 유지할 수 있다.
즉 NoAutoStaticsCleanup이 값을 유지시키기 위해 별도의 작업을 하는 것은 아니다.
그럼 왜 존재할까?
AutoStaticsCleanup 정책에서 제외할 수 있다가장 중요한 이유다.
AutoStaticsCleanup은 static 필드 하나하나뿐 아니라 타입 전체에 적용할 수도 있다.
예를 들어:
[AutoStaticsCleanup]
public partial class GameStatics
{
public static int Score = 0;
public static int Coin = 0;
public static int UniqueId = 0;
}
이렇게 하면 해당 타입 안에 있는 static들이 자동 Cleanup 대상이 된다.
대략 이런 느낌이다.
GameStatics
├─ Score → Cleanup
├─ Coin → Cleanup
└─ UniqueId → Cleanup
그런데 UniqueId만 초기화하고 싶지 않다면?
이때 NoAutoStaticsCleanup을 사용할 수 있다.
[AutoStaticsCleanup]
public partial class GameStatics
{
public static int Score = 0;
public static int Coin = 0;
[NoAutoStaticsCleanup]
public static int UniqueId = 0;
}
결과적으로:
GameStatics
├─ Score → Cleanup
├─ Coin → Cleanup
└─ UniqueId → Cleanup 제외
가 된다.
즉 이 상황에서는 NoAutoStaticsCleanup이 확실한 역할을 한다.
상위에서 적용된 Auto Cleanup 정책을 특정 멤버에서 예외 처리한다.
또 하나 중요한 부분이 있다.
다음 코드를 보자.
public static int PersistentCounter;
코드만 봐서는 이 static이
알기 어렵다.
그런데 이렇게 작성하면 이야기가 달라진다.
[NoAutoStaticsCleanup]
public static int PersistentCounter;
이제 코드를 보는 사람 입장에서는 바로 이해할 수 있다.
아, 이 값은 의도적으로 자동 초기화를 하지 않는구나.
즉 NoAutoStaticsCleanup은 단순히 동작을 바꾸는 Attribute라기보다 정책을 명시하는 역할도 가지고 있다.
Unity의 Static Cleanup 관련 Analyzer를 사용하는 경우에는 이런 구분이 더 중요해진다.
간단히 정리하면 다음과 같다.
| 선언 | 의미 |
|---|---|
| Attribute 없음 | 별도의 Cleanup 정책을 지정하지 않음 |
[AutoStaticsCleanup] | 자동으로 초기화함 |
[NoAutoStaticsCleanup] | 의도적으로 자동 초기화하지 않음 |
특히 아래 두 코드는 실행 결과만 보면 비슷할 수 있다.
static int Value;
[NoAutoStaticsCleanup]
static int Value;
하지만 코드가 표현하는 의미는 다르다.
첫 번째는
아무 설정도 하지 않았다.
이고,
두 번째는
이 static은 일부러 Cleanup하지 않는다.
라는 의미다.
처음에는 이름 때문에
[NoAutoStaticsCleanup]
을 붙이면 Unity가 무언가 특별하게 "값을 보존하는 작업"을 해주는 줄 알았다.
하지만 실제로는 그보다는
AutoStaticsCleanup
→ 이 static은 자동 초기화해라.
NoAutoStaticsCleanup
→ 이 static은 자동 초기화 대상에서 명시적으로 제외해라.
라는 정책 선언에 가깝다.
특히 클래스 전체에 AutoStaticsCleanup을 적용하고 일부 static만 예외 처리할 때 의미가 명확해진다.
NoAutoStaticsCleanup만 단독으로 보면
이거 그냥 Attribute 안 붙이는 거랑 똑같은 거 아닌가?
라는 생각이 드는 게 자연스럽다.
실제 런타임 결과도 비슷할 수 있다.
하지만 존재 이유는 분명하다.
AutoStaticsCleanup 정책에서 특정 static을 제외할 수 있다.결국 한 줄로 정리하면:
NoAutoStaticsCleanup은 static 값을 유지시키는 기능이라기보다는, "이 static은 자동 Cleanup하지 않는다"는 것을 명시적으로 선언하기 위한 Attribute다.
그래서 프로젝트에서 Static Cleanup 정책을 명확하게 관리한다면, 단순히 Attribute를 생략하는 것과는 꽤 다른 의미를 가진다.