# 커스텀 네이티브 컨테이너 구현

> Implement custom native containers.

커스텀 네이티브 컨테이너를 구현하려면 [`NativeContainer`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/native-container-attribute.md) 속성을 사용하여 유형을 주석으로 작성해야 합니다. 또한 네이티브 컨테이너가 [안전 시스템](/engine/6000.0/manual/scripting/optimization/job-system/native-container.md#safety-system)과 어떻게 통합되는지 이해해야 합니다.

두 가지 주요 요소를 구현해야 합니다.

* **사용 추적:** Unity가 `NativeContainer` 인스턴스를 사용하는 예약된 잡을 추적하여 두 개의 잡이 동시에 동일한 네이티브 컨테이너에 쓰는 것과 같은 충돌 가능성을 감지하고 방지할 수 있도록 합니다.
* **누수 추적:** `NativeContainer`가 제대로 제거되지 않은 경우 감지합니다. 이 경우 메모리 누수가 발생하여 프로그램의 남은 전체 수명 동안 `NativeContainer`에 할당된 메모리를 사용할 수 없게 됩니다.

## 사용 추적 구현

코드에서 사용 트래킹에 액세스하려면 [`AtomicSafetyHandle`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle.md) 클래스를 사용하십시오. `AtomicSafetyHandle`은 안전 시스템이 특정 네이티브 컨테이너에 대해 저장하는 중앙 정보에 대한 레퍼런스를 보유하며, `NativeContainer`의 메서드가 안전 시스템과 상호 작용하는 주요 방법입니다. 따라서 모든 `NativeContainer` 인스턴스에는 `m_Safety`라는 `AtomicSafetyHandle` 필드가 포함되어야 합니다.

각 `AtomicSafetyHandle`에는 현재 컨텍스트에서 네이티브 컨테이너에서 수행할 수 있는 작업 유형을 나타내는 일련의 플래그가 저장됩니다. 잡에 `NativeContainer` 인스턴스가 포함된 경우 잡 시스템은 `AtomicSafetyHandle`의 플래그를 자동으로 설정하여 해당 잡에서 네이티브 컨테이너를 사용할 수 있는 방법을 반영합니다.

잡이 `NativeContainer` 인스턴스에서 읽으려고 할 때 읽기 전에 잡 시스템이 `CheckReadAndThrow` 메서드를 호출하여 잡에 네이티브 컨테이너에 대한 읽기 액세스 권한이 있는지 확인합니다. 마찬가지로 잡이 네이티브 컨테이너에 쓰기를 시도할 때 쓰기 전에 잡 시스템이 `CheckWriteAndThrow`를 호출하여 잡에 네이티브 컨테이너에 쓰기 액세스 권한이 있는지 확인합니다. 동일한 `NativeContainer` 인스턴스에 할당된 두 개의 잡에는 해당 네이티브 컨테이너에 대해 별도의 `AtomicSafetyHandle` 오브젝트가 있으므로 둘 다 동일한 중앙 정보 집합을 참조하지만 각 잡이 네이티브 컨테이너에 대해 어떤 읽기 및 쓰기 액세스 권한을 갖는지 나타내는 별도의 플래그를 각각 포함할 수 있습니다.

## 누수 추적 구현

Unity의 네이티브 코드는 주로 누수 추적을 구현합니다. [`UnsafeUtility.MallocTracked`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/unsafe-utility/malloc-tracked.md) 메서드를 사용하여 `NativeContainer` 데이터를 저장하는 데 필요한 메모리를 할당한 후 [`UnsafeUtility.FreeTracked`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/unsafe-utility/free-tracked.md)를 사용하여 이를 폐기합니다.

이전 버전의 Unity에서는 [`DisposeSentinel`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/dispose-sentinel.md) 클래스가 누수 추적을 제공합니다. Unity는 [가비지 컬렉터](/engine/6000.0/manual/analysis/performance-memory-overview/managed-memory/garbage-collector.md)가 `DisposeSentinel` 오브젝트를 수집할 때 메모리 누수를 보고합니다. `DisposeSentinel`을 생성하려면 동시에 `AtomicSafetyHandle`을 초기화하는 `Create` 메서드를 사용하십시오. 이 메서드를 사용하면 `AtomicSafetyHandle`을 초기화할 필요가 없습니다. `NativeContainer`가 폐기되면 `Dispose` 메서드는 단일 호출로 `DisposeSentinel`과 `AtomicSafetyHandle`을 모두 폐기합니다.

누출된 `NativeContainer`가 생성된 위치를 식별하려면 메모리가 원래 할당된 위치의 스택 추적을 캡처할 수 있습니다. 이렇게 하려면 [`NativeLeakDetection.Mode`](/engine/6000.0/script-reference/unity-collections/native-leak-detection/mode.md) 프로퍼티를 사용하십시오. 에디터에서 이 프로퍼티에 액세스할 수도 있습니다. 이렇게 하려면 **Preferences** > **Jobs** > **Leak Detection Level**로 이동하여 필요한 누수 감지 수준을 선택합니다.

## 중첩된 네이티브 컨테이너

안전 시스템은 잡에서 중첩된 네이티브 컨테이너를 지원하지 않는데, 이는 잡 시스템이 더 큰 `NativeContainer` 인스턴스 내부의 각 개별 `NativeContainer`에 대해 `AtomicSafetyHandle`을 올바르게 설정할 수 없기 때문입니다.

중첩된 네이티브 컨테이너를 사용하는 잡을 예약하지 않으려면 다른 `NativeContainer` 인스턴스를 포함할 때 `NativeContainer`를 중첩된 것으로 플래그를 지정하는 `SetNestedContainer`를 사용하십시오.

## 안전 ID 및 오류 메시지

안전 시스템은 코드가 안전 제약을 준수하지 않는 경우 오류 메시지를 표시합니다. 오류 메시지를 더 명확하게 만들기 위해 안전 시스템에 `NativeContainer` 오브젝트의 이름을 등록할 수 있습니다.

이름을 등록하려면 [`NewStaticSafetyId`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/new-static-safety-id.md)를 사용하여 [`SetStaticSafetyId`](ScriptRef:Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.SetStaticSafetyIdl)에 전달할 수 있는 안전 ID를 반환합니다. 안전 ID를 생성한 후에는 모든 `NativeContainer` 인스턴스에 재사용할 수 있으므로 일반적인 패턴은 컨테이너 클래스의 정적 멤버에 저장하는 것입니다.

또한 [`SetCustomErrorMessage`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/set-custom-error-message.md)로 특정 안전 제약 위반에 대한 오류 메시지를 오버라이드할 수도 있습니다.

## 추가 리소스

* [NativeContainer 구조체 복사](/engine/6000.0/manual/scripting/optimization/job-system/native-container/copy-nativecontainer.md)
* [커스텀 NativeContainer 예제](/engine/6000.0/manual/scripting/optimization/job-system/native-container/custom-nativecontainer-example.md)
