PART 3 ยท ๊ฐ•์˜ 1/4

UPROPERTY ์‹ฌํ™”

๋ชจ๋“  ํ”„๋กœํผํ‹ฐ ์ง€์ •์ž์™€ GC ๊ด€๋ จ ํ”Œ๋ž˜๊ทธ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค

SECTION 01

UPROPERTY ์ง€์ •์ž ์ด์ •๋ฆฌ

GC์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ ์ง€์ •์ž

GC ๊ด€๋ จ ์ง€์ •์ž

์ง€์ •์žGC ์˜ํ–ฅ์„ค๋ช…
UPROPERTY()GC ์ถ”์ ๊ธฐ๋ณธ - UObject* ์ฐธ์กฐ๋ฅผ GC๊ฐ€ ์ถ”์ 
Transient์ถ”์  ์œ ์ง€์ง๋ ฌํ™” ์ œ์™ธ, GC ์ถ”์ ์€ ์œ ์ง€
DuplicateTransient์ถ”์  ์œ ์ง€๋ณต์ œ ์‹œ ์ œ์™ธ, GC ์ถ”์  ์œ ์ง€
SkipSerialization์ถ”์  ์œ ์ง€๋ชจ๋“  ์ง๋ ฌํ™” ์ œ์™ธ, GC ์ถ”์  ์œ ์ง€
TextExportTransient์ถ”์  ์œ ์ง€ํ…์ŠคํŠธ ๋‚ด๋ณด๋‚ด๊ธฐ ์ œ์™ธ
NonPIEDuplicateTransient์ถ”์  ์œ ์ง€PIE ๋ณต์ œ ์‹œ์—๋งŒ ๋ณต์‚ฌ๋จ
Instanced์†Œ์œ ๊ถŒ ์ถ”์ ์ฐธ์กฐ๊ฐ€ ์ธ์Šคํ„ด์Šค์˜ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ง
Export์†Œ์œ ๊ถŒ ์ถ”์ Instanced์™€ ๋™์ผ (์ปดํฌ๋„ŒํŠธ์šฉ)
C++ UCLASS() class UMyObject : public UObject { GENERATED_BODY() // ๊ธฐ๋ณธ: GC ์ถ”์  + ์ง๋ ฌํ™” UPROPERTY() UObject* StandardRef; // GC ์ถ”์  O, ์ง๋ ฌํ™” X (์บ์‹œ์šฉ) UPROPERTY(Transient) UTexture2D* CachedTexture; // ์ธ์Šคํ„ด์Šค ์†Œ์œ  (์ด ๊ฐ์ฒด๊ฐ€ ํŒŒ๊ดด๋˜๋ฉด ์ฐธ์กฐ๋„ ํŒŒ๊ดด) UPROPERTY(Instanced) UMySubObject* OwnedSubObject; // ์—๋””ํ„ฐ์—์„œ๋งŒ ์œ ํšจ (์ฟ ํ‚น ์‹œ ์ œ๊ฑฐ) UPROPERTY(Transient) UObject* EditorOnlyCache; };
SECTION 02

Instanced์™€ ์†Œ์œ ๊ถŒ ์˜๋ฏธ๋ก 

UPROPERTY(Instanced)๊ฐ€ GC์— ๋ฏธ์น˜๋Š” ํŠน๋ณ„ํ•œ ์˜ํ–ฅ

Instanced ํ”„๋กœํผํ‹ฐ

Instanced ์ง€์ •์ž๋Š” ํ•ด๋‹น ์ฐธ์กฐ๊ฐ€ ๊ฐ์ฒด์˜ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ง์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์†Œ์œ  ๊ฐ์ฒด๊ฐ€ ๋ณต์ œ๋˜๋ฉด Instanced ์„œ๋ธŒ์˜ค๋ธŒ์ ํŠธ๋„ ํ•จ๊ป˜ ๋ณต์ œ๋ฉ๋‹ˆ๋‹ค. GC ๊ด€์ ์—์„œ๋Š” ์ผ๋ฐ˜ ์ฐธ์กฐ์™€ ๋™์ผํ•˜๊ฒŒ ์ถ”์ ๋˜์ง€๋งŒ, ์ง๋ ฌํ™”์™€ ๋ณต์ œ ๋™์ž‘์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

C++ // Instanced ์„œ๋ธŒ์˜ค๋ธŒ์ ํŠธ ํŒจํ„ด UCLASS(DefaultToInstanced, EditInlineNew) class UAbilityData : public UObject { GENERATED_BODY() UPROPERTY(EditAnywhere) float Damage = 10.f; UPROPERTY(EditAnywhere) float Cooldown = 1.0f; }; UCLASS() class AMyCharacter : public ACharacter { GENERATED_BODY() // Instanced: ์บ๋ฆญํ„ฐ๊ฐ€ ์†Œ์œ ํ•˜๋Š” ๊ณ ์œ  ์ธ์Šคํ„ด์Šค UPROPERTY(EditAnywhere, Instanced) UAbilityData* PrimaryAbility; // Instanced ๋ฐฐ์—ด: ๊ฐ๊ฐ ๊ณ ์œ  ์ธ์Šคํ„ด์Šค UPROPERTY(EditAnywhere, Instanced) TArray<UAbilityData*> Abilities; }; // ์บ๋ฆญํ„ฐ๊ฐ€ ๋ณต์ œ๋˜๋ฉด โ†’ AbilityData๋„ ์ž๋™ ๋ณต์ œ // ์บ๋ฆญํ„ฐ๊ฐ€ GC๋˜๋ฉด โ†’ AbilityData๋„ GC ๋Œ€์ƒ
DefaultToInstanced์™€ EditInlineNew

DefaultToInstanced๋Š” ์ด ํด๋ž˜์Šค์˜ ๋ชจ๋“  UPROPERTY ์ฐธ์กฐ๋ฅผ ์ž๋™์œผ๋กœ Instanced๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. EditInlineNew๋Š” ์—๋””ํ„ฐ์—์„œ ์ธ๋ผ์ธ์œผ๋กœ ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‘ ์ง€์ •์ž๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์—๋””ํ„ฐ์—์„œ ์„œ๋ธŒ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SECTION 03

์ปจํ…Œ์ด๋„ˆ ํ”„๋กœํผํ‹ฐ์™€ GC

TArray, TMap, TSet ๋‚ด๋ถ€์˜ UObject ์ฐธ์กฐ ์ถ”์ 

์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ ์ฐธ์กฐ ์ถ”์  ๊ทœ์น™

C++ UCLASS() class UMyContainer : public UObject { GENERATED_BODY() // TArray<UObject*> - ๋ชจ๋“  ์š”์†Œ GC ์ถ”์  UPROPERTY() TArray<AActor*> ActorList; // TMap - Key์™€ Value ๋ชจ๋‘ ์ถ”์  ๊ฐ€๋Šฅ UPROPERTY() TMap<FName, UObject*> ObjectMap; // TMap<UObject*, UObject*> - ์–‘์ชฝ ๋ชจ๋‘ ์ถ”์  UPROPERTY() TMap<UObject*, UObject*> BothSidesTracked; // TSet<UObject*> - ๋ชจ๋“  ์š”์†Œ ์ถ”์  UPROPERTY() TSet<UObject*> ObjectSet; // ์ค‘์ฒฉ ์ปจํ…Œ์ด๋„ˆ - ๋‚ด๋ถ€๊นŒ์ง€ ์ถ”์  UPROPERTY() TArray<FMyStruct> StructArray; // FMyStruct ๋‚ด UPROPERTY UObject*๋„ ์ถ”์ ๋จ // ์œ„ํ—˜: UPROPERTY ์—†๋Š” ์ปจํ…Œ์ด๋„ˆ TArray<UObject*> DangerousArray; // GC ๋ฏธ์ถ”์ ! };
์ž์ฃผ ํ•˜๋Š” ์‹ค์ˆ˜: ๋กœ์ปฌ ์ปจํ…Œ์ด๋„ˆ

ํ•จ์ˆ˜ ๋กœ์ปฌ ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋œ TArray<UObject*>๋Š” UPROPERTY๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ GC๊ฐ€ ์ถ”์ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•ด๋‹น ํ•จ์ˆ˜ ์‹คํ–‰ ์ค‘ GC๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด(๋น„๋™๊ธฐ ์ฝœ๋ฐฑ ๋“ฑ), ์ปจํ…Œ์ด๋„ˆ ๋‚ด์˜ ๊ฐ์ฒด๊ฐ€ ์ˆ˜์ง‘๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์žฅ์‹œ๊ฐ„ ์œ ์ง€๋˜๋Š” ๋กœ์ปฌ ์ปจํ…Œ์ด๋„ˆ์—๋Š” FGCObject๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์Šน๊ฒฉ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

SECTION 04

UPROPERTY ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ GC ์ตœ์ ํ™”

ํ”„๋กœํผํ‹ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ GC ํšจ์œจ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ

GC ํ† ํฐ ์ŠคํŠธ๋ฆผ ์ตœ์ ํ™”

UPROPERTY์˜ ํƒ€์ž…์— ๋”ฐ๋ผ GC ํ† ํฐ ์ŠคํŠธ๋ฆผ์˜ ํฌ๊ธฐ์™€ ๋ณต์žก๋„๊ฐ€ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. UObject ์ฐธ์กฐ๊ฐ€ ์—†๋Š” ํ”„๋กœํผํ‹ฐ๋Š” ํ† ํฐ ์ŠคํŠธ๋ฆผ์— ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ GC ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

C++ UCLASS() class UHeavyObject : public UObject { GENERATED_BODY() // GC ํ† ํฐ ์—†์Œ (๊ฐ’ ํƒ€์ž…) UPROPERTY() int32 Health; // ํ† ํฐ ์ŠคํŠธ๋ฆผ ๋ฏธํฌํ•จ UPROPERTY() FString Name; // ํ† ํฐ ์ŠคํŠธ๋ฆผ ๋ฏธํฌํ•จ UPROPERTY() FVector Location; // ํ† ํฐ ์ŠคํŠธ๋ฆผ ๋ฏธํฌํ•จ // GC ํ† ํฐ ์ƒ์„ฑ (์ฐธ์กฐ ํƒ€์ž…) UPROPERTY() UObject* Ref1; // GCRT_Object ํ† ํฐ 1๊ฐœ UPROPERTY() TArray<UObject*> Refs; // GCRT_ArrayObject ํ† ํฐ 1๊ฐœ UPROPERTY() TMap<FName, UObject*> Map; // GCRT_Map ํ† ํฐ }; // ์ด ํด๋ž˜์Šค์˜ GC ํ† ํฐ ์ŠคํŠธ๋ฆผ = 3๊ฐœ ํ† ํฐ // โ†’ GC๊ฐ€ ์ด ๊ฐ์ฒด๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ 3๋ฒˆ๋งŒ ๊ฒ€์‚ฌ
GC ํšจ์œจ ํŒ

UObject ์ฐธ์กฐ๋ฅผ ๋งŽ์ด ๊ฐ€์ง„ ํด๋ž˜์Šค๋Š” GC ๋น„์šฉ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰์˜ ์ฐธ์กฐ๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด:

  • ์ฐธ์กฐ๋ฅผ ๊ตฌ์กฐ์ฒด๋กœ ๋ฌถ์–ด ๊ด€๋ฆฌ (ํ† ํฐ ์ˆ˜ ๊ฐ์†Œ)
  • ํ•„์š” ์‹œ TWeakObjectPtr ์‚ฌ์šฉ (GC ์ถ”์  ๋ถˆํ•„์š”)
  • ๊ฐ€๋Šฅํ•˜๋ฉด TSoftObjectPtr๋กœ ์ „ํ™˜ (์ง€์—ฐ ๋กœ๋”ฉ)
SUMMARY

ํ•ต์‹ฌ ์š”์•ฝ

์ด ๊ฐ•์˜์—์„œ ๋ฐฐ์šด ๋‚ด์šฉ
  • Transient, SkipSerialization ๋“ฑ์€ ์ง๋ ฌํ™”๋งŒ ์ œ์–ดํ•˜๋ฉฐ GC ์ถ”์ ์—๋Š” ์˜ํ–ฅ ์—†์Šต๋‹ˆ๋‹ค
  • Instanced ์ง€์ •์ž๋Š” ์†Œ์œ ๊ถŒ์„ ๋ถ€์—ฌํ•˜์—ฌ ๋ณต์ œ์™€ ์ง๋ ฌํ™” ๋™์ž‘์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค
  • TArray, TMap, TSet์˜ UPROPERTY ์ปจํ…Œ์ด๋„ˆ ๋‚ด UObject* ์ฐธ์กฐ๋Š” ์ž๋™ ์ถ”์ ๋ฉ๋‹ˆ๋‹ค
  • UPROPERTY๊ฐ€ ์—†๋Š” ๋กœ์ปฌ TArray<UObject*>๋Š” GC๊ฐ€ ์ถ”์ ํ•˜์ง€ ๋ชปํ•ด ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค
  • ๊ฐ’ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋Š” GC ํ† ํฐ ์ŠคํŠธ๋ฆผ์— ํฌํ•จ๋˜์ง€ ์•Š์•„ GC ๋น„์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค
PRACTICE

๋„์ „ ๊ณผ์ œ

๋ฐฐ์šด ๋‚ด์šฉ์„ ์ง์ ‘ ์‹ค์Šตํ•ด๋ณด์„ธ์š”

์‹ค์Šต 1: UPROPERTY ์ง€์ •์ž๋ณ„ GC ๋™์ž‘ ํ…Œ์ŠคํŠธ

ํ•˜๋‚˜์˜ UObject์— UPROPERTY(), UPROPERTY(Transient), raw pointer(UPROPERTY ์—†์Œ), TObjectPtr ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ๊ฐ ๋งŒ๋“ค๊ณ , ์ฐธ์กฐ ๋Œ€์ƒ ๊ฐ์ฒด์˜ GC ์ˆ˜์ง‘ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธํ•˜์„ธ์š”. UPROPERTY ์—†๋Š” raw pointer๊ฐ€ dangling ๋˜๋Š” ์ƒํ™ฉ์„ ์žฌํ˜„ํ•˜์„ธ์š”.

์‹ค์Šต 2: TObjectPtr vs raw UObject* ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

๊ธฐ์กด ์ฝ”๋“œ์—์„œ UObject* raw pointer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ TObjectPtr๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜์„ธ์š”. Access Tracking๊ณผ Lazy Load ๋™์ž‘์˜ ์ฐจ์ด๋ฅผ ๋””๋ฒ„๊ทธ ๋กœ๊ทธ๋กœ ํ™•์ธํ•˜๊ณ , ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ „ํ›„ ๋™์ž‘์ด ๋™์ผํ•œ์ง€ ๊ฒ€์ฆํ•˜์„ธ์š”.

์‹ฌํ™” ๊ณผ์ œ: UPROPERTY ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ ๋ถ„์„

FProperty::GetOffset_ForInternal()์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ž˜์Šค ๋‚ด UPROPERTY๋“ค์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์„ ๋ถ„์„ํ•˜์„ธ์š”. ํ”„๋กœํผํ‹ฐ ์ˆœ์„œ, ํŒจ๋”ฉ, ์˜คํ”„์…‹์„ ์‹œ๊ฐํ™”ํ•˜๊ณ , GC๊ฐ€ ํ† ํฐ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฐธ์กฐ๋ฅผ ์Šค์บ”ํ•˜๋Š” ๊ณผ์ •์„ ์ดํ•ดํ•˜๋Š” ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.