티스토리 뷰
🟩 학습 목표
- 다형성(Polymorphism)을 활용하여 컨테이너와 플레이어 모두 대응 가능한 상속 기반 인벤토리 컴포넌트 설계
- FGameplayTag 및 데이터 테이블을 연동하여 하드코딩 없는 데이터 주도형 아이템 시스템 구축
- 멀티플레이어 환경에서 아이템 복사 부정행위를 방지하는 스택(Stack) 제어 로직 및 Server RPC 보안 파이프라인 구현
🟧 1. 상속(Inheritance) 기반의 인벤토리 아키텍처 설계
🟦 다형성을 통한 코드 중복 및 메모리 낭비 방지
플레이어의 퀵슬롯 기능과 필드 상자의 파밍 기능을 하나의 컴포넌트에 통합할 경우, 불필요한 메모리 점유와 스파게티 코드가 양산되는 문제가 발생한다. 이를 해결하기 위해 객체 지향 프로그래밍의 상속 구조를 도입하였다.
- NCInventoryBaseComponent (부모): GridSize 기반 슬롯 생성, 아이템 입출력(Add/Remove), 서버 동기화 등 가방으로서의 공통 코어 로직을 전담한다. 일반 상자나 파밍 컨테이너에 부착하여 재사용한다.
- NCPlayerInventoryComponent (자식): 부모 클래스를 상속받아, 플레이어 캐릭터만 전용으로 사용하는 4칸짜리 QuickSlots 배열 및 인터페이스 기능만 확장하여 구현한다.
🟧 2. 게임플레이 태그(Gameplay Tag) 전면 도입 및 데이터 주도 설계
🟦 구조적 통일성 및 오타 위험 방지
아이템 분류 및 ID 체계를 기존의 FName이나 Enum 방식에서 FGameplayTag 구조로 전면 교체하였다. 이는 프로젝트 내 캐릭터 상태 제어 시스템과의 데이터 아키텍처 통일성을 확보하고, 하드코딩으로 인한 오타 에러를 사전에 방지하기 위함이다.
- 태그 예시: Item.Consumable.Potion, Item.Equipment.Weapon
🟦 기획 친화적 데이터 구조 수립
FItemData 구조체를 정의할 때 팀 C++ 코딩 컨벤션에 맞춰 에셋 참조 변수에 TObjectPtr를 엄수하여 적용하였다. 이를 기반으로 DT_ItemData 데이터 테이블을 구축하여, 프로그래머의 코드 수정 및 재컴파일 없이 기획 파트에서 에디터 조율만으로 아이템별 최대 스택 수량(MaxStackSize) 등을 실시간으로 제어할 수 있는 구조를 완성하였다.
🟧 3. 아이템 입출력 (CRUD) 및 스택(Stack) 시스템 C++ 구현
아이템 개수 관리 책임 및 로직을 개별 아이템 객체 클래스가 아닌 인벤토리 메인 매니저 로직으로 이관하여 구조를 캡슐화하였다.
🟦 AddItem (아이템 추가) 시퀀스
- 데이터 테이블을 조회하여 해당 아이템 태그의 MaxStackSize를 룩업한다.
- FindStackableSlot: 인벤토리 배열 내에서 동일한 태그를 가졌으면서 아직 최대 수량에 도달하지 않은 여유 슬롯이 있는지 탐색하여 남은 수량을 먼저 합산(Stacking)한다.
- FindEmptySlot: 기존 슬롯이 모두 만석이거나 스택이 불가능한 장비류 항목일 경우, 완전히 비어 있는 새로운 칸을 찾아 남은 수량을 할당한다.
🟦 RemoveItem (아이템 차감) 시퀀스
인덱스 및 지정 수량을 넘겨받아 차감을 진행하며, 연산 결과 수량이 0에 도달하면 슬롯의 식별자를 FGameplayTag::EmptyTag로 변경하여 완전 초기화 처리를 수행한다.
🟧 4. 트러블슈팅 (Troubleshooting)
🟦 이슈 1: 인벤토리 컴포넌트 데이터의 클라이언트 동기화 실패
- 원인: 가방 내부의 인벤토리 데이터 배열 변수에 Replicated 마킹을 지정했음에도 불구하고, 정작 배열을 소유한 인벤토리 컴포넌트 자체의 네트워크 통신 속성이 비활성화되어 있어 0 Array Elements 상태로 누락되었다.
- 해결: 부모 클래스인 ANCInventoryBaseComponent 생성자 내부에 컴포넌트 리플리케이션을 선언하는 아래 코드를 추가하여 네트워크 파이프라인을 활성화하였다.
SetIsReplicatedByDefault(true);
🟦 이슈 2: 클라이언트가 아이템 획득 시 데이터가 삭제되는 롤백 현상
- 원인: 클라이언트 로컬(클라이언트 프록시) 환경에서만 인벤토리 배열 값을 직접 조작하여 발생한 현상이다. 서버 권한(Authority) 측은 이 변화를 비정상적인 데이터 변조(핵 행위)로 판정하고, 서버가 가진 원본 데이터(빈 가방)를 다시 클라이언트에 강제로 덮어씌워 롤백시켰다.
- 해결: 입력 이벤트 발생 시 로컬 가방을 직접 조작하는 로직을 완전히 걷어냈다. 대신 Server RPC를 구현하여 서버에 데이터 처리를 정석으로 요청하도록 구조를 변경하였다. 서버 내에서 HasAuthority() 검증을 거친 후 안전하게 아이템 데이터를 추가 및 복제하도록 수정하여 아이템 복사 버그를 원천 차단하였다.
🟧 5. 후속 작업 (Next Steps)
- 에디터에서 배열 데이터 수량(Quantity)이 의도대로 스택형(3 ➔ 6 ➔ 9)으로 정상 누적 출력되는지 최종 검증한다.
- 백엔드 C++ 인벤토리 배열 데이터를 UI 화면에 1:1 슬롯 그리드로 바인딩하여 뿌려주는 UMG 위젯 화면 연동 작업을 준비한다.
🟧 핵심 요약
- 객체 지향 설계에 따라 공통 가방 기능(Base)과 플레이어 특화 기능(Player)을 상속 구조로 분리하여 모듈성을 확보하였다.
- FGameplayTag 매핑 및 데이터 테이블 기반 룩업 방식을 통해 에디터 친화적인 데이터 주도형 아이템 시스템을 정립하였다.
- SetIsReplicatedByDefault(true) 및 Server RPC 보안 검증 파이프라인을 구축하여 멀티플레이 데이터 무결성을 증명하였다.
- 데이터 변조 핵 방지를 위해 모든 데이터 변동 연산 권한을 서버(HasAuthority)에 집중시키는 안전한 인벤토리 코어 로직을 완성하였다.
'내일배움캠프 Unreal_7기 > 본캠프' 카테고리의 다른 글
| 멀티플레이 인벤토리 코어 시스템 구축 및 네트워크 데이터 흐름 검증 (1) | 2026.05.29 |
|---|---|
| 인벤토리 UI 최적화, 협업 아키텍처 및 MVP 구현 전략 (1) | 2026.05.28 |
| 캐릭터 상태 제어 리팩토링 및 멀티플레이 동기화 (0) | 2026.05.26 |
| 언리얼 엔진 5 AI 기초 시스템 및 경로 탐색 아키텍처 정리 (1) | 2026.05.22 |
| 캐릭터 이동 메커니즘 개선 및 모션 매칭 적용 (0) | 2026.05.21 |

