[Unreal Engine 5] 멀티플레이 아키텍처: GAS 퀵슬롯과 인벤토리 설계

2026. 4. 9. 22:03·프로그래밍/Unreal Engine 5

오늘의 목표

언리얼 엔진 5 환경에서 멀티플레이 네트워크 동기화와 메모리 최적화를 고려하여, 인벤토리 시스템과 연동되는 퀵슬롯(Active Skill) 발동 시스템 아키텍처를 설계하고 구현 방향성을 확립한다.


고민과 문제 인식

1. SRP(단일 책임 원칙) vs 멀티플레이 안정성

  • 초기 구상: 인벤토리(SMInventoryComponent)와 퀵슬롯(SMQuickSlotComponent)의 책임을 분리하여 설계하려고 했다. (SRP 준수)
  • 문제점 인식:
    • 퀵슬롯은 본질적으로 인벤토리 아이템의 '포인터(참조)' 역할을 한다.
    • 컴포넌트를 분리할 경우, 멀티플레이 환경에서 "가방에서 지워짐"과 "퀵슬롯에 등록됨" 패킷 사이의 딜레이로 인해 Race Condition(경합 조건)이 발생하여 널 포인터 크래시나 아이템 복사/증발 버그가 터질 위험이 컸다.
  • 해결 및 결정: * 언리얼의 멀티플레이 환경에서는 "높은 결합도"를 가지는 두 시스템을 하나의 컴포넌트(SMInventoryComponent)로 합쳐서 응집도(Cohesion)를 높이는 것이 훨씬 안전하다.
    • 컴포넌트의 책임을 '가방'이 아닌 '플레이어 아이템/스킬 상태 관리자(Item Manager)'로 확장하여 한 곳에서 통제하도록 팀원과 합의했다.

2. 아이템 객체: UObject vs UStruct

  • 고민: 예전 프로젝트에서는 아이템을 UObject로 설계했는데, 이번 프로젝트에서는 UStruct(구조체)와 DataAsset으로 설계되었다. 이 차이가 무엇일까?
  • 학습 내용 (UE5 Lyra 패러다임):
    • UObject 방식은 직관적이지만, 대규모 멀티플레이에서는 가비지 컬렉션(GC) 부하와 네트워크 동기화(Replication)의 불안정성이라는 치명적인 단점이 있다.
    • 현재 설계인 UStruct (런타임 동적 데이터) + DataAsset (정적 메타 데이터) 방식은 에픽게임즈의 최신 '데이터 지향 설계'이다.
    • 깃털처럼 가볍고, 배열 동기화(Fast Array Serialization) 기술을 통해 멀티플레이에서 압도적인 성능과 안정성을 보장한다는 것을 이해했다.

🛠️ 핵심 아키텍처 설계: 퀵슬롯 발동 (Pull 방식)

기획 요구사항: "동일한 파이어볼이라도 박혀있는 젬(보석)과 레벨에 따라 데미지가 달라야 한다. 1, 2번 키로 스킬을 장착하고 좌클릭으로 발사한다."

1. 역할 분리 (Separation of Concerns)

  • 캐릭터 (SMPlayerCharacter): 입력 라우터(Router) 역할만 수행.
  • 인벤토리 (SMInventoryComponent): 데미지 계산(캐싱) 및 활성화된 스킬 정보 제공.
  • 어빌리티 (UGameplayAbility): 실제 발동 시 인벤토리 데이터를 읽어와서(Pull) 적용.

2. 데이터 플로우 (Data Flow)

  1. 장착 (키보드 1, 2): 캐릭터가 InventoryComp->SetActiveQuickSlot(Index) 호출하여 활성화 슬롯 상태만 변경.
  2. 발사 (좌클릭): 캐릭터가 InventoryComp->GetActiveQuickSlotAbilityTag()를 통해 태그를 얻고, GAS의 TryActivateAbilitiesByTag를 호출.
  3. GAS 서버 통신: TryActivate 함수가 내부적으로 Built-in RPC를 태워 클라이언트 예측과 함께 서버에 안전하게 발동 요청을 전달.
  4. 데미지 적용 (Pull & SetByCaller): * GA가 ActivateAbility 되는 순간, 인벤토리에 접근하여 활성화된 스킬의 캐싱된 데미지 합산 값(CachedSummary)을 조회.
    • 가져온 수치를 Assign Tag Set By Caller 기능을 통해 Gameplay Effect (GE)에 주입하여 적에게 정확한 데미지를 가함.

오늘의 회고

  • 단순히 구현 가능 여부를 떠나, 멀티플레이어 환경과 엔진의 철학(Lyra 프레임워크, GAS)을 고려하며 설계하는 시야를 넓혔다.
  • "모든 기능은 컴포넌트를 잘게 쪼개는 것이 정답이다"라는 고정관념에서 벗어나, 데이터의 의존성과 네트워크 트랜잭션의 안전성을 저울질하여 합치는 것이 더 나은 아키텍처(통합 상태 관리자)일 수 있음을 배웠다.
  • GAS 시스템이 제공하는 "클라이언트 예측"과 "자동 RPC 통신"의 강력함을 실감했다. 앞으로도 로직은 최대한 어빌리티 내부로 격리하고, 캐릭터는 입력만 전달하는 구조를 지향해야겠다.

'프로그래밍 > Unreal Engine 5' 카테고리의 다른 글

[Unreal Engine5] GAS의 GameplayEffectContextHandle과 GameplayEffectSpecHandle  (0) 2026.04.20
[Unreal Engine 5] GAS_멀티플레이에서 GameplayCue가 작동하는 방식  (1) 2026.04.17
[Unreal Engine 5] 멀티플레이어 디버깅 유틸리티 & WorldContext  (0) 2026.04.06
[Unreal Engine 5] Module과 Plugin의 차이점  (0) 2026.04.02
[Unreal Engine 5] 싱글플레이어 vs 멀티플레이어(DedServer) GAS 아키텍처의 결정적 차이  (0) 2026.03.30
'프로그래밍/Unreal Engine 5' 카테고리의 다른 글
  • [Unreal Engine5] GAS의 GameplayEffectContextHandle과 GameplayEffectSpecHandle
  • [Unreal Engine 5] GAS_멀티플레이에서 GameplayCue가 작동하는 방식
  • [Unreal Engine 5] 멀티플레이어 디버깅 유틸리티 & WorldContext
  • [Unreal Engine 5] Module과 Plugin의 차이점
hanong8
hanong8
hanong8 님의 블로그 입니다.
  • hanong8
    HaNong
    hanong8
  • 전체
    오늘
    어제
    • 분류 전체보기 (102) N
      • 프로그래밍 (99) N
        • Unreal Engine 5 (45)
        • C++ (22)
        • UML (2)
        • 자료구조 (2)
        • 알고리즘 (9)
        • 개발일지 (4)
        • DirectX11 (5)
        • Git (2)
        • 코드카타 (8) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
hanong8
[Unreal Engine 5] 멀티플레이 아키텍처: GAS 퀵슬롯과 인벤토리 설계
상단으로

티스토리툴바