본문 바로가기
유니티

Unity Garbage Collection

by 유니티세상 2026. 3. 11.
반응형

Addressables를 공부하다 보니 자연스럽게 Unity 메모리 구조와 GC(Garbage Collector)까지 이어지게 되었다.
이 글에서는 Unity에서의 GC 개념과 메모리 구조를 정리해보려고 한다.


Unity 메모리 구조

Unity 메모리는 크게 다음 세 가지로 나뉜다.

Managed Memory (C#)
Native Memory (Unity Engine)
GPU Memory

 

이 중 GC는 Managed Memory만 관리한다.

즉 Unity에서는 다음과 같이 메모리 관리 방식이 나뉜다.

메모리 종류 관리 방식
Managed Memory GC
Native Memory Destroy
GPU Memory Graphics Driver

GC란 무엇인가

GC(Garbage Collector)는

Managed Heap에 존재하는 C# 객체 중 더 이상 참조되지 않는 객체를 자동으로 회수하는 시스템이다.

 

즉 C#에서 생성된 객체가 더 이상 사용되지 않으면 GC가 해당 메모리를 정리한다.


GC의 대상이 되는 객체

Unity에서 다음과 같은 객체들은 GC의 대상이 된다.

  • List
  • Dictionary
  • string
  • 사용자 정의 class 객체

이러한 객체들은 Managed Heap에 생성되는 C# 객체이기 때문이다.


GC의 대상이 아닌 Unity Object

반면 다음과 같은 Unity Object들은 GC의 대상이 아니다.

  • GameObject
  • Texture
  • Mesh
  • Material
  • Transform

이 객체들은 C# 객체가 아니라 Unity Engine(C++)에서 생성되는 Native Object이기 때문이다.

예를 들어 다음 코드를 보면

GameObject goblin = Instantiate(prefab);

 

겉으로 보면 C# 객체처럼 보이지만 실제 구조는 다음과 같다.

Managed Memory
└ goblin (reference)

Native Memory
├ GameObject
├ Transform
├ Renderer
└ Component

 

즉 goblin 변수는 단순히 Native Object를 가리키는 reference일 뿐이며
실제 GameObject는 Unity Engine의 Native Memory에 존재한다.

그래서 Unity Object는 GC가 아니라 Destroy를 통해 관리해야 한다.

Destroy(goblin);

GC는 언제 실행되는가

GC는 Managed Heap에 객체 할당이 계속 발생하여 Heap 사용량이 증가할 때 실행될 수 있다.

예를 들어 Heap이 다음과 같이 증가한다고 가정해보자.

16MB → 20MB → 25MB → 30MB

 

이 상태에서 새로운 객체를 할당하려고 할 때 공간이 부족하면
GC가 실행되어 사용되지 않는 객체를 탐색하고 메모리를 회수한다.

GC 실행 과정은 다음과 같다.

1. Root 객체 탐색
2. 참조 그래프 탐색
3. 사용되지 않는 객체 식별
4. 메모리 회수

이 과정에서 Heap을 탐색해야 하기 때문에 Main Thread가 잠시 멈출 수 있다.

이 현상을 GC Spike라고 한다.


GC Allocation이란

GC Allocation은

Managed Heap에 새로운 객체가 할당되는 것

 

을 의미한다.

예를 들어 다음 코드가 있다고 가정해보자.

void Update()
{
    string text = "HP : " + hp;
}

이 코드는 매 프레임 새로운 string 객체를 생성한다.

만약 게임이 60FPS라면

1초 = 60개의 string 객체 생성

이렇게 생성된 객체들이 누적되면 GC가 실행될 가능성이 높아진다.

그래서 Unity에서는 반복 루프(Update 등)에서 GC Allocation을 최소화하는 것이 중요하다.


GC Allocation을 발생시키는 대표적인 코드

다음과 같은 코드들은 GC Allocation을 발생시킬 수 있다.

  • string 생성
  • new 객체 생성
  • boxing
  • LINQ 사용

이러한 코드들은 Managed Heap에 새로운 객체를 생성하기 때문이다.


메모리 최적화 방법

Unity 프로젝트에서는 다음과 같은 방법으로 메모리를 최적화할 수 있다.


Object Pool

Object Pool은 객체를 미리 생성해두고 재사용하는 방식이다.

예를 들어 총알 시스템을 생각해보자.

일반적인 방식

총알 발사
→ Instantiate
→ Destroy

 

이 방식은 반복적인 객체 생성과 제거가 발생한다.

 

Object Pool 방식

초기
총알 50개 생성

사용
비활성 → 활성

회수
활성 → 비활성

이 방식의 장점은 다음과 같다.

  • Instantiate 호출 감소
  • Destroy 호출 감소
  • GC Allocation 감소
  • CPU 사용량 감소

Addressables Release

Addressables를 사용하는 경우

Addressables.Release(handle);

 

을 통해 AssetBundle과 같은 Native Memory 리소스를 해제할 수 있다.

이러한 리소스는 Scene 변경과 관계없이 메모리에 남을 수 있기 때문에 명시적인 해제가 필요하다.


GC Allocation 확인 방법

GC Allocation은 다음과 같은 도구를 통해 확인할 수 있다.

  • Unity Profiler
  • Memory Profiler

Unity Profiler의 GC Alloc 항목을 통해 프레임마다 발생하는 GC Allocation을 확인할 수 있다.


정리

Unity 메모리는 크게 다음 세 가지로 구분된다.

Managed Memory (C#)
Native Memory (Unity Engine)
GPU Memory

 

이 중 GC는 Managed Memory만 관리한다.

따라서 Unity 개발에서는 다음 두 가지를 모두 고려해야 한다.

 

1. GC Allocation 최소화 (Managed Memory)
2. Native Object 명시적 관리 (Destroy / Addressables.Release)

 

 


참고)


https://gameclientstudynote.tistory.com/22

 

유니티 최적화 - Garbage Collection

게임에서의 최적화는 정말 중요하다. 만약 유저가 재밌게 플레이하고 있을 때 게임이 잠깐 멈추는 현상이 일어나게 되면 유저에게 부정적 영향을 주게 된다. 지금부터 알아보는건 유니티엔진을

gameclientstudynote.tistory.com

 

반응형