티스토리 뷰

개요

안녕하세요 Shyplants입니다!

저번 DevLog #5에서 서버사이드 안정적으로 동작을 위한 품질 개선에 이어

이번 DevLog #6에서는 클라이언트 멀티플레이 품질 개선을 위한 작업내용을 정리해보려 합니다.

 

기존 MultiPlayState 구성도

위 그림과 같이 기존 MultiPlayState는 주요 4가지 기능을 담당하는 코드가 한 클래스에 있어 복잡하고, SRP에 위배되었는데요.

이를 다음과 같이 개선하였습니다.

 

개선된 MultiPlayState 구성도

 

개선된 모듈의 주요 역할은 다음과같습니다.

 

[MultiPlayLogic]

- 역할: 게임 규칙 (Move, Rotate, Hold, Drop, Ghost, Board Lock 등)

 

[MultiPlayNetwork]

- 역할: 서버 동기화 (SyncFlag 기반 패킷 전송, 서버 패킷 처리)

 

[MultiPlayRenderer]

- 역할: 화면 렌더링 (Local/Remote ConsoleRenderer로 분리 렌더링)

 

[MultiPlayState]

- 역할: 게임 전체 제어 (입력 처리, 사운드 재생, GameOverState 전환)

 

사운드 로직 완전 분리 (Event Flag 방식)

개선된 구조에 따르면 Logic 모듈에서 사운드 재생이 필요함을 인지하고, State 모듈에 이를 요청해야 하는데요.

해당 과정은 아래와 같습니다.

 

[MultiPlayLogic]
  m_bPlayFloorSE = true;    // 바닥 충돌
  m_bPlayComboSE = true;    // 콤보 발생

         ▼  Logic은 단지 이벤트만 표시
         
[MultiPlayState]
  PlaySoundEffects();
  
         ▼
         
[SoundManager]
  PlaySE_Force("floor");
  PlaySE_Force("combo_3");

 

코드 품질 정리

 

이번 DevLog에서 작업했던 품질 개선 핵심은 아래와 같습니다.

 

1. 전방 선언 적극 활용

 

2. unique_ptr 멤버가 있는 클래스는 명시적 default destructor 제공

컴파일 결과 "불안정한 형태 사용~~" 무수한 에러가 저를 반겨주었는데요.. 

 

unique_ptr<T>는 소멸 시점에 delete T 호출이 필요하기 때문에

**소멸자가 인스턴스화 되는 순간 T가 완전한 타입(complete type)** 이어야 하는데요.

 

하지만 해당 클래스 소멸자를 따로 작성하지 않으면

컴파일러는 암시적 destructor를 헤더에서 inline으로 생성하고,

이 시점에서 unique_ptr<T>의 소멸자도 인스턴스화됩니다.

 

이 때 T가 전방 선언 상태라 불완전 타입이므로

unique_ptr<T>는 delete를 수행할 수 없어 컴파일 에러가 발생하게 됩니다.

 

이를 해결하기 위해 클래스 소멸자를 사용하지 않더라도 아래와 같이 작업해야 합니다.

헤더에서 클래스 소멸자를 선언하고, cpp에서 해당 소멸자를 정의합니다.

그러면 unique_ptr<T>의 소멸자 인스턴스화가 T의 정의가 보이는 cpp 시점으로 지연되어 문제를 해결할 수 있습니다!

 

3. SyncFlag / SoundFlag / ComboFlag 등 이벤트 기반 전달 구조 설계

 

끝으로

이번 DevLog #6에서는 저번에 이어 새로운 기능 추가보다는 구조 리팩토링 및 코드 안정화 작업을 하였습니다.

새로운 기능을 추가하기 전에 기존 베이스를 튼튼하게 개선할 필요성을 강하게 느꼈는데요.

다음 DevLog #7에서도 새로운 기능을 추가하기에 적합한지 기존 코드를 되집어 보고,

(개선 or 새로운 기능) 추가 작업을 해볼 것 같습니다!!

 

 

댓글