뒤끝 서버시간 호출문의

고객님의 문의에 답변하는 직원은 고객 여러분의 가족 중 한 사람일 수 있습니다.
고객의 언어폭력(비하, 조롱, 욕설, 협박, 성희롱 등)으로부터 직원을 보호하기 위해
관련 법에 따라 수사기관에 필요한 조치를 요구할 수 있으며, 형법에 의해 처벌 대상이 될 수 있습니다.

커뮤니티 이용 정책에 위배되는 게시물을 작성할 경우, 별도 안내 없이 게시물 삭제 또는 커뮤니티 이용이 제한될 수 있습니다.

문의 응대 : 평일 오전 10시 ~ 오후 6시
문의를 남기실 경우 다음 항목을 작성해 주세요.
정보가 부족하거나 응대시간 외 문의하는 경우 확인 및 답변이 지연될 수 있습니다.

  • 뒤끝 SDK 버전 :
  • 프로젝트명 :
  • 스테이터스 코드 :
  • 에러 코드 :
  • 에러 메시지 :

뒤끝 서버시간을
BackendReturnObject servertime = Backend.Utils.GetServerTime();

string time = servertime.GetReturnValuetoJSON()[“utcTime”].ToString();
DateTime parsedDate = DateTime.Parse(time);

이렇게 받아오라고 뒤끝개발자사이트에서 확인했는데
이호출을 계속하면 서버 비용이 어마어마하게 나올것같은데
처음 로그인할때 받아오고 나서 호출없이 시간을 받아오는 방법은 없을까요??

저는 시작할때 서버시간과(baseServerTime) Time.unscaledTime값(baseRealtime)을 저장하고

public DateTime GetCurrentServerTime()
{
float elapsed = Time.unscaledTime - baseRealtime;
return baseServerTime.AddSeconds(elapsed);
}
이렇게 체크했는데 이게 시간이 정확하게 안맞는것 같은 느낌이들어서 문의 드립니다.

안녕하세요, 개발자님.

현재 뒤끝에서는 GetServerTime() 호출 외에,
별도로 호출 없이 서버 시간을 확인하는 기능은 제공되지 않고 있습니다.

비용 최적화를 위해 호출을 1회만 진행하고자 한다면,
말씀 주신 것처럼 로그인 시점에 한 번 서버 시간을 호출한 후 baseServerTime과 baseRealtime(Time.unscaledTime)을 저장하고, 이후에는 로컬 타이머 방식으로 경과 시간을 계산하여 사용하는 방법이 현재로서는 유일한 방식입니다.

혹 서버 시간을 지속적으로 확인하고자 하시는 특별한 이유나 사용 목적이 있으실까요?

항상 친절하게 답변해주셔서 감사합니다^^

저는 방치형게임을 서비스중 입니다.

그래서 몇몇 컨텐츠가 특정 시간에 맞춰서 초기화된 후 유저들이 다시 이용할 수 있게 서비스를 해주고있습니다.

그런데 제가 테스트하는 단말기에서는 앞서 시간체크를 하는 방식으로 초기화가 정상적으로 이뤄지고있는데

몇몇 유저들이 초기화가 이뤄지고있지않습니다.

그래서 질문 드렸습니다…

좋아요 1

제가 서버시간을 저장하고 받아오는 방식이 잘못된걸까요?

public void SaveResetTimeData()
    {
        if (!BackendManager.IsLoggedIn) return;

        string inDate = InDateManager.Get("ResetTimeData");
        if (string.IsNullOrEmpty(inDate))
        {
            Debug.LogWarning("ResetTimeData 저장 실패: inDate 없음");
            return;
        }

        //서버 시간 요청
        SendQueue.Enqueue(Backend.Utils.GetServerTime, serverTimeCallback =>
        {
            if (!serverTimeCallback.IsSuccess())
            {
                Debug.LogError("서버 시간 가져오기 실패: " + serverTimeCallback);
                return;
            }

            string serverTimeString = serverTimeCallback.GetReturnValuetoJSON()["utcTime"].ToString();
            DateTime serverTime = DateTime.Parse(serverTimeString);
            Debug.Log(serverTime.ToString("o"));
            Param data = new Param
            {
                { "lastAccessTime", serverTime.ToString("o") }, // 서버 UTC 시간 저장
                { "resetToday", resetToday }
            };

            // 최종 데이터 저장
            SendQueue.Enqueue(Backend.GameData.UpdateV2, "ResetTimeData", inDate, Backend.UserInDate, data, callback =>
            {
                if (!callback.IsSuccess())
                {
                    Debug.LogError("ResetTimeData 저장 실패: " + callback);
                }
            });
        });
    }

    public void LoadResetTimeData()
    {
        if (!BackendManager.IsLoggedIn) return;

        SendQueue.Enqueue(Backend.GameData.GetMyData, "ResetTimeData", new Where(), callback =>
        {
            if (callback.IsSuccess())
            {
                var jsonData = callback.FlattenRows();
                if (jsonData.Count > 0)
                {
                    // inDate 캐싱
                    var row = jsonData[0];
                    InDateManager.Set("ResetTimeData", row["inDate"].ToString());

                    string rawTime = row["lastAccessTime"].ToString();
                    lastAccessTime = DateTime.Parse(rawTime); // 시간대 포함된 문자열 → 정확히 파싱됨
                    //lastAccessTime = parsedTime.ToUniversalTime(); // UTC 기준 고정

                    //Debug.Log($"[LoadResetTimeData] 로드된 lastAccessTime(KST): {lastAccessTime:yyyy-MM-dd HH:mm:ss}");


                    resetToday = bool.Parse(row["resetToday"].ToString());
                    
                    GoNextProcess(LoadProcess.LOAD_IDLETIME);
                }
                else
                {
                    // 서버 시간 가져오기 (비동기)
                    SendQueue.Enqueue(Backend.Utils.GetServerTime, serverTimeCallback =>
                    {
                        if (!serverTimeCallback.IsSuccess())
                        {
                            Debug.LogError("서버 시간 가져오기 실패 (초기화 중)");
                            return;
                        }

                        string serverTimeString = serverTimeCallback.GetReturnValuetoJSON()["utcTime"].ToString();
                        DateTime serverTime = DateTime.Parse(serverTimeString);

                        lastAccessTime = serverTime;
                        resetToday = false;

                        Param initData = new Param
                        {
                            { "lastAccessTime", serverTime.ToString("o") },
                            { "resetToday", resetToday }
                        };

                        //데이터 저장
                        SendQueue.Enqueue(Backend.GameData.Insert, "ResetTimeData", initData, insertCallback =>
                        {
                            if (insertCallback.IsSuccess())
                            {
                                string inDate = insertCallback.GetInDate();
                                InDateManager.Set("ResetTimeData", inDate);
                            }
                            else
                            {
                                Debug.LogError("초기 데이터 삽입 실패: " + insertCallback);
                            }

                            GoNextProcess(LoadProcess.LOAD_IDLETIME);
                        });
                    });
                }
            }
            else
            {
                Debug.LogError("ResetTimeData 불러오기 실패: " + callback);
            }
        });
    }

이렇게 보상받은 시간을 저장하고 다음 접속때 불러오게해놨는데 왜 초기화가안되는 유저가 발생하는지 이유를 모르겠습니다.
보상은 9시에 받게 하기위해 업데이트문에서 체크하고있으며,

private void Update(){
 DateTime serverTime = GetCurrentServerTime();              // 서버 시간 기준 계산
        DateTime todayResetTime = new DateTime(serverTime.Year, serverTime.Month, serverTime.Day, 9, 0, 0); //오늘 9시로 고정해주는 코드 ex) 25-07-14 오전09:00

        if (serverTime >= todayResetTime && lastAccessTime < todayResetTime)
        {
            resetToday = false;
        }
}
 public void InitializeServerTime()
    {
        if (!Backend.IsInitialized) return;

        var bro = Backend.Utils.GetServerTime();
        if (bro.IsSuccess())
        {
            string time = bro.GetReturnValuetoJSON()["utcTime"].ToString();

            baseServerTime = DateTime.Parse(time);      //한국시간 KTS
            //baseServerTime = DateTime.Parse(time, null, System.Globalization.DateTimeStyles.AdjustToUniversal);   //세계시간
            baseRealtime = Time.unscaledTime;

            Debug.Log("서버 시간 초기화 완료: " + baseServerTime + "\n 리얼타임 : "+ baseRealtime); // 한국 시간으로 출력
        }
        else
        {
            DebugHelper.LogError("서버 시간 초기화 실패: " + bro.GetMessage());
        }
    }
public DateTime GetCurrentServerTime()
    {
        float elapsed = Time.unscaledTime - baseRealtime;
        return baseServerTime.AddSeconds(elapsed);
    }

시간체크는 이렇게하고있으며 resetToday 이게 false가 되는순간 초기화가 진행됩니다.

한달넘게 초기화 관련으로 문제가 있는데 방식이틀렸다면 뒤끝에서 어떤기능을 사용해야하는지 알려주시면 감사하겠습니다.

DateTime.Parse를 사용하신 특별한 이유가 있으실까요?

뒤끝의 서버 시간 조회 결과는 UTC 기준으로 제공되기 때문에,
기기의 로컬 문화권(CultureInfo)에 따라 변환되지 않도록 DateTime.Parse을 사용하지 않고 UTC 그대로 활용하시는 것이 예상된 리셋 시점 비교에 가장 안전합니다.

여기서 설명해주길 tostring로 시간을받고 DateTime.Parse로 변환을해서 사용하길레 저렇게 코드를 제작했습니다~

bro.GetReturnValuetoJSON()[“utcTime”].ToString()이렇게 받는게 문자열이기때문에 가이드처럼 변환해줘야 시간비교가 되는게 아닐까요?

네, 말씀 주신 것처럼 utcTime 값은 문자열 형태로 반환되기 때문에
비교를 위해서는 DateTime.Parse() 또는 DateTimeOffset.Parse() 등을 통해 변환하는 과정이 필요합니다.

다만 DateTime.Parse()는 시스템의 로컬 문화권(CultureInfo)이나 시간대(TimeZone) 설정에 따라
오프셋 정보가 무시되거나 변형될 수 있어, 서버 기준(UTC)과 정확하게 비교하려면
UTC 시간대로 명확히 변환하는 과정이 필요합니다.

아래 안내드리는 방법을 참고해 주시면 감사하겠습니다.

// 방법 1: 시간대 정보를 반영해 바로 UTC로 변환
DateTime utcTime = DateTimeOffset.Parse(time).UtcDateTime;
// 방법 2: Parse 후 수동으로 UTC로 변환
string time = bro.GetReturnValuetoJSON()["utcTime"].ToString();
DateTime parsedDate = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse(time));