서론
지난 글과 이어서 작성해본다.
지난 글에서, 앞으로의 방향성에 대해 언급했는데, 추가된 부분이나 빠진 부분을 첨삭하여 요약해보았다.
1. 사내 채팅 기능과 맞물리는지 여부 (1:1 문의 기능 관점의 채팅만 필요한 상황)
2. 현재 회사의 비즈니스 로직을 무난히 적용할 수 있는가 (+ 채팅 봇 파악)
3. 백엔드 관점에서의 api 활용
센드버드의 1:1 채팅 기능
센드버드에는 아래처럼, 오픈 채팅방과, 그룹 채팅방 밖에 없기 때문에, 1:1 채팅 기능이 없는건가?? 라고 생각했지만
1:1채팅은 그룹 채팅을 이용하여 구현할 수 있다.
생성 시 채팅 속성에 isDistinct를 true로 설정하고 userId를 만드는 사람을 포함해서 2명을 지정해서 입력해주면 된다.
다음은 내가 구현한 1:1 채팅 생성 api의 서비스 로직이다.
//채널 만들기(임시::관리자문의)
async createChannel(userId: string) {
const userIds = [userId, 'admin'];
try {
const channel = await this.sendbirdAPI.gcCreateChannel(this.API_TOKEN, { userIds, isDistinct: true });
console.log(channel)
return channel.channel;
} catch (error) {
throw new sendbird.HttpException('createChannel');
}
}
groupChannelApi의 생성자 중 채널을 생성해주는 gcCreateChannel의 파라미터 중 GcCreateChannelData에는 다음과 같은 속성들이 들어있고, docs에 각 속성에 대한 설명이 들어있다.
export declare class GcCreateChannelData {
'userIds': Array<string>;
'users'?: Array<SendBirdUser>;
'name'?: string;
'channelUrl'?: string;
'coverUrl'?: string;
'coverFile'?: HttpFile;
'customType'?: string;
'data'?: string;
'isDistinct'?: boolean;
'isPublic'?: boolean;
'isSuper'?: boolean;
'isEphemeral'?: boolean;
'accessCode'?: string;
'inviterId'?: string;
'strict'?: boolean;
'invitationStatus'?: any;
'hiddenStatus'?: any;
'operatorIds'?: Array<string>;
'blockSdkUserChannelJoin'?: boolean;
static readonly discriminator: string | undefined;
static readonly attributeTypeMap: Array<{
name: string;
baseName: string;
type: string;
format: string;
}>;
static getAttributeTypeMap(): {
name: string;
baseName: string;
type: string;
format: string;
}[];
constructor();
}
센드버드 도입 가능성
사내 클라이언트, 서버의 코드를 생각해봤을 때
PHP에도 JS로 되어있는 센드버드 SDK를 사용한다면 충분히 개발이 가능해보였다.
또한 채팅 로직이 메세지를 주고받는 소켓 서버에서, 각각의 웹 서버로 로깅, 메세지 전달과 같은 작업을 수행하기 때문에
소켓을 걷어내고 센드버드 서버를 사용하면서 채팅을 보낼 때 직접 클라이언트 서버에서, PHP 서버에 로깅 api를 fetch시키고
반대로 서비스 관리자인 PHP쪽 클라이언트에서 메세지를 보낼 때는 PHP 서버에 로깅 api를 적용시키면 될 것으로 보인다.
현재 서비스 웹의 버전과 센드버드 SDK에서 지원하는 next나 react버전이 일치하지 않아서 마이그레이션같은 작업을 수행해야 하는지는 검토중에 있다. 이건 체크하는 데로 포스팅을 따로 하도록 하겠다.
채팅봇
사내 채팅 봇은, 단순 DB에서 자동 응답에 대한 데이터를 기록해뒀다가, 유저의 토큰을 검증해 서비스의 사용자면 데이터를 가지고 view만 해 주는 것으로 알고 있다.
센드버드의 채팅 봇은, Open AI, Llama2, Bard를 지원하는 것으로 보였고(현재 OpenAI만 활성화 되어있는데, 결제여부에 따라 다른것인지, 현재 사용 불가인지는 파악이 되지 않는다.) 학습까지 가능한 것으로 파악이 되고 있다. 우리가 적용하기에는 차고 넘치는 서비스로 보여진다.
그래서 뭘 해야할까?
리액트에 대해 잘 모르지만, 토이 프로젝트 수준 정도의 웹 사이트를 노드와 리엑트를 사용해서 만들었고, 계속 만들어 나가는 중에 있기 때문에 간단한 UI Kit을 활용해서 센드버드 프로토타입을 만드는 것은 가능해보여서 제작해보았다.
SendBirdProvider는 동적으로 넣어주지 않으면 window is not defined 에러를 뱉어낸다. 아마 Next라서 그런 것 같다.
import React, { useEffect, useState } from "react";
import '@sendbird/uikit-react/dist/index.css';
import dynamic from "next/dynamic";
import { Channel, ChannelList, MessageSearch } from "@sendbird/uikit-react";
import GlobalStyle from "@/styles/globalStyle";
import SendbirdCustom from "@/styles/sendbirdCustom";
import Server500Alert from "@/components/sweetalert/500.alert";
import { initChannel } from "@/apis/sendbird";
const SendBirdProvider = dynamic(() => import("@sendbird/uikit-react/SendbirdProvider"), { ssr: false });
function SendbirdMain() {
const [currentChannelUrl, setCurrentChannelUrl] = useState('');
const [channelCnt, setChannelCnt] = useState(0);
const APP_ID = `${process.env.NEXT_PUBLIC_SENDBIRD_APP_ID}`;
const USER_ID = 'test1';
const initialize = async () => {
try {
await initChannel('test1');
} catch (error: any) {
console.error(error);
Server500Alert();
}
}
return (
<>
<div className="sendbird-app">
{/* <Navb /> */}
<SendBirdProvider appId={APP_ID} userId={USER_ID} theme="dark">
<>
<MessageSearch channelUrl={currentChannelUrl} />
<Channel channelUrl={currentChannelUrl} />
<ChannelList
onChannelSelect={(channel) => {
if (channel && channel.url) {
setCurrentChannelUrl(channel.url)
setChannelCnt(channelCnt + 1);
}
else if(channelCnt <= 1) {
initialize();
}
}}
/>
</>
</SendBirdProvider>
</div>
<GlobalStyle />
<SendbirdCustom />
</>
)
}
export default SendbirdMain;
여기서 init은, 입장 시 채널이 없을 때 자동으로 하나 생성해주는 api에 불과하다.
server500alert는 sweet-alert를 이용해서 커스텀한 에러 alert이다.
const initialize = async () => {
try {
await initChannel('test1');
} catch (error: any) {
console.error(error);
Server500Alert();
}
}
//service단 로직
async initChannel(userId: string) {
const channel = await this.createChannel(userId);
if(!channel) throw new sendbird.HttpException('initChannel::createChannel error');
const { channelUrl } = channel;
const dto:SendbirdTextMsgDto = {
message_type: "MESG",
user_id: "admin",
message: "안녕하세요? 무엇을 도와드릴까요?"
}
return await this.sendbirdMsgService.sendTextMsg(dto, channelUrl);
}
단순 이런식으로 UI Kit을 사용해도 되고, 커스텀해도 되는 것 같다.
회사에서, 단순 UI Kit을 사용하는 것이 아니라 회사 프론트 코드를 사용하여 개발한다면 방 생성, 메세지 보내기 등 관련된 모든 api를 사용할 것 같으나, 단순 UI Kit을 사용한다면 백엔드 쪽에서 처리할 것은 글쎄... 거의 없어 보였다.
기타:: 센드버드의 QnA AI
센드버드도 Open AI와 같은 채팅 봇을 가지고 있어 질문하면 대답은 잘 해준다.
하지만 Open AI를 사용할 때도 뱅뱅 돌때처럼 그럴 때가 많다.
특히 자사 코드를 물어봐도 SDK docs 수준에서의 답변만 해주는 것 같고 명확한 질문을 해도 참고 수준도 안될 때가 많다.
Todo List
센드버드를 도입한다면, 확실히 장단점을 파악해서 장점을 더 잘 활용하고 단점을 보완하는 측면에서 사용해야할 것 같다.
또한 도입한다면 보안 쪽이 어떻게 구현되어 있는지, FCM을 어떻게 사용할 수 있는지 알아봐야한다..
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!