본문 바로가기
카테고리 없음

[언리얼] 가비지 콜렉터 GC(Garbage Collector) 동작 원리

by 연지니어스 2025. 3. 17.

언리얼 엔진에서 GC(Garbage Collector)의 동작 원리

1. GC(Garbage Collector)란 ?

GC(Garbage Collector, 가비지 컬렉터)는 메모리 관리 기법 중 하나로, 사용되지 않는 객체를 자동으로 해제하여 메모리 누수를 방지하는 역할을 한다. C++ 기반의 언리얼 엔진은 기본적으로 수동 메모리 관리를 요구하지만, UObject 시스템을 통해 자동으로 가비지 컬렉션을 수행한다. 이를 통해 개발자는 보다 효율적으로 메모리를 관리할 수 있으며, 수동 할당과 해제에 따른 메모리 오류를 줄일 수 있다.

한마디로 요약하자면, 메모리에서 사용되지 않는 객체를 메모리 누수 방지를 목적으로 정리해주는 기능이다.

 

2. 언리얼 엔진에서 GC의 동작 방식

2.1 UObject와 GC의 관계

언리얼 엔진의 GC는 UObject를 기반으로 동작한다. 엔진 내부에서 메모리 관리를 위해 사용되는 모든 객체는 UObject를 상속받으며, GC가 이를 추적하여 불필요한 객체를 해제한다. UObject를 기반으로 한 객체만이 GC의 관리 대상이 되므로, 일반적인 C++ 클래스는 자동으로 해제되지 않는다.

2.2 GC의 기본 동작 과정

  1. 객체 추적(Object Tracking): 모든 UObject는 엔진 내부의 Object Array에 등록되며, 이를 통해 참조 관계를 관리한다.
  2. 마킹(Marking) 단계 : GC는 루트 객체(Root Object)부터 시작하여 연결된 객체를 탐색한다. 이 과정에서 접근 가능한 객체는 '살아있는 객체'로 마킹되고, 접근할 수 없는 객체는 '가비지'로 간주된다.
  3. 스위핑(Sweeping) 단계 : 마킹되지 않은 객체는 메모리에서 해제된다. 이를 통해 사용되지 않는 메모리를 반환하며, 메모리 누수를 방지한다.
  4. 메모리 반환(Memory Reclamation) : 해제된 객체가 차지하던 메모리는 다시 사용 가능한 상태가 된다.

2.3 GC 루트(GC Root)

GC가 객체를 추적하는 과정에서 중요한 개념이 * *GC 루트(GC Root) * *이다. GC 루트는 게임 실행 중 반드시 유지되어야 하는 객체들을 의미하며, 이를 기준으로 참조 관계를 분석한다. 주요 GC 루트는 다음과 같다.

  • UWorld : 게임의 핵심 객체이며, 전체 게임 월드를 관리한다.
  • UGameInstance : 게임 실행 상태를 관리하는 객체이다.
  • AActor : 씬 내에서 존재하는 개별 객체로, 게임플레이의 주요 요소가 된다.

 

3. GC의 성능 최적화

GC는 편리한 기능이지만, 잘못된 사용으로 인해 성능 저하를 초래할 수 있다. 이를 방지하기 위한 최적화 방법을 살펴보자.

3.1 스마트 포인터 활용

TWeakObjectPtr, TSharedPtr, TUniquePtr 등의 스마트 포인터를 활용하면 불필요한 객체 유지로 인한 메모리 낭비를 줄일 수 있다. 특히 TWeakObjectPtr은 GC가 관리하는 객체를 안전하게 참조할 수 있도록 돕는다.

3.2 GC 호출 빈도 조절

언리얼 엔진에서는 Garbage Collection Interval을 조정하여 GC 호출 빈도를 조절할 수 있다. gc.TimeBetweenPurgingPendingKillObjects 등의 설정을 변경하면 불필요한 GC 호출을 줄여 성능을 개선할 수 있다.

3.3 객체 풀링(Object Pooling) </span >

반복적으로 생성 및 제거되는 객체는 객체 풀링(Object Pooling)기법을 활용하여 재사용하는 것이 바람직하다. 이를 통해 불필요한 메모리 할당과 해제를 방지할 수 있다.

3.4 불필요한 UObject 사용 지양

모든 객체를 UObject로 선언하면 GC 부담이 증가하므로, 꼭 필요한 경우에만 UObject를 사용해야 한다. 일반적인 데이터 클래스나 연산을 수행하는 클래스는 UObject가 아닌 일반 C++ 클래스로 구현하는 것이 좋다.

 

4. GC의 한계 및 수동 메모리 관리

언리얼 엔진의 GC는 강력하지만, 모든 메모리를 완벽하게 관리하지는 못한다.다음과 같은 한계점이 존재한다.

  • 비UObject 기반 객체 관리 불가: 일반 C++ 클래스는 GC의 대상이 아니므로, 수동으로 메모리를 해제해야 한다.
  • 성능 부담 : GC 수행 시 많은 객체를 탐색하면 프레임 드롭이 발생할 수 있다.
  • C++와의 혼합 사용 시 충돌 가능성 : C++ 기반 수동 메모리 해제와 GC 기반 자동 해제가 충돌하면 예기치 않은 버그가 발생할 수 있다.

이러한 문제를 해결하기 위해서는 RAII(Resource Acquisition Is Initialization) 패턴과 스마트 포인터를 적극 활용하여 수동 메모리 관리를 병행하는 것이 좋다.

 

5. 결론 및 요약

언리얼 엔진의 GC는 UObject 기반의 메모리 관리 시스템으로, 자동으로 불필요한 객체를 해제하여 메모리 누수를 방지한다. 하지만 잘못된 사용으로 인해 성능 저하가 발생할 수 있으므로, 스마트 포인터 활용, GC 호출 빈도 조절, 객체 풀링 등의 최적화 기법을 적용해야 한다. 또한, GC의 한계를 이해하고 필요에 따라 수동 메모리 관리 기법을 병행하는 것이 중요하다.

 

개념 설명
GC 대상 UObject 기반 객체만 관리
동작 과정 객체 추적 - 마킹 - 스위핑 - 메모리 반환
최적화 방법 스마트 포인터 활용, 객체 풀링, GC 호출 빈도 조절
한계점 비UObject 기반 객체 관리 불가, 성능 부담 존재

 

GC를 올바르게 이해하고 활용하면, 언리얼 엔진에서 안정적이고 성능이 뛰어난 게임을 개발할 수 있으니 좋은 개발을 하고자 한다면 꼭 기억해두자.