네트워크 일시 끊김 이후 자동 재접속 이상 현상

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

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

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

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

현재 무료 요금제로 채팅 기능 테스트용 프로젝트를 구성하여
테스트 진행 중인데, 안드로이드 기기에서 잠시 네트워크가 연결 해제되고 복구되는 경우에는 자동 재접속이 정상적으로 처리되지 않는 듯하여 질문드립니다.
(Fallback으로 설정해둔 채널을 없는 상태입니다)

추가로 코드 문제일까 하여 구현 코드도 하단에 첨부하겠습니다.

에디터에서 인터넷을 잠시 연결 해제 후 다시 활성화 시 (정상)
(ChatClient 생성)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨
(네트워크 연결 해제)
OnLeaveChannel 호출됨: channelInfo = channel-0001 / korean / 1
(네트워크 재연결)
(약 15초 대기)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnError 호출됨: error = ALREADY_JOIN_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨

안드로이드 기기에서 인터넷을 잠시 연결 해제 후 다시 활성화 시 (비정상)
(ChatClient 생성)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨
(네트워크 연결 해제)
OnLeaveChannel 호출됨: channelInfo = channel-0001 / korean / 1
(네트워크 재연결)
(약 15초 대기)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnError 호출됨: error = ALREADY_JOIN_CHANNEL, param =
(무반응…)

에디터에서 장시간 백그라운드 → 재오픈 (정상)
(ChatClient 생성)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨
(백그라운드 전환 이후 재오픈)
OnLeaveChannel 호출됨: channelInfo = channel-0001 / korean / 1
(약 15초 대기)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnError 호출됨: error = ALREADY_JOIN_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨

안드로이드 기기에서 장시간 백그라운드 → 재오픈 (정상)
(ChatClient 생성)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨
(백그라운드 전환 이후 재오픈)
OnLeaveChannel 호출됨: channelInfo = channel-0001 / korean / 1
(약 15초 대기)
OnError 호출됨: error = DISABLED_CHANNEL, param =
OnError 호출됨: error = ALREADY_JOIN_CHANNEL, param =
OnJoinChannel 호출됨: channelInfo = channel-0001 / korean / 1
OnJoinChannelPlayer 호출됨

ChattingUI.cs

using System.Collections;
using System.Collections.Generic;
using BackEnd;
using BackndChat;
using TMPro;
using UnityEngine;

public class ChattingUI : MonoBehaviour, IChatClientListener
{
    private ChatClient ChatClient;
    private string targetChannelName = "korean";
    private string targetChannelGroup = "channel-0001";

    public TMP_Text text_Chat;
    public TMP_InputField input_Chat;
    private string chatLog = "";
    private ChannelInfo currentChannelInfo = null;

    public void Init()
    {
        ChatClient = new ChatClient(this, new ChatClientArguments
        {
            Avatar = "default",
            Metadata = new()
        });

        input_Chat.onSubmit.AddListener(OnSubmitChat);
    }

    void OnSubmitChat(string message)
    {
        if (currentChannelInfo == null)
        {
            Debug.Log("채널 정보가 없습니다.");
            return;
        }

        ChatClient.SendChatMessage(currentChannelInfo.ChannelGroup, currentChannelInfo.ChannelName, currentChannelInfo.ChannelNumber, message);
    }

    void Update() => ChatClient?.Update();

    void OnApplicationQuit() => ChatClient?.Dispose();

    public void OnJoinChannel(ChannelInfo channelInfo)
    {
        Debug.Log($"OnJoinChannel 호출됨: channelInfo = {channelInfo.ChannelGroup} / {channelInfo.ChannelName} / {channelInfo.ChannelNumber}");

        currentChannelInfo = channelInfo;

        string str = "";

        // 이전 메시지 확인
        foreach (var msg in channelInfo.Messages)
        {
            str += $"{msg.GamerName}: {msg.Message}\n";
        }

        chatLog = str;
        text_Chat.text = chatLog;
    }

    public void OnLeaveChannel(ChannelInfo channelInfo)
    {
        currentChannelInfo = null;
        Debug.Log($"OnLeaveChannel 호출됨: channelInfo = {channelInfo.ChannelGroup} / {channelInfo.ChannelName} / {channelInfo.ChannelNumber}");
    }

    public void OnJoinChannelPlayer(string channelGroup, string channelName, ulong channelNumber, PlayerInfo player)
    {
        if (channelName != targetChannelName)
        {
            return;
        }

        Debug.Log($"OnJoinChannelPlayer 호출됨");
    }

    public void OnLeaveChannelPlayer(string channelGroup, string channelName, ulong channelNumber, PlayerInfo player)
    {
        Debug.Log($"OnLeaveChannelPlayer 호출됨");
    }

    public void OnUpdatePlayerInfo(string channelGroup, string channelName, ulong channelNumber, PlayerInfo player)
    {
        Debug.Log($"OnUpdatePlayerInfo 호출됨");
    }

    public void OnChangeGamerName(string oldGamerName, string newGamerName)
    {
        Debug.Log($"OnChangeGamerName 호출됨");
    }

    public void OnChatMessage(MessageInfo messageInfo)
    {
        Debug.Log($"OnChatMessage 호출됨");

        chatLog += $"{messageInfo.GamerName}: {messageInfo.Message}\n";
        text_Chat.text = chatLog;
    }

    public void OnWhisperMessage(WhisperMessageInfo messageInfo)
    {
        Debug.Log($"OnWhisperMessage 호출됨");
    }

    public void OnTranslateMessage(List<MessageInfo> messages)
    {
        Debug.Log($"OnTranslateMessage 호출됨");
    }

    public void OnHideMessage(MessageInfo messageInfo)
    {
        Debug.Log($"OnHideMessage 호출됨");
    }

    public void OnDeleteMessage(MessageInfo messageInfo)
    {
        Debug.Log($"OnDeleteMessage 호출됨");
    }

    public void OnSuccess(SUCCESS_MESSAGE success, object param)
    {
        Debug.Log($"OnSuccess 호출됨: success = {success}, param = {param}");
    }

    public void OnError(ERROR_MESSAGE error, object param)
    {
        Debug.Log($"OnError 호출됨: error = {error}, param = {param}");

        if (error == ERROR_MESSAGE.DISABLED_CHANNEL)
        {
            ChatClient.SendJoinOpenChannel(targetChannelGroup, targetChannelName);
        }
    }
}

ChatManager.cs

using BackEnd;
using TMPro;
using UnityEngine;

public class ChatManager : MonoBehaviour
{
    public string loginId;
    public ChattingUI ChattingUI;
    public TMP_InputField input_Login;
    public CanvasGroup group;

    void Start()
    {
        // 뒤끝 초기화
        Backend.Initialize();

        input_Login.onSubmit.AddListener(OnSubmitLogin);
    }

    void OnSubmitLogin(string message)
    {
        group.alpha = 0;
        loginId = message;

        var result = Backend.BMember.CustomLogin(loginId, "PASSWORD");
        if (!result.IsSuccess())
        {
            Backend.BMember.CustomSignUp(loginId, "PASSWORD");
            // 닉네임 설정
            Backend.BMember.UpdateNickname(loginId);
        }

        ChattingUI.Init();
    }
}

안녕하세요 개발자님,
뒤끝 채팅 SDK는 네트워크 단절, 앱 비활성화, 백그라운드 전환 등으로 인한 채팅 서버 접속 종료 상황에서 사용자 편의를 위해 자동 재연결 기능을 제공하고 있습니다.
재연결 과정에서는 Exponential backoff 알고리즘을 적용하여 최대 2분 정도 소요될 수 있으며,
이는 잦은 접속 시도로 인한 불필요한 트래픽 증가와 서버 과부하를 방지하기 위함입니다.
이점을 참고하여 이용해 주시면 감사하겠습니다.

네 답변 감사합니다.
재연결 알고리즘으로 인해 최장 2분이 소요될 수 있는 점 인지하고 있습니다
하지만 현재 상황은 약 10분을 넘게 기다려도 별도의 Callback 함수가 실행되고 있지 않는 점입니다. 혹시 문제상황을 확인하는 데 필요한 추가적인 정보가 있으시다면 첨부해 드리도록 하겠습니다.

좋아요 1

추가 정보 확인 요청드립니다.
테스트를 진행하고 계신 안드로이드 기기와 안드로이드 버전 정보 확인 요청드립니다.

문제 발생 기기 정보 첨부해 드리겠습니다
기종1 : Galaxy S23 Ultra, 안드로이드 버전 : 15(API 35)
기종2 : Galaxy Wide6, 안드로이드 버전 : 14(API 34)

좋아요 1

확인 시 채팅 서버 재 연결까지는 문제 없이 이루어지는 것으로 확인되나, 채널 입장에 문제가 발생하고 있는 것으로 보입니다.
담당부서에서 현상 재현 및 수정을 진행할 예정에 있습니다, 이용에 불편을 드려 죄송합니다.

추가적으로 재연결 텀을 30초 이상으로 할 경우에도 문제가 발생 하는지,
그리고 대기 상태에서 콘솔 화면에 입장이 되어 있는 상태인지 확인하여 주시면 감사하겠습니다.

네 답변 감사합니다
잠시 네트워크 해제 및 재연결 테스트 진행 중 콘솔에서 확인한 입장 상태는 최초 로그인 이후 별도 변경 사항은 없었습니다(지속적으로 새로고침 하면서 확인)
재연결 텀을30초 이상으로 테스트했을 때의 경우는 정상적으로 재로그인이 처리된 것을 확인하였습니다 (콘솔에서 입장 상태를 확인 시 네트워크가 끊어지고 일정 시간(약 20초?) 이후에 인원 리스트에서 제외된 것을 확인하였습니다)

유추하기에는 잠시 네트워크가 끊기고 콘솔에서 인원 목록에서 사라지기 전에 다시 네트워크가 돌아오면 문제가 발생하는 게 아닐까 싶긴 합니다.

좋아요 1