Unity/게임개발

Unity 유니티 HTTP 서버 통신 모듈 구현 (2)

한니닝 2025. 4. 1. 21:56

이전 글 ↓↓

https://hanni01.tistory.com/9

 

Unity 유니티 HTTP 게임 서버 통신 모듈 구현

까마득한 예전 작업을 이제서야 정리하는 글.게임 개발 중에 서버와의 소통을 위한 통신 모듈을 만들 필요가 있었다.그래서 여러 사이트들을 참고하여 구현해본 HTTP 통신모듈 유니티이기 때문

hanni01.tistory.com

 


유니티 클라이언트와 게임 서버간의 HTTP 통신을 위해 구현했던 모듈을 개선할 필요가 생겼다.

HTTP 모듈 뿐만 아니라 게임 전체적으로 사실 코루틴을 많이 사용했었는데, 이 코루틴이

1. 객체를 생성할 때 힙 메모리에 할당이 돼서, 반복적으로 객체를 생성하면 성능을 잡아먹게 된다는 것.

2. 코루틴은 IEnumerator를 반환하고, 비동기 실행이 끝난 후 값을 직접 반환할 수 없어서, 콜백을 사용해 가독성이 떨어진다는 점

을 알았다.

 

네트워크 요청에 있어서 간단한 요청은 괜찮을지 모르겠지만, 복잡한(재시도, 취소, 병렬 처리, 에러 핸들링)에서 한계가 있음을 알았다. 

 

해서 찾아보니 유니티에서 더 적합한 UniTask라는 것을 알게되었다.

 

UniTask

  • 구조체 기반, 스택 할당
  • 내부적으로 Task Pool을 미리 생성해 자주 사용되는 비동기 작업 객체를 풀에 저장하고 필요할 때 재사용
    • Zero Allocation 기대 가능
  • async/await 패턴을 사용해 비동기 작업 처리: 직관적이며 유지보수하기 쉬움
  • try-catch를 통한 예외를 쉽게 처리할 수 있음(코루틴에선 불가능함)
  • 병렬 처리 간편: UniTask.WhenAll()같은 기능으로 여러개의 네트워크 요청을 동시에 실행 가능

 

하여 프로젝트의 모든 코루틴을 UniTask로 수정하는 작업을 갖게 되었다.

당연 HTTP 통신 모듈도 예외는 아니었다. 

 


SendRequest 개선 모습

public static async UniTaskVoid SendRequest(string url, SendType sendType, Action<Result> onSuccess = null, Action<Result> onError = null, string jsonData = null)
{
    var result = await SendRequest(url, sendType, jsonData);

    if (result.IsSuccess)
    {
        onSuccess?.Invoke(result);
    }
    else
    {
        onError?.Invoke(result);
    }
}

private static async UniTask<T> SendRequest<T>(string url, SendType sendType, string jsonData = null)
{
    var result = await SendRequest(url, sendType, jsonData);

    if (result.IsSuccess)
    {
        return ParseJson<T>(result.Json);
    }

    Debug.LogError($"오류 발생: {result.Error}");
    return default;
}

private static async UniTask<Result> SendRequest(string url, SendType sendType, string jsonData = null)
{
    if (!IsSessionAvailable())
    {
        return CreateErrorResult("Session 키가 존재하지 않음");
    }

    var customHeader = PlayerPrefs.GetString("Session");

    if (!await CheckNetwork())
    {
        return CreateErrorResult("네트워크 연결이 되어있지 않아 Request 종료");
    }

    using var req = CreateRequest(url, sendType, customHeader, jsonData);

    await req.SendWebRequest().ToUniTask();
    return HandleRequest(req);
}
  1. SendRequest(string url, SendType sendType, Action<Result> onSuccess = null, Action<Result> onError = null, string jsonData = null)
    • 비동기 요청을 보낸 후, 성공하면 onSuccess, 실패하면 onError 콜백 호출
    • UniTaskVoid를 반환하므로 결과를 기다리지 않고 즉시 실행
    • 특정한 리턴값이 필요없고, 단순히 성공/실패에 따른 동작을 수행할 때
  2. SendRequest<T>(string url, SendType sendType, string jsonData = null)
    • 네트워크 요청을 보내고, 응답 데이터를 특정타입 T로 변환해서 반환
    • JSON 데이터를 받아서 T 타입 객체로 변환(ParseJson<T>(result.Json))
    • 실패하면 default(T)를 반환(각 자료형의 기본값)
    • UniTask<T>를 반환하므로, 요청 결과를 기다린 후 사용할 때 유용
  3. SendRequest(string url, SendType sendType, string jsonData = null)
    • 실제로 HTTP 요청을 수행하는 핵심 함수
    • 세션 키 확인 -> 네트워크 상태 확인 -> 요청 전송 -> 결과 처리 순
    • Result 타입을 반환하여 성공/실패 여부와 데이터를 포함.

좀 더 유연한 사용을 위해 SendRequest는 콜백 기반 메서드와 제네릭 변환 메서드가 따로 구현되었다.

 


 

나머지 코드 부분들은 유지보수성과 재사용성, 가독성 등을 위해 함수 분리, HTTP Monobehaviour가 아닌 전역 클래스(static)으로 변경 등의 작업만 이루어졌고, 그 외 바뀐 부분은 크게 없다.