채팅 시스템 개요
PlayNANOO 채팅 시스템은 실시간 WebSocket 기반의 채팅 기능을 제공합니다. 이 문서에서는 채팅 시스템의 전체 구조와 사용 방법을 설명합니다.
시스템 구성
채팅 시스템은 3개의 핵심 클래스로 구성됩니다.
| 클래스 | 역할 |
|---|---|
| ChatManager | 싱글톤 매니저로, 채팅 서버 연결 및 API 호출을 관리합니다 |
| ChatClient | WebSocket 연결 및 메시지 송수신을 처리하는 코어 클래스입니다 |
| ChatModels | 데이터 모델과 이벤트 리스너 인터페이스를 정의합니다 |
필수 구현 안내
위 3개의 클래스는 필수 구현 클래스이며, 사용자의 프로젝트 구조에 맞게 자유롭게 변경할 수 있습니다.
필수 구현 요소:
IChatListener인터페이스의 모든 콜백 메서드 구현ChatClient.Service()메서드를 Update()에서 주기적으로 호출 (메시지 수신을 위해 필수)- WebSocket 연결을 위한 서버 목록 API 호출 (
PUT /chat/v20211101/server) - HMAC-SHA256 해시 인증 로직 구현
동작 흐름
1. ChatManager.Connect() 호출
↓
2. 서버 목록 API 요청 (PUT /chat/v20211101/server)
↓
3. 서버 목록 수신 후 랜덤 서버 선택
↓
4. ChatClient가 WebSocket 연결 수행
↓
5. 연결 성공 시 IChatListener.OnConnected() 호출
↓
6. 채널 구독 및 메시지 송수신
1단계: 리스너 구현
채팅 이벤트를 수신하려면 IChatListener 인터페이스를 구현해야 합니다.
public class MyChatHandler : MonoBehaviour, IChatListener
{
public void OnConnected()
{
// 서버 연결 성공
Debug.Log("채팅 서버에 연결되었습니다.");
}
public void OnDisconnected()
{
// 서버 연결 해제
Debug.Log("채팅 서버와 연결이 해제되었습니다.");
}
public void OnError(string code, string message)
{
// 오류 발생
Debug.LogError($"오류: [{code}] {message}");
}
public void OnChannels(ChatChannelInfo[] channels)
{
// 채널 목록 수신
foreach (var ch in channels)
{
Debug.Log($"채널: {ch.channel}, 접속자: {ch.count}명");
}
}
public void OnSubscribed(ChatUserInfo user)
{
// 사용자가 채널에 입장
Debug.Log($"{user.visitorName}님이 입장했습니다.");
}
public void OnUnSubscribed(ChatUserInfo user)
{
// 사용자가 채널에서 퇴장
Debug.Log($"{user.visitorName}님이 퇴장했습니다.");
}
public void OnPublicMessage(ChatUserInfo sender, string message)
{
// 공개 메시지 수신
Debug.Log($"[{sender.visitorName}]: {message}");
}
public void OnPrivateMessage(ChatUserInfo sender, string message)
{
// 귓속말 수신
Debug.Log($"[귓속말][{sender.visitorName}]: {message}");
}
public void OnNotifyMessage(ChatUserInfo sender, string message)
{
// 시스템 알림 수신
Debug.Log($"[시스템]: {message}");
}
public void OnPlayerOnline(ChatPlayerInfo[] players)
{
// 플레이어 온라인 상태 수신
foreach (var p in players)
{
string status = p.online == "Y" ? "온라인" : "오프라인";
Debug.Log($"{p.userUniqueId}: {status}");
}
}
}
2단계: 채팅 서버 연결
ChatManager.Instance.Connect()를 호출하여 채팅 서버에 연결합니다.
void Start()
{
// IChatListener를 구현한 객체를 전달
ChatManager.Instance.Connect(this);
}
연결이 성공하면 OnConnected() 콜백이 호출됩니다.
3단계: 채널 구독
연결 후 원하는 채널을 구독합니다.
public void OnConnected()
{
// 글로벌 채널 구독
ChatManager.Instance.Subscribe("global");
// 또는 특정 채널 구독
ChatManager.Instance.Subscribe("room_123");
}
4단계: 메시지 전송
공개 메시지 전송
채널의 모든 사용자에게 메시지를 전송합니다.
public void SendChatMessage(string text)
{
ChatManager.Instance.SendPublicMessage("global", text);
}
귓속말 전송
특정 사용자에게만 메시지를 전송합니다.
public void SendWhisper(string targetUserId, string text)
{
ChatManager.Instance.SendPrivateMessage(targetUserId, text);
}
5단계: 기타 기능
채널 목록 조회
ChatManager.Instance.GetChannels();
// 결과는 OnChannels() 콜백으로 수신
채널 구독 해제
ChatManager.Instance.Unsubscribe("global");
플레이어 온라인 상태 조회
string[] userIds = new string[] { "user_001", "user_002", "user_003" };
ChatManager.Instance.GetPlayersOnline(userIds);
// 결과는 OnPlayerOnline() 콜백으로 수신
연결 상태 확인
if (ChatManager.Instance.IsConnected())
{
Debug.Log("채팅 서버에 연결되어 있습니다.");
}
전체 사용 예제
using UnityEngine;
public class ChatExample : MonoBehaviour, IChatListener
{
void Start()
{
// 1. 채팅 서버 연결
ChatManager.Instance.Connect(this);
}
// 2. 연결 성공 시 채널 구독
public void OnConnected()
{
Debug.Log("연결 성공!");
ChatManager.Instance.Subscribe("global");
}
// 3. 채널 입장 알림
public void OnSubscribed(ChatUserInfo user)
{
Debug.Log($"{user.visitorName}님이 입장했습니다.");
}
// 4. 메시지 수신
public void OnPublicMessage(ChatUserInfo sender, string message)
{
Debug.Log($"[{sender.visitorName}]: {message}");
}
// 5. 메시지 전송 (UI 버튼에서 호출)
public void OnSendButtonClick()
{
ChatManager.Instance.SendPublicMessage("global", "안녕하세요!");
}
// 기타 콜백 구현
public void OnDisconnected() => Debug.Log("연결 해제됨");
public void OnError(string code, string message) => Debug.LogError($"[{code}] {message}");
public void OnChannels(ChatChannelInfo[] channels) { }
public void OnUnSubscribed(ChatUserInfo user) => Debug.Log($"{user.visitorName}님이 퇴장했습니다.");
public void OnPrivateMessage(ChatUserInfo sender, string message) => Debug.Log($"[귓속말] {message}");
public void OnNotifyMessage(ChatUserInfo sender, string message) => Debug.Log($"[알림] {message}");
public void OnPlayerOnline(ChatPlayerInfo[] players) { }
}
주의사항
Update에서 Service 호출: ChatManager의 Update()에서 ChatClient.Service()가 호출되어 WebSocket 콜백을 메인 스레드에서 처리합니다. ChatManager를 직접 수정하는 경우 이 부분을 유지해야 합니다.
싱글톤 패턴: ChatManager는 싱글톤으로 구현되어 있어
ChatManager.Instance로 접근합니다. 씬 전환 시에도 유지됩니다.연결 해제: 앱 종료 시 ChatManager.OnDestroy()에서 자동으로 연결이 해제됩니다.