[Unity] 유니티에서 NonSerialized
개요
NonSerialized
는 Unity에서 특정 필드를 직렬화하지 않도록 명시적으로 지정하는 속성(Attribute)입니다.
Unity의 직렬화 시스템은 기본적으로 public 필드와 [SerializeField]가 적용된 private 필드를 직렬화합니다. 그러나 [NonSerialized]를 사용하면 Unity가 해당 필드를 직렬화에서 제외합니다.
목적과 특징
- 직렬화 제외
- Unity가 직렬화할 필요 없는 데이터를 명시적으로 제외합니다.
예를 들어, 런타임에만 사용되는 캐시 데이터나 참조값 등은 직렬화가 필요하지 않습니다.
- Unity가 직렬화할 필요 없는 데이터를 명시적으로 제외합니다.
- 데이터 보호
- 인스펙터에 표시되지 않도록 하고, Unity 장면 또는 Prefab에 데이터를 저장하지 않습니다.
- 사용 범위
- 직렬화 가능 필드에만 적용됩니다.
- private 필드에는 필요하지 않습니다. Unity는 기본적으로 private 필드를 직렬화하지 않습니다 (단, [SerializeField]가 없는 경우).
- 런타임 전용 데이터 관리
- 런타임 동안에만 필요한 값을 저장하거나 초기화해야 하는 경우 유용합니다.
- 런타임 동안에만 필요한 값을 저장하거나 초기화해야 하는 경우 유용합니다.
장단점
장점
- 불필요한 직렬화 방지: 런타임 전용 데이터가 직렬화되지 않도록 하여 성능을 최적화합니다.
- 데이터 노출 방지: 의도적으로 데이터를 인스펙터에 노출하지 않음으로써 코드의 가독성을 유지하고 오류 가능성을 줄입니다.
- 직렬화 오류 방지: Unity 직렬화 시스템이 처리할 수 없는 타입에 사용하면 경고 또는 오류를 피할 수 있습니다.
단점
- 값 초기화 불가: 직렬화되지 않으므로, Unity가 장면이나 Prefab을 저장/로드할 때 값을 유지하지 않습니다.
- 유지보수 어려움: 잘못된 사용은 나중에 직렬화가 필요할 때 혼란을 초래할 수 있습니다.
주의 사항
- Unity 직렬화의 범위
- Unity는 다음 필드만 기본적으로 직렬화합니다:
- public 필드
- [SerializeField]가 적용된 private 필드
- Unity는 다음 필드만 기본적으로 직렬화합니다:
- 필드 타입 제한
- Unity 직렬화 시스템은 특정 데이터 타입(예: int, float, GameObject, 사용자 정의 클래스 등)만 직렬화할 수 있습니다.
- 직렬화 불가능한 데이터 타입(예: Dictionary, HashSet)은 Unity에서 무시되며, [NonSerialized]를 추가하지 않아도 기본적으로 직렬화되지 않습니다.
- 런타임 데이터
- 런타임에서 계산되거나 생성되는 임시 데이터는 직렬화하지 않아야 합니다.
사용 예시
[사용 예시]
using UnityEngine;
using System;
[Serializable] // 사용자 정의 클래스 직렬화 가능
public class PlayerStats
{
public int health;
public int mana;
}
public class NonSerializedExample : MonoBehaviour
{
// 1. 인스펙터에 표시되는 직렬화 필드
[SerializeField] private PlayerStats stats;
// 2. NonSerialized 필드 (직렬화 제외)
[NonSerialized] public int runtimeOnlyData; // 런타임 전용 데이터
// 3. 직렬화되지 않는 C# 타입
private System.Collections.Generic.Dictionary<string, int> cachedValues;
// 4. NonSerialized는 private 필드에 필요하지 않음
private int privateData; // 자동으로 직렬화되지 않음
private void Start()
{
// 런타임 전용 데이터 초기화
runtimeOnlyData = 42;
Debug.Log($"Runtime-Only Data: {runtimeOnlyData}");
// 런타임에 Dictionary 초기화
cachedValues = new System.Collections.Generic.Dictionary<string, int>
{
{ "HealthPotion", 3 },
{ "ManaPotion", 5 }
};
}
private void Update()
{
// Dictionary를 활용해 데이터 조회
if (cachedValues.TryGetValue("HealthPotion", out int value))
{
Debug.Log($"Health Potion Count: {value}");
}
}
}