개발일지공부아이디어
    • 4월
    • 3월
    • 2월
    • 1월
  • 14

    26. 4. 14.

  • 10

    26. 4. 10.

  • 09

    26. 4. 9.

  • 08

    26. 4. 8.

로딩 중...

2026. 4. 14.

언리얼 컨테이너 라이브러리 Ⅱ - 구조체와 Map

UStruct

데이터 저장/전송에 특화된 가벼운 객체

  • UStruct를 쓰자/쓰지말자는 논의가 있음
  • UObject와 달리 가비지 컬렉션 대상이 아님
  • 함수도 가질 수 없음

사용방법

  1. USTRUCT(지정자) 매크로로 리플렉션 시스템에 등록
  2. GENERATED_BODY()로 리플렉션 코드 자동생성

구조체 지정자

  • BlueprintType: 블루프린트 변수 타입으로 사용 가능
  • Atomic: 멤버 변수에 대해 멀티스레드 환경에서 안전한 동시 접근 보장
  • NoExport: 자동 생성 코드 제외, 메타데이터 파싱 전용(블루프린트나 런타임 노출 x)

STL struct와 차이점

  • STL struct는 언리얼 에디터나 블루프린트에서 인식 못함
  • 직렬화, 리플렉션, 가비지 컬렉터 기능 못씀

언리얼 엔진의 메모리관리

C++ 언어 메모리 관리의 문제점

  • 저수준 언어이므로 메모리 주소에 직접 접근하는 포인터를 사용해 오브젝트를 관리한다
  • 그러다보니 프로그래머가 직접 할당(new)과 해지(delete) 짝 맞추기를 해야 한다. 이는 휴먼 에러 발생 가능성을 높인다
  • 잘못된 포인터 사용 예시
    • 메모리 누수(Leak): delete를 깜빡해 힙에 메모리가 그대로 남아있음
    • 허상 포인터(dangling): 이미 해제해 무효화된 오브젝트의 주소를 가리키는 포인터
    • 와일드 포인터(wild): 값이 초기화되지 않아 엉뚱한 주소를 가리키는 포인터(직접 nullptr로 초기화해ㅑ함)
  • 잘못된 포인터 값은 다양한 문제를 일으키며, 한 번의 실수는 크래시로 이어짐
  • 프로그램 규모가 커지고 복잡해질수록 실수활 확률도 같이 증가함

가비지 컬렉션 시스템

  • 프로그램에서 더 이상 사용되지 않는 오브젝트를 자동으로 감지해 메모리를 회수하는 시스템
  • UObject는 참조타입임. 참조타입은 레퍼런스로, 힙에서 사용됨을 뜻함. 결국 힙에 올라가있는 리소스를 파악하는 것.
  • 동적으로 생성된 모든 오브젝트 정보를 모아둔 저장소를 사용해 추적함
  • Mark-Sweep 방식
    1. 저장소에서 최초 검색을 시작하는 루트 오브젝트를 표기
    2. 루트 오브젝트가 참조하는 객체를 찾아 Marking
    3. Mark된 객체로부터 다시 참조하는 객체를 찾아 Mark하고 계속 반복
    4. 끝나면 저장소에는 Marked 객체외 Unmarked 객체 두 그룹으로 나뉜다
    5. 마크되지 않은 객체들의 메모리를 회수한다(Sweep)

언리얼의 가비지 컬렉션 시스템

  • 언리얼이 자체적으로 구축함
  • 지정된 주기마다 몰아서 없애도록 설정돼있음(기본값 60초)
  • 성능 향상을 위한 벙렬 처리, 클러스터링 기능을 탑재함

객체 저장소

  • 관리되는 모든 언리얼 오브젝트의 정보를 저장하는 전역변수: GUObjectArray
  • GUObjectArray의 각 요소에는 Flag가 설정돼있음
    • Garbage flag: 참조가 없어 회수 예정인 오브젝트
    • RootSet flag: 참조가 없어도 회수하지 않는 특별한 오브젝트

메모리 회수

  • 가비지 컬렉터는 지정된 시간에 따라 주기적으로 메모리를 회수한다.
  • Garbage flag로 설정된 오브젝트를 파악하고 메모리를 안전하게 회수함
  • Garbage flag는 수동으로 설정하는게 아니고 시스템이 알아서 설정함

회수되지 않는 언리얼 오브젝트

  • 언리얼 엔진 방식으로 참조를 설정한 언리얼 오브젝트
    • UPROPERTY()로 참조된 언리얼 오브젝트(대부분의 경우 이를 사용)
    • AddReferencedObject() 함수를 통해 참조를 설정한 언리얼 오브젝트
  • 루트셋으로 지정된 언리얼 오브젝트

핵심: 오브젝트 포인터는 가급적 UPROPERTY()로 선언하고, 메모리는 가비지컬렉터가 자동으로 관리하도록 위임한다.

일반 클래스에서 언리얼 오브젝트를 관리하는 경우

  • UPROPERTY()를 사용하지 못하는 일반 C++ 클래스가 언리얼 오브젝트를 관리해야할 때
  • FGCObject 클래스를 상속받은 후 AddReferencedObjects() 함수를 구현한다.
  • 함수 구현 부에서 관리할 언리얼 오브젝트를 추가해줌

언리얼 오브젝트의 관리 원칙

  • 언리얼 객체 내 언리얼 객체: UPROPERTY() 사용
  • 일반 C++ 객체 내 언리얼 객체: FGCObject 상속 후 구현
  • 생성된 언리얼 객체는 강제로 지우려하지 말 것
    • 참조를 끊는다는 생각으로 설계할 것
    • 가비지컬렉터에게 회수를 재촉할 수는 있으나 보장은 못받음(ForceGarbageCollerction())
    • 콘텐츠 제작에서 Destroy()함수를 사용할 수는 있으나 내부적으로는 위와 동일함
왼쪽 화살표다음 글이 없습니다.