[Unity] HTTP 통신 모듈 빌더패턴으로 재구성Unity/Network2023. 3. 8. 11:14
Table of Contents
개요
위 글에서 작성했던 통신 모듈을 팝업 시스템 구현에 사용한 빌더패턴으로 재구성을 하는 글이다.
이유는
리퀘스트 전송 함수를 이런식으로 짰는데
protected virtual IEnumerator SendRequestCor(string url, SendType sendType, JObject jobj, Action<Result> onSucceed, Action<Result> onFailed, Action<Result> onNetworkFailed)
{
yield return StartCoroutine(CheckNetwork());
using (var req = new UnityWebRequest(url, sendType.ToString()))
{
Debug.LogFormat("url: {0} \n" +
"보낸데이터: {1}",
url,
JsonConvert.SerializeObject(jobj, Formatting.Indented));
byte[] bodyRaw = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jobj));
req.uploadHandler = new UploadHandlerRaw(bodyRaw);
req.downloadHandler = new DownloadHandlerBuffer();
req.SetRequestHeader("Content-Type", "application/json");
yield return req.SendWebRequest();
var result = ResultCheck(req);
if (result.IsNetworkError)
{
onNetworkFailed?.Invoke(result);
// TODO: 네트워크 재시도 팝업 호출.
yield return new WaitForSeconds(1f);
Debug.LogError("재시도");
yield return StartCoroutine(SendRequestCor(url, sendType, jobj, onSucceed, onFailed, onNetworkFailed));
}
else
{
if (result.IsSuccess)
{
onSucceed?.Invoke(result);
}
else
{
onFailed?.Invoke(result);
}
}
}
}
재시도를 자동으로 할 리퀘스트와 실패해도 넘어갈 리퀘스트를 구분하기 위해
파라미터를 추가하자니 모든 참조를 수정해야하는 대참사가 일어났고...
앞으로 파라미터가 또 안늘어난다는 보장도 없으니 이 김에 나중에 옵션을 추가하기 편한 빌더 패턴으로 바꾸게 됐다.
이전에 작성한 빌더 패턴을 사용한 팝업 시스템은 아래 글이다.
본문
우섯 첫번째로 새로 파라미터로 받을 Info클래스와 하위 Builder클래스를 만들었다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class HttpRequestInfo : MonoBehaviour
{
// url
public string URL { get; private set; }
// 전송 메소드
public HttpServerBase.SendType SendType { get; private set; }
// json body
public JObject Jobj { get; private set; }
// 실패시 재시도 팝업 노출 여부
public bool UseRetry { get; set; }
// 액션들
public Action<HttpServerBase.Result> OnSucceedAction { get; private set; }
public Action<HttpServerBase.Result> OnFailedAction { get; private set; }
public Action<HttpServerBase.Result> OnNetworkFailedAction { get; private set; }
private HttpRequestInfo(Builder builder)
{
this.URL = builder.URL;
this.SendType = builder.SendType;
this.Jobj = builder.Jobj;
this.UseRetry = builder.UseRetry;
this.OnSucceedAction = builder.OnSucceedAction;
this.OnFailedAction = builder.OnFailedAction;
this.OnNetworkFailedAction = builder.OnNetworkFailedAction;
}
public class Builder
{
// url
public string URL { get; private set; }
// 전송 메소드
public HttpServerBase.SendType SendType { get; private set; }
// json body
public JObject Jobj { get; private set; }
// 실패시 재시도 팝업 노출 여부
public bool UseRetry { get; set; }
// 액션들
public Action<HttpServerBase.Result> OnSucceedAction { get; private set; }
public Action<HttpServerBase.Result> OnFailedAction { get; private set; }
public Action<HttpServerBase.Result> OnNetworkFailedAction { get; private set; }
public Builder()
{
URL = string.Empty;
SendType = HttpServerBase.SendType.POST;
Jobj = null;
UseRetry = true;
}
public Builder SetUrl(string url)
{
this.URL = url;
return this;
}
public Builder SetJobj(JObject jobj)
{
this.Jobj = jobj;
return this;
}
public Builder SetUseRetry(bool use)
{
UseRetry = use;
return this;
}
public Builder SetAllAction(Action<HttpServerBase.Result> onSucceed, Action<HttpServerBase.Result> onFailed, Action<HttpServerBase.Result> onNetworkFailed)
{
this.OnSucceedAction = onSucceed;
this.OnFailedAction = onFailed;
this.OnNetworkFailedAction = onNetworkFailed;
return this;
}
public HttpRequestInfo Build()
{
return new HttpRequestInfo(this);
}
}
}
그리고 info객체를 파라미터로 받는 Send코루틴을
HttpServerBase클래스에 오버로딩으로 새로 만들었다.
protected virtual IEnumerator SendRequestCor(HttpRequestInfo info)
{
yield return StartCoroutine(CheckNetwork());
using (var req = new UnityWebRequest(info.URL, info.SendType.ToString()))
{
Debug.LogFormat("url: {0} \n" +
"보낸데이터: {1}",
info.URL,
JsonConvert.SerializeObject(info.Jobj, Formatting.Indented));
byte[] bodyRaw = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(info.Jobj));
req.uploadHandler = new UploadHandlerRaw(bodyRaw);
req.downloadHandler = new DownloadHandlerBuffer();
req.SetRequestHeader("Content-Type", "application/json");
yield return req.SendWebRequest();
var result = ResultCheck(req);
if (result.IsNetworkError)
{
info.OnNetworkFailedAction?.Invoke(result);
if (info.UseRetry)
{
// TODO: 네트워크 재시도 팝업 호출.
yield return new WaitForSeconds(1f);
Debug.LogError("재시도");
yield return StartCoroutine(SendRequestCor(info));
}
}
else
{
if (result.IsSuccess)
{
info.OnSucceedAction?.Invoke(result);
}
else
{
info.OnFailedAction?.Invoke(result);
}
}
}
}
이제 원본 Send코루틴을 참조하는 부분을 옮겨주려 했으나...
너무 시간낭비인것 같아서
오버로딩으로 두 함수를 일단 냅두고
대신 Obsolete Attribute로 경고 메세지를 남겼다.
[Obsolete("Use Overloaded method instead")]
protected virtual IEnumerator SendRequestCor(string url, SendType sendType, JObject jobj, Action<Result> onSucceed, Action<Result> onFailed, Action<Result> onNetworkFailed)
이렇게 Obsolete Attribute를 남기면 사용하는 부분에 초록색 밑줄과 함께 경고가 남게된다.
이제 다른 협업자가 SendRequestCor() 코루틴을 실행하려하면 경고를 보고
😁아! 오버로딩된 함수를 써야되는구나
라고 알아차려 주지않을까 생각한다.
결론
이번에 느낀 생각
파라미터가 많고 앞으로 파라미터가 추가 삭제 될 가능성이 농후하다면
꼭 빌더패턴이 아니더라도 클래스를 만들어서 그 객체를 파라미터로 받는게
나중에 수정할 때 편하다!
좋은 교훈을 얻었다.
'Unity > Network' 카테고리의 다른 글
[Unity] 오픈 소스 게임 서버 Nakama를 알아보자 (0) | 2024.10.24 |
---|---|
[Unity] HTTP REST api 통신 모듈 구현 (8) | 2023.02.14 |
[Unity] TCP서버 위치 동기화 데드 레커닝 구현 (0) | 2023.01.09 |