[25.06.09] :: 가디언 앤 시커 프로젝트 10

chooha·2025년 6월 11일

가디언앤시커

목록 보기
10/25

📝 개발일지 - 아케인보드 직업 변경 동기화 문제

👨‍💻 오늘의 개발 작업

오늘은 아케인보드 시스템에서 직업을 변경하고 빠르게 위젯을 열면 이전 직업의 그리드가 보이는 문제를 해결했음

처음엔 델리게이트 타이밍이나 위젯 초기화 순서 문제인 줄 알았는데, 알고 보니 네트워크 복제 지연과 UI 반응성 사이의 근본적인 동기화 문제였음

최종적으로 델리게이트 방식을 포기하고 버튼 클릭 시 즉시 업데이트하는 직접 호출 방식으로 해결했음


💡 오늘의 5분 기록

1. 문제 확인 - 이전 직업 그리드가 보임

아케인보드 시스템을 테스트하니까 뭔가 이상했음

문제 상황

사용자 입장에서는 직업을 바꿨는데 이전 설정이 보이니까 정말 불쾌한 경험이었음

2. 원인 파악 - 네트워크 복제 지연

코드 흐름을 자세히 추적해봤음

현재 시스템 구조

1. 버튼 클릭 → Server_SetSeekerJob() RPC 호출
2. 서버에서 PlayerState 업데이트
3. 클라이언트로 복제 (시간 소요 )
4. OnRep_SeekerJob() → 델리게이트 호출
5. ArcaneBoardLPS::OnPlayerJobChanged() 실행
6. BoardManager 업데이트

핵심 문제점

  • 3번 복제 과정에서 시간이 소요됨
  • 사용자가 빠르게 아케인보드를 열면 복제 완료 전에 위젯이 초기화됨
  • 결과적으로 이전 직업 정보로 그리드가 생성됨

3. 해결 과정 - 여러 방법 시도

여러 해결책을 시도해봤음

시도 1: 델리게이트에 직업 정보 추가

// 기존: OnJobChangedDelegate(EPlayerRole)
// 수정: OnJobChangedDelegate(EPlayerRole, ESeekerJob)

→ 여전히 네트워크 복제 지연 문제 해결 안 됨

시도 2: 위젯에서 PlayerState 델리게이트 바인딩

// 아케인보드 위젯이 열린 후에도 직업 변경 감지
Widget->BindPlayerStateDelegate()

→ 위젯이 열린 후 그리드가 바뀌는 UX 문제 발생

시도 3: 타이머 기반 재확인

// 0.1초 후 다시 확인
GetWorld()->GetTimerManager().SetTimer(...)

→ 불확실하고 근본적 해결책이 아님

4. 문제 해결 - 즉시 업데이트 방식

결국 델리게이트를 포기하고 버튼 클릭 시 즉시 업데이트하는 방식으로 변경했음

최종 해결책

// GS_CharacterSelectList.cpp
void UGS_CharacterSelectList::OnCharacterSelectClicked(int32 CharacterID, EPlayerRole PlayerRole)
{
    if (PlayerRole == EPlayerRole::PR_Seeker)
    {
        // 즉시 아케인보드 업데이트 (새로 추가)
        if (UGS_ArcaneBoardLPS* LPS = LocalPlayer->GetSubsystem<UGS_ArcaneBoardLPS>())
        {
            ECharacterClass NewCharacterClass = LPS->MapSeekerJobToCharacterClass((ESeekerJob)CharacterID);
            LPS->OnPlayerJobChanged(NewCharacterClass);  // 직접 호출
        }
        
        // 기존 RPC 호출
        GSPlayerState->Server_SetSeekerJob((ESeekerJob)CharacterID);
    }
}

코드 단순화

  • 델리게이트 바인딩 코드 모두 제거
  • PlayerState 복제를 기다리지 않고 즉시 업데이트
  • 매개변수로 직접 ECharacterClass 전달해서 변환 로직 중복 제거

5. 성과와 깨달은 점

이제 직업을 변경하고 즉시 아케인보드를 열어도 올바른 그리드가 바로 보임

설계 개선사항

  • 네트워크 복제와 UI 반응성을 분리해서 처리
  • 중요한 UI 업데이트는 사용자 액션과 동시에 즉시 실행

깨달은 점
멀티플레이어 게임에서 네트워크 복제는 항상 지연이 있다는 것을 항상 고려해야 함. 특히 UI 반응성이 중요한 부분은 복제를 기다리지 말고 즉시 로컬에서 처리하는 것이 사용자 경험에 훨씬 좋음.


📚 개발 참고

네트워크 복제와 UI 동기화 패턴

// 안티패턴: 복제 완료를 기다림
버튼 클릭 → RPC → 복제 → 델리게이트 → UI 업데이트

// 권장패턴: 즉시 로컬 업데이트 + 백그라운드 동기화  
버튼 클릭 → 즉시 UI 업데이트 + RPC (백그라운드)

핵심 포인트

  • 네트워크 복제 지연: 항상 0.1~0.3초 소요됨을 가정해야 함
  • UI 반응성: 사용자 액션에 대한 즉시 피드백이 중요
  • 델리게이트 vs 직접호출: 단순한 로직은 직접 호출이 더 명확
  • 로컬 우선 업데이트: 중요한 UI는 로컬에서 먼저 처리하고 서버 동기화는 백그라운드에서

0개의 댓글