에러 핸들링 구현 패턴
GS2 를 사용한 게임 개발에서의 실전적인 에러 핸들링과 재시도 전략 모범 사례
GS2 를 이용한 네트워크 기능 구현에서 에러 핸들링은 게임의 안정성과 사용자 경험(UX)에 직결됩니다. 여기서는 단순히 예외를 포착하는 데 그치지 않는 실전적인 구현 패턴을 소개합니다.
1. 에러 분류와 대응 방침
GS2 의 예외는 그 성질에 따라 크게 3가지로 분류할 수 있습니다.
| 분류 | 해당하는 예외 (예) | 대응 방침 |
|---|---|---|
| 일시적인 에러 | InternalServerError, ServiceUnavailable, RequestTimeout | 자동 재시도. 몇 차례 시도해도 안 되는 경우 에러 다이얼로그를 표시. |
| 로직/설정 에러 | BadRequest, NotFound | 개발 중에 해결해야 할 에러. 릴리스 후에는 버그로 간주하여 로그를 수집하고, 사용자에게는 적절한 메시지를 표시. |
| 인증·상태 에러 | Unauthorized, Conflict, QuotaLimitExceeded | 특별한 복구 처리가 필요. 재로그인이나 데이터 재동기화(도메인 재취득)를 수행. |
2. 재시도 전략 구현(지수 백오프)
서버의 과부하나 일시적인 네트워크 불안정으로 인한 에러에 대해서는 즉시 재시도하는 것이 아니라, 간격을 두고 재시도하는 “지수 백오프(Exponential Backoff)“가 권장됩니다.
Unity / C# 에서의 예(자동 재시도)
public async Task<T> ExecuteWithAutoRetry<T>(Func<Task<T>> action, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
try
{
return await action();
}
catch (Gs2.Core.Exception.Gs2Exception e) when (e.RecommendAutoRetry) // 자동 재시도가 권장되는지 판정
{
if (i == maxRetries - 1) throw;
// 지수 백오프: 1s, 2s, 4s...
await Task.Delay((int)Math.Pow(2, i) * 1000);
}
}
throw new Exception("Reached unreachable code");
}수동 재시도 판단
RecommendAutoRetry 가 false 이고 RecommendRetry 가 true 인 경우(예: ConflictException 나 QuotaLimitExceededException), 자동으로 계속 반복하면 상황을 악화시킬 가능성이 있으므로, 사용자에게 확인을 요청하는 다이얼로그를 표시하여 재시도하게 하는 것이 일반적입니다.
3. 인증 에러(UnauthorizedException)의 자동 복구
액세스 토큰의 유효기간 만료 등으로 UnauthorizedException 이 발생한 경우, 사용자에게 타이틀 화면으로 돌아가도록 안내하는 것이 아니라, 백그라운드에서 자동으로 재로그인하여 요청을 재시도하는 것이 이상적입니다.
구현 예시
try
{
await gs2.Inventory.Namespace("...").Me(GameSession).Inventory("...").ModelAsync();
}
catch (Gs2.Core.Exception.UnauthorizedException)
{
// 1. 백그라운드에서 재로그인 처리를 실행
GameSession = await ReLogin();
// 2. 새로운 GameSession 을 사용하여 요청을 재시도
await gs2.Inventory.Namespace("...").Me(GameSession).Inventory("...").ModelAsync();
}4. 충돌(ConflictException) 해소
스탬프 시트 실행 중에 통신이 끊긴 경우 등에 ConflictException 이 발생할 수 있습니다. 이는 “이전 처리가 아직 서버 측에서 완료되지 않았거나, 혹은 중복되고 있다"는 것을 나타냅니다.
- 대응책: 대부분의 경우 단순한 재시도로 해결됩니다. GS2 SDK 의 상위 레벨 API(Domain 오브젝트)를 사용하는 경우, 내부 캐시와 서버 상태 사이에 불일치가 있을 가능성이 있으므로 Domain 오브젝트를 다시 가져온 후 재시도할 것을 권장합니다.
5. 사용자에게 주는 피드백(UX)
모든 에러에 대해 다이얼로그를 표시하면 사용자는 스트레스를 느낍니다.
- 사일런트 재시도: 일시적인 에러는 우선 백그라운드에서 1~2회 재시도합니다. 그동안 UI 에는 “통신 중…” 인디케이터만 표시합니다.
- 복구 가능한 다이얼로그: 재시도해도 실패한 경우, “통신에 실패했습니다. 전파가 양호한 곳에서 다시 시도해 주세요"와 같은 메시지와 [재시도] [타이틀로] 버튼을 표시합니다.
- 치명적인 에러: 점검 중이거나 앱 버전의 강제 업데이트가 필요한 경우에는, 타이틀 화면으로 돌아가는 것 외에는 선택지가 없는 전용 다이얼로그를 표시합니다.
정리
- 재시도 가능한 에러에는 지수 백오프를 적용한다.
- 인증 에러는 자동 재로그인으로 감춘다.
- 개발 중에는 카오스 모드를 활성화하여 이러한 핸들링이 올바르게 동작하는지 검증한다.