본문 바로가기
유니티 공부/Unity

Unity - 가비지 컬렉터(Garbage Collector,GC)

by 코딩하는 돼징 2025. 7. 9.
반응형

Unity와 C#의 가비지 컬렉션 (Garbage Collection)

1. 가비지 컬렉션(GC)이란?

GC(Garbage Collector)는 더 이상 사용되지 않는 메모리를 자동으로 탐지하고 해제하는 시스템이다. 개발자가 수동으로 메모리를 해제하지 않아도 되며 안전하고 편리하게 메모리를 관리할 수 있게 해준다.

자동화: 명시적 해제 코드 없이 메모리를 관리한다.

안전성: 포인터 오류 및 이중 해제 등의 문제 방지한다.

단점:

GC가 작동하는 순간에는 다른 작업이 멈추는 정지 시간이 생긴다.

메모리 관리를 직접 제어하기 어려워 고성능 튜닝이 힘들다.


GC는 주로 힙 메모리에서 작동하며 더 이상 참조되지 않는 참조형 객체를 정리한다.

2. GC의 동작 방식: 마크 앤 스윕(Mark and Sweep)

마크(Mark): 루트(root) 객체에서 참조 체인을 따라 유효한 객체를 마킹한다.

스윕(Sweep): 마킹되지 않은 객체는 더 이상 사용되지 않는 것으로 간주되어 해제된다.

컴팩션(Compaction): 힙의 단편화가 심할 경우 객체를 재배치하여 메모리를 정리한다.

마크-스윕 자체는 세대별 GC 방식에서 사용되는 핵심 알고리즘이다.


3. 세대별 가비지 컬렉션 (Generational GC)

GC는 객체의 생존 기간에 따라 다음 세 가지 세대로 구분하여 관리한다.

0세대 (Gen 0): 새로 생성된 객체, GC 대상 1순위

1세대 (Gen 1): Gen 0에서 살아남은 객체

2세대 (Gen 2): Gen 1에서도 살아남은 객체 (대부분 오래 살아남는 객체)

Full GC = 2세대까지 모두 포함한 가비지 컬렉션

세대를 나누는 이유:

최근 생성된 객체는 대부분 금방 버려진다. 오래된 객체는 생존율이 높음 → 자주 검사할 필요 없다. 그러므로 부분 수집이 전체 수집보다 빠르다.


4. LOH와 SOH (Heap 분리 구조)

SOH (Small Object Heap): 83KB 미만의 객체

LOH (Large Object Heap): 83KB 이상의 객체, 무조건 2세대 취급

LOH는 컴팩션이 수행되지 않기 때문에 외부 단편화가 발생할 수 있다.


5. GC 작동 시점

메모리 사용량이 기준치를 초과했을 때 혹은 명시적으로 System.GC.Collect() 호출 시이다.

유니티: 상태 전환, 일시정지 시 등

주의: GC.Collect()의 남발은 성능 저하를 유발하므로 최소한으로 사용해야 한다.


6. Unity에서의 GC 사용

Unity는 기본적으로 Mono 환경에서 세대 기반 GC를 사용한다.

IL2CPP 환경(모바일 빌드 등)은 세대 개념이 없는 단순화된 GC 또는 BDW 가비지 컬렉터를 사용한다.

BDW (Boehm–Demers–Weiser) 가비지 컬렉터

트래킹 기반 + 마크 앤 스윕

비차단(Non-blocking) 방식으로 멀티스레드 환경에서도 작동

부분 수집(Piecemeal Collection) 지원

Incremental GC (점진적 가비지 컬렉션)

Unity 2019.1 이상에서 지원

GC 작업을 프레임에 나누어 수행하여 성능 스파이크 완화

단점: 평균 프레임 성능이 약간 낮아질 수 있다.


7. GC 성능 이슈 & 최적화

성능 저하 원인

new 연산자 사용 과다

문자열 연산 (특히 + 연산 반복)

foreach 루프

델리게이트/이벤트의 잘못된 구독 해제

최적화 방법

Object Pooling: 반복 사용되는 객체 재사용

StringBuilder: 문자열 누적 시 사용

구조체(Struct) 사용 고려 (값 타입은 GC 대상 아님)

델리게이트 해제 철저히


8. 메모리 단편화

내부 단편화 (Internal Fragmentation)

할당된 블록 내 실제 사용되지 않는 공간

외부 단편화 (External Fragmentation)

작은 빈 공간들이 흩어져 있어 큰 연속 메모리 할당 불가능

LOH에서 외부 단편화가 발생하며, 이는 성능 문제의 원인이 될 수 있다.


9. 실시간 게임에서의 GC 이슈

GC 도중 메인 스레드 정지 → 프레임 드랍, 버벅임

Unity는 이를 완화하기 위해 Incremental GC 도입한다.

메모리 사용 계획을 잘 세워야 프레임 안정성을 확보할 수 있다.


10. 결론

C#과 Unity의 GC는 자동화된 메모리 관리를 통해 개발 편의성을 높여주지만 성능에 민감한 게임 개발에서는 반드시 메모리 사용 패턴을 이해하고 최적화를 수행해야 한다.

 

 

반응형

댓글