"GC(Garbage Collector)"
개발을 하다보면 메모리 관리를 내가 직접 하지 않아도 되는 언어가 얼마나 편한지 체감하게 된다.
C#(Unity)에서는 new로 객체를 만들고 참조만 잘 관리하면, 사용이 끝난 객체는 GC(가비지 컬렉터)가 알아서 회수해준다.
하지만 게임에서는 자동이 항상 좋은 건 아니다.
GC가 한 번 크게 돌면 프레임이 순간적으로 멈추는 GC 스파이크가 생길 수 있고,
이게 프레임 드랍으로 이어진다.
그래서 Unity에서 GC는 성능 최적화에서 자주 등장하는 단골 주제이다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
1) GC(Garbage Collector) 란?
더 이상 참조되지 않는 *관리 힙(Managed Heap) 객체를 자동으로 찾아 메모리를 회수하는 시스템
*관리 힙(Managed Heap): C#에서 new로 만든 객체(참조 타입, string, 배열, List 등)
GC가 회수하는 건 관리 힙(Managed Heap) 쪽 메모리이며,
Unity 리소스(Texture/Mesh/AudioClip 등)는 엔진(C/C++)의 *네이티브 메모리에 존재하는 경우가 많아,
GC만으로 해결되지 않을 수 있다.
*네이티브 메모리(Native):
Unity 엔진 리소스(Texture/Mesh 등) → Destroy, UnloadUnusedAssets 같은 별도 관리가 필요할 수 있음

----------------------------------------------------------------------------------------------------------------------------------------------------------------
2) GC는 어떻게 “쓰레기”를 찾을까?
GC는 루트(스택 변수, static 필드 등)에서 시작해 참조를 따라가며 살아있는 객체를 표시(Mark)하고,
표시되지 않은 객체는 회수(Sweep)합니다. 그리고 필요할 경우,
흩어진 빈 공간(단편화)을 줄이기 위해 살아있는 객체를 한쪽으로 모아 압축(Compaction)하기도 한다.
Mark(표시): 루트(root)에서 시작해 참조를 따라가며 살아있는 객체를 표시
Sweep(정리): 표시되지 않은 객체를 더 이상 사용하지 않는 객체로 보고 회수
Compaction(압축): 필요하면 살아있는 객체를 한쪽으로 모아 단편화를 줄이고 연속 공간을 확보

----------------------------------------------------------------------------------------------------------------------------------------------------------------
3) GC가 무서운 이유
GC는 상황에 따라 Stop-the-world(잠깐 멈추고 일괄 처리) 형태로 동작할 수 있어,
한 프레임이 갑자기 길어지면 프레임 드랍이 된다.
Unity에는 이를 완화하기 위한 점진적(Incremental) GC 옵션이 있는데,
이는 GC 작업을 여러 프레임에 나눠서 스파이크를 줄이는 방식이다.

점진적 GC는 GC를 더 빠르게 만드는 게 아니라
GC 일을 쪼개서 프레임 드랍을 완화하는 접근이다.
대신 분산 처리 자체의 오버헤드도 있을 수 있으므로,
할당 자체를 줄이는 것이 우선순위다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
4) GC를 줄이는 핵심은 “할당(Alloc) 줄이기”
GC를 돌지 않게 만드는 게 아니라,
GC가 돌 만큼 쓰레기를 만들지 않는 설계가 핵심이다.
자주 나오는 GC Alloc 원인
매 프레임 new (List/배열/클래스 생성)
문자열 결합(+), ToString(), string.Format 남발
LINQ(Select/Where 등), 박싱(Boxing)
람다/클로저(캡처)
코루틴에서 new WaitForSeconds()를 매번 생성
대표적인 해결법
캐싱: List/배열/컴포넌트/문자열 포맷 재사용
오브젝트 풀링(Object Pool): 자주 생성/파괴되는 오브젝트는 풀로 관리
핫패스에서 LINQ 자제
코루틴 Yield 캐싱
(WaitForSeconds를 미리 만들어두고 재사용)
----------------------------------------------------------------------------------------------------------------------------------------------------------------
5) 오늘의 한 줄 요약
『 GC는 편리한 자동 메모리 회수 장치지만,
Unity에서는 런타임 할당이 누적되면 GC 스파이크로 프레임 드랍이 발생할 수 있어
‘Alloc 관리(캐싱/풀링/핫패스 최적화)’가 중요하다.』
'1일 1 cs' 카테고리의 다른 글
| 13. 컬렉션(Collection)이란? (0) | 2026.01.28 |
|---|---|
| 12. 시간복잡도란? (0) | 2026.01.27 |
| 10. 애니메이션(Animation)과 애니메이터(Animator)란? (0) | 2026.01.25 |
| 9. 컬링(Culling)이란? (0) | 2026.01.24 |
| 8. 코루틴(Coroutine)이란? (0) | 2026.01.23 |
