프로젝트 일지/Unity

[Unity/TIL] Firebase Cloud Functions - 서버에서 뽑기 로직 돌리기(2)

톰마토 2025. 6. 24. 14:09
728x90

2025.05.19 - [프로젝트 일지/Unity] - [Unity/TIL] Firebase Cloud Functions - 서버에서 뽑기 로직 돌리기(1)

 

[Unity/TIL] Firebase Cloud Functions (1) - 함수 배포하기

프로젝트 '오집마'에서는 가챠 시스템이 존재한다. 그런데 가챠 로직을 클라에서 돌리고 있었는데, 이는 실제 출시하는 게임에서는 있을 수 없는 일이다! 그래서 우리도 Cloud Functions를 사용하여

ramenkirby.tistory.com


초기 세팅

FirebaseFunctions 인스턴스를 받아놓는다. 비동기함수이므로 functions 함수를 호출하는 시점과 비교/판단해서 적잘한 곳에서 초기화하면 된다.

    FirebaseFunctions functions;

    public void Init()
    {
        if (functions != null) return;

        // Firebase 초기화
        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
        {
            if (task.Result == DependencyStatus.Available)
            {
                functions = FirebaseFunctions.DefaultInstance;
                IsReady = true;
                Util.Log("Firebase 준비 완료!");
            }
            else
            {
                Util.LogError("Firebase 초기화 실패: " + task.Result.ToString());
            }
        });
    }

호출 

호출 후 결과를 받는 것도 비동기로 이루어지기 때문에 서버에서 받은 결과값으로 실행할 함수는 onResult Action으로 받아 실행시켜줬다. 

    public void CallGacha(int count, bool isUnit, Action<List<GachaResult>> onResult = null)
    {
        if (functions == null)
        {
            Init();
        }

        // Cloud Function에 넘길 데이터(callData) 준비하는 함수
        SettingGradeRanges(count, isUnit);

        functions.GetHttpsCallable("gachaDrawWithGuarantees")
            .CallAsync(callData)
            .ContinueWithOnMainThread(task =>
            {
                if (task.IsFaulted || task.IsCanceled)
                {
                    Util.LogError("가챠 실패: " + task.Exception);
                    return;
                }

                // Data를 JSON 문자열로 변환 (바로 변환이 어려워서 이런 방식으로 결정)
                string json = JsonConvert.SerializeObject(task.Result.Data);
                // JSON 역직렬화
                GachaResultWrapper parsed = JsonConvert.DeserializeObject<GachaResultWrapper>(json);
                foreach (GachaResult r in parsed.results)
                {
                    //Util.Log($"등급: {r.grade}, ID: {r.id}"); // 테스트용
                }
                onResult?.Invoke(parsed.results);
            });

    }

 

서버에서 계산되고 넘어온 데이터 task.Result.Data는 ~~때문에 저렇게 파싱했다.

 

functions에 데이터를 넘길 때 firebase에서 알아서 한 번 더 키-값으로 묶어서 보내지기 때문에 js에서 data를 바로 사용하면 안되고 data.data를 받아서 써야 한다. 처음에 이거를 몰라서 한참 헤맸다.

 

이런 구조로 데이터를 받게 된 이유는 아래 디버깅 과정에 담았다.


디버깅 과정

함수를 서버에 배포하는 것보다 오류 원인 찾고 해결하는 것이 어려웠다. js쓰는 것도 낯선데 디버깅이 번거로워!! 직접 콘솔로그를 찍어서 봤다.

firebase functions:log 명령어로 js에서 찍어둔 로그를 확인할 수 있다. 

콘솔창에서 로그 확인하는 모습

 

데이터를 무조건 Dictionary<string, object> 유형 바로 키-값 쌍으로 넣어줘야 해서 아래와 같은 모양새로 넣어주었다.

그런데 Log를 봤을 때 gradeRanges가 제대로 나오지 않는 모습이 보였다. drawCount도 100을 넣어 호출한건데 10이 나왔다. 아래 코드처럼 js에서 Number로 변환 실패하면 10으로 나오게한거라 로그를 보고 제대로 안들어갔음을 알 수 있었다...

drawCount 예외 처리

🔽 잘못된 걸 확인했던 로그 

gradeRanges는 undefined, drawCount는 10으로 찍힘

2025-05-19T05:56:22.152857Z W gachadrawwithguarantees:
2025-05-19T05:56:22.164751Z D gachadrawwithguarantees: {"verifications":{"app":"MISSING","auth":"MISSING"},"message":"Callable request verification passed"}
2025-05-19T05:56:22.164873Z ? gachadrawwithguarantees: gradeRanges: undefined

2025-05-19T05:56:22.164947Z ? gachadrawwithguarantees: drawCount: 10

 

 

디버깅해보면 서버에서 오는 Data가 results 키에 담겨오는 것을 알 수 있는데 (사진 참고)

Firebase SDK가 자동으로 data: {...} 로 감싸기 때문에 유니티에서 제대로 보냈어도 제대로 파싱이 안됐을 가능성을 예측할 수 있었다. 그래서 data.data로 사용하니 해결된 것임.

results에 한 번 담겨옴


정리

1. 서버에 데이터를 보낼 때는 그대로 gradeRanges 키 - 값, gradeCount 키 - 값의 Dictionary 형태로 보낸다.

2. 서버에서는 받은 data에서 data를 한 번 더 꺼내서 사용한다. data.data

1번 참고사진
2번 참고사진


실사용 코드

서버 함수 호출하는 코드

 

호출할 때 넣어주는 데이터인 callData 준비하는 코드

728x90