오늘의 할 일 |
프로젝트 회고 할 일 |
|
|
트러블 슈팅
시스템 아키텍처: 확장성에 초점을 둔 감자가 생각났어요

1. Shop 클래스 싱글톤 구조 해제 및 의존성 주입
☞ 문제 상황
상점 시스템을 처음 구현할 때, 전역 어디서든 상점 재고에 접근하기 쉽도록 Shop 클래스를 싱글톤 패턴으로 설계했었다.
기능 자체는 정상적으로 동작했으나 팀원 분의 깃 코드 리뷰 과정에서 클래스 명칭이 저희 프로젝트에서 싱글톤으로 구현된 클래스들과 맞지 않다는 등의 문제점이 제기되었다.
☞ 원인 분석 및 리뷰 피드백
- 과도한 싱글톤의 남용이 될 수 있음: 시스템 내에 매니저급 클래스들이 이미 여러 개 존재하는 상황에서, 단순한 상점 객체가 싱글톤으로 선언되면 전역 상태 관리가 복잡해질 수 있다.
- 통합 관리의 부재: 프로젝트 구조 상 GameManager가 게임 전체 생명 주기와 주요 객체들을 중앙에서 관리하고 있었는데, Shop만 싱글톤으로 존재하면 일관성이 떨어지고, 나중에 게임 재시작이나 상태 초기화 시 메모리 제어가 분산되는 문제가 발생할 수 있다.
☞ 해결 로직
팀원 분의 리뷰를 수용하여, Shop 클래스의 싱글톤 패턴을 해제하고 GameManager의 멤버 변수로 Shop을 할당하여 라이프사이클을 함께하도록 리팩토링을 진행했다.
코드 수정 내용은 다음과 같다.
- Shop.h 변경: GetInstance() 정적 메서드와 private 생성자를 삭제하고, 일반적인 클래스로 변경했다.
- GameManager에 편입: GameManager.h에 Shop* shop = nullptr; 멤버 변수를 추가하고 GameManager의 생성자에서 new Shop()을 할당, 소멸자에서 delete shop;을 수행하여 라이프사이클을 묶었다.
- State(호출부) 일괄 수정: 기존에 Shop::GetInstance()를 호출하던 모든 상태 클래스(ShopBuyState, ShopSellState, ShopStockState)의 코드를 GameManager::GetInstance().GetShop()을 통해 포인터로 받아오도록 전면 수정했다.
자세한 코드는 다음 링크에서 확인 가능하다.
refactor: Shop 싱글톤 해제 · NBC-TRPG6/TRPG6@7710d7f
@@ -22,10 +23,10 @@ void ShopStockState::Update(int ch, std::string& lastCommand)
github.com
☞ 결과
객체의 생명 주기가 GameManager 하나로 통합되어 메모리 누수 위험이 감소하였고, 초기화/해제 로직이 깔끔해졌다.
또한, 클래스 간의 의존성이 명확해져 객체 지향 설계 원친에 더 부합하는 구조가 되었다.
이 경험을 통해 무분별한 싱글톤 사용의 위험성을 깨달았고, 객체 간의 올바른 참조 방식과 코드 리뷰를 통한 구조 개선의 중요성을 배웠다.
2. 리슨 서버 모델에서의 호스트 데이터 동기화 예외 처리
☞ 문제 상황
아이템 거래 시스템 구현 중, 클라이언트 간의 거래는 정상적으로 아이템이 교환되었으나, 방장이 거래에 참여할 경우 방장의 인벤토리가 실시간으로 갱신되지 않는 현상이 발생했다.(방장이 거래를 수락해도 방장의 화면에는 아이템 변화가 없음)
☞ 원인 분석
리슨 서버의 패킷 루프백 부재: 일반적인 클라이언트는 서버에 요청을 보내고 서버가 브로드캐스트하는 패킷을 받아 자신의 데이터를 갱신한다. 하지만 본 프로젝트의 네트워크 구조에서는 방장이 서버 역할을 겸하기 때문에 방장이 보낸 브로드캐스트 패킷은 다른 클라이언트들에게 전송되지만, 방장 본인의 수신 루프에는 도달하지 않는다.
결과적으로 방장은 다른 클라이언트들에게는 데이터가 바뀌었다고 알려주지만, 정작 자기 자신의 로컬 데이터를 갱신하는 함수는 호출하지 않는다.
☞ 해결 로직
방장 본인이 거래에 참여할 경우 패킷을 브로드캐스트한 직 후, 자신의 로컬 동기화 함수를 직접 호출하도록 강제하여 문제를 해결했다.
코드 수정 내용은 다음과 같다.
- 방장이 거래 응담을 처리하는 Server_HandleResponse 함수 마지막에 로컬 동기화 함수인 SyncTrade() 호출을 추가했다.
자세한 코드는 다음 링크에서 확인 가능하다.
add: 아이템 거래 시 방장에게도 인벤토리 변경사항 적용 · NBC-TRPG6/TRPG6@5896b64
@@ -101,25 +101,24 @@ void TradeManager::Server_HandleResponse(uint32_t tradeId, uint8_t response)
github.com
☞ 결과
방장과 클라이언트 구분 없이 모든 환경에서 거래 즉시 인벤토리가 갱신되는 것을 확인하였고, 리슨 서버 모델의 특수성을 이해하기 되었다. 서버가 곧 클라이언트인 환경에서는 패킷을 보냈으니 서버도 당연히 받겠지라는 가정이 가장 위험하다는 것을 배웠고, 전역적인 패킷 처리 루틴 외에도 호스트만을 위한 로컬 실행 경로를 반드시 고려해야 함을 깨달았다.
☞ 문제 해결 전 후 실행 영상 비교


'내배캠 > CH2 팀프로젝트(감자가생각났어요)' 카테고리의 다른 글
| [TIL: 2026.06.03] TRPG 프로젝트 진행 시 담당했던 파트 코드 분석 회고(2) (0) | 2026.06.03 |
|---|---|
| [TIL: 2026.06.02] TRPG 프로젝트 분석 및 회고(1) (1) | 2026.06.02 |
| [TIL: 2026.05.29] TRPG 팀프로젝트 종료 회고록 (0) | 2026.06.01 |
| [TIL: 2026.05.28] C++ TRPG 프로젝트: 서버 검증 기반 1:1 아이템 거래 시스템 구현 (0) | 2026.06.01 |
| [TIL: 2026.05.22] C++ TRPG 인벤토리 구조 리팩토링 및 렌더러 기반 상점 UI 구축 트러블슈팅 (0) | 2026.06.01 |