728x90
1. 기존 코드
기존 통신코드는 아래와 같다.
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEditor.VersionControl;
using UnityEngine;
using UnityEngine.Networking;
using static System.Net.WebRequestMethods;
[System.Serializable]
public class ChatRequest
{
public string sender;
public string chatContent;
public string receiver;
public int chatDay;
}
[System.Serializable]
public class ChatResponse
{
public string sender;
public string chatContent;
}
[System.Serializable]
public class ChatListRequest
{
public string userName;
public string aiNpcName;
}
[System.Serializable]
public class ChatListResponse
{
public string resultCode;
public List<ChatListContent> message;
}
[System.Serializable]
public class ChatListContent
{
public string sender;
public string receiver;
public string chatContent;
}
public class ChatHttpTestBJH : MonoBehaviour
{
public TMP_Text npcName;
public TMP_Text content;
public void TryChat(string text)
{
string url = "ngrox 서버 url/api/v1/chat/send";
CreateJson(url, text);
}
public void ShowChatList()
{
string url = "ngrox 서버 url/api/v1/chat/list";
string userName = "지환이";
string aiNpcName = "김쿵야";
CreateJson(url, userName, aiNpcName);
}
public void CreateJson(string url, string text)
{
string u = url;
ChatRequest chatRequest = new ChatRequest();
chatRequest.sender = "지환이";
chatRequest.chatContent = text;
chatRequest.receiver = "김쿵야";
chatRequest.chatDay = 1;
string createdJsonData = JsonUtility.ToJson(chatRequest);
OnGetRequest(RequestType.POST, u, createdJsonData);
}
public void CreateJson(string url, string userName, string aiNpcName)
{
string u = url;
ChatListRequest request = new ChatListRequest();
request.userName = userName;
request.aiNpcName = aiNpcName;
string createdJsonData = JsonUtility.ToJson(request);
print(createdJsonData);
OnGetRequest(RequestType.POST, u, createdJsonData);
}
public void OnGetRequest(RequestType type, string url, string s)
{
HttpRequester requester = new HttpRequester();
requester.Settting(type, url);
requester.body = s;
requester.complete = Complete;
HttpManagerBJH.instance.SendRequest(requester);
}
public void Complete(DownloadHandler result)
{
ChatResponse chatResponse = new ChatResponse();
chatResponse = JsonUtility.FromJson<ChatResponse>(result.text);
print(chatResponse.sender + " " + chatResponse.chatContent);
if(chatResponse.chatContent != null)
{
print("complete함수 if문 실행");
npcName.text = chatResponse.sender;
StartCoroutine(Typing(chatResponse.chatContent));
//text.text = chatResponse.chatContent;
}
}
IEnumerator Typing(string t)
{
yield return new WaitForSeconds(0.1f);
for (int i = 0; i < t.Length; i++)
{
content.text = t.Substring(0, i);
yield return new WaitForSeconds(0.01f);
}
}
}
위처럼 작성했더니 문제점이 있었다.
채팅에 대한 답변을 받는 객체와 채팅 리스트를 받는 객체가 다르기 때문에 통신 종류에 따라 다른 클래스의 객체가 선언되어야하는데, 이를 어떻게 해결하지? 였다.
이때 생각해본 것이 전략패턴이다.
통신의 전략(즉, 채팅을 위한 통신인지 채팅 리스트를 출력하기 위한 통신인지)만 수정하여 통신을 진행할 수 있도록 코드를 리팩토링 했다.
2. 전략패턴을 적용한 코드
// Json을 만들기위한 class는 동일한 코드이므로 생략
// TryChat() 생성자에 들어갈 메서드 인자를 간편하게 담기 위해서
// 구조체 생성
public struct StrTryChat
{
public string url;
public string sender, chatContent, receiver;
public int chatDay;
}
// 인터페이스
public interface ConnectionStratege
{
public void CreateJson();
public void OnGetRequest(string jsonData);
public void Complete(DownloadHandler result);
}
// TryChat : 채팅을 하기위한 통신
public class TryChat : ConnectionStratege
{
string url;
string sender, chatContent, receiver;
int chatDay;
// 구조체를 매개변수로 받음
public TryChat(StrTryChat str)
{
this.url = str.url;
this.sender = str.sender;
this.chatContent = str.chatContent;
this.receiver = str.receiver;
this.chatDay = str.chatDay;
CreateJson();
}
// Json data 생성
public void CreateJson()
{
ChatRequest request = new ChatRequest();
request.sender = this.sender;
request.chatContent = this.chatContent;
request.receiver = this.receiver;
request.chatDay = this.chatDay;
string jsonData = JsonUtility.ToJson(request);
OnGetRequest(jsonData);
}
// 통신을 위한 Request 생성
public void OnGetRequest(string jsonData)
{
HttpRequester requester = new HttpRequester();
requester.Settting(RequestType.POST, this.url);
requester.body = jsonData;
requester.complete = Complete;
// 통신 시작
HttpManagerBJH.instance.SendRequest(requester);
}
// 통신이 완료되면, 실행되는 메서드
public void Complete(DownloadHandler result)
{
ChatResponse response = new ChatResponse();
response = JsonUtility.FromJson<ChatResponse>(result.text);
if (response.chatContent != null)
{
ChatManager.instance.npcText.text = response.chatContent;
ChatManager.instance.EmitChat();
}
}
}
public class ShowChatList : ConnectionStratege
{
string url, userName, aiNpcName;
public ShowChatList(string url, string userName, string aiNpcName)
{
this.url = url;
this.userName = userName;
this.aiNpcName = aiNpcName;
CreateJson();
}
public void CreateJson()
{
ChatListRequest request = new ChatListRequest();
request.userName = userName;
request.aiNpcName = aiNpcName;
string createdJsonData = JsonUtility.ToJson(request);
OnGetRequest(createdJsonData);
}
public void OnGetRequest(string jsonData)
{
HttpRequester requester = new HttpRequester();
requester.Settting(RequestType.POST, this.url);
requester.body = jsonData;
requester.complete = Complete;
HttpManagerBJH.instance.SendRequest(requester);
}
public void Complete(DownloadHandler result)
{
ChatListResponse response = new ChatListResponse();
response = JsonUtility.FromJson<ChatListResponse>(result.text);
if (response.resultCode == "SUCCESS")
{
UI.instance.chatListContent = response.message;
}
}
}
토대를 완성했으니, 해당 객체를 선언하여 통신을 시작하는 코드를 작성해보겠다.
아래는 채팅을 시도한다.
// Chat
// 전송 버튼
public TMP_Text text;
public TMP_Text npcText;
public void OnclickSend(TMP_Text text)
{
// 추후 수정 될 부분
string url = "서버와 통신하기위한 url";
string sender = "Dongsik";
string chatContent = text.text;
string receiver = "KoongYa";
int chatDay = 1;
// 구조체 사용
StrTryChat str;
str.url = url;
str.sender = sender;
str.chatContent = chatContent;
str.receiver = receiver;
str.chatDay = chatDay;
// 생성자 실행 후 바로 통신 시작
TryChat tryChat = new TryChat(str);
}
3. 결과
결과는 잘 작동한다.. 결과물을 캡쳐해서 올리고 싶었는데, 지금 서버쪽에서 채팅 코드를 수정한다며 서버를 내린 상태다.. 그래서 생각이 난다면 다시 들려서 실행 결과 이미지를 가져오도록 하겠다.
4. 고민
결제 플랫폼에 따른 전략패턴을 예제삼아 코드로 몇 번 작성해봤다. 실제로 적용한 것이 아니라 예제 코드를 손코딩 해본 경험이 전부라 내가 생각해낸 이 방법이 정말 '전략패턴'이라고 부를 수 있을지는 모르겠다... 내가 이것을 전략패턴이라 칭한 이유는
1. 통신 전략이 분리됨
2. 분리된 전략이 같은 인터페이스를 구현함
3. 공통된 로직과 전략별 로직이 잘 연결되어 이행됨
위 세가지 이유였다.