React Native를 사용하여 애플리케이션에서 채팅 기능을 구축하는 방법[섹션 2]

글의 두 번째 부분인'React Native를 어떻게 사용해 앱에서 채팅 기능을 구축하는가'에서 Sendbird 채팅 API와 SDK 기반의 채팅 앱을 개발하는 관건적인 절차를 소개한다.
Sendbird 채팅 SDK를 사용하여 간단한 React 네이티브 채팅 프로그램을 구축하기 전에 그 기능에 대해 개괄적으로 설명합니다.소프트웨어에 대해 다음과 같은 기능과 기능을 개발합니다.

  • 등록/로그인 기능 - 사용자가 애플리케이션에 액세스할 수 있도록 합니다.

  • 송신 및 수신 기능을 사용하여 송신 및 수신 채널 목록을 입력할 수 있습니다.

  • 채팅 기능 - 사용자가 실시간으로 문자를 입력하고 메시지를 보내고 받을 수 있도록 합니다.
  • 이제 Sendbird의 채팅 SDK에 대해 더 깊이 있게 알아보겠습니다. 이 해결 방안을 통해 실시간 채팅을 클라이언트 응용 프로그램에 효과적으로 통합할 수 있습니다.
    Sendbird의 도움을 받아 채팅을 쉽게 초기화하고 설정하며 구축할 수 있습니다.서버에서, Sendbird는 응용 프로그램 내의 채팅에 신뢰할 수 있는 infra 관리 서비스를 제공할 수 있도록 보장합니다.
    Sendbird에는 클라이언트 API(React 기본 API 포함)와 플랫폼 API 두 가지 기본 API가 있습니다.본고는 플랫폼 API를 소개하지 않습니다. 백엔드나 서버 응용 프로그램(서버에서 서버로 통신)에서 Sendbird 백엔드와 통신할 수 있습니다. 이벤트(예를 들어 알림 전송은 전형적인 장면)에 따라 Rails, Meteor 또는 노드 응용 프로그램에서 터치하기를 원한다면 매우 편리합니다.본 연구에서 우리는 Sendbird JavaScript SDK를 이용하여 간단한 채팅 응용 프로그램을 구축하는 데 중점을 둘 것이다.

    Sendbird 채팅 SDK 설치 및 구성


    1단계: 새 Sendbird 응용 프로그램 만들기


    Sendbird 콘솔에서 새 응용 프로그램을 만드는 것은 매우 간단합니다.먼저 Sendbird 계정에 로그인한 다음 대시보드로 이동하여 오른쪽 상단에 있는Create+를 클릭합니다.그런 다음 고유한 애플리케이션 자격 증명이 생성됩니다.

    이러한 자격 증명을 사용하면 채팅 SDK 설치에 대해 자세히 알 수 있습니다.

    2단계: Sendbird 채팅 SDK 설치


    외부 라이브러리나 SDK를 잘 사용한다면 채팅 SDK를 설치하는 것은 매우 간단합니다.명령줄에 아래 명령을 입력하면 패키지 관리자 npm 또는 Thread를 사용하여 채팅 SDK를 설치할 수 있습니다.
    NPM의 경우(참고: NPM을 사용하여 채팅 SDK를 설치하려면 먼저 시스템에 Node.js를 설치해야 함): $ npm install sendbird (request to npm server)사선:$ yarn add sendbird

    3단계: Sendbird 채팅 SDK 초기화


    채팅 SDK 기능을 사용하려면 먼저 저희 프로그램에서 Sendbird 실례를 시작해야만 Sendbird 서버를 사용하여 사용자 인증을 할 수 있습니다.
    Sendbird 인스턴스를 초기화하려면 대시보드의 Sendbird 응용 프로그램의 App ID를 new Sendbird() 메서드의 매개 변수로 전달합니다.새 SendBird()는 클라이언트 응용 프로그램에서 한 번 호출되어야 합니다.일반적으로 초기화는 사용자 로그인 보기에서 이루어진다.var sb = new SendBird({appId: APP_ID});

    4단계: Sendbird 서버에 연결


    새 SendBird()를 사용하여 초기화한 후 응용 프로그램은 항상 SendBird 서버에 연결해야 모든 방법을 호출할 수 있습니다.Sendbird 서버에 사용자를 연결하는 방법에는 고유한 사용자 ID를 사용하거나 액세스 토큰과 함께 사용하는 두 가지가 있습니다.
    사용자의 고유한 사용자 ID를 사용하여 Sendbird 서버에 사용자를 연결합니다.sb.connect(USER_ID, function(user, error) {
    if (error) {
    // Handle error.
    }
    채팅 플랫폼 API를 사용하면 사용자와 자신의 방문 영패를 만들거나 기존 사용자에게 방문 영패를 수여할 수 있습니다.일단 방문 영패를 보내면 사용자는 sb에서 방문 영패를 제공해야 한다.로그인에 사용되는 연결 () 방법입니다.
    사용자 ID와 액세스 토큰 ID의 조합을 사용하여 Sendbird 서버에 사용자를 연결합니다.sb.connect(USER_ID, ACCESS_TOKEN, function(user, error) {
    if (error) {
    // Handle error.
    }
    Sendbird 채팅 SDK를 설치하고 설정하며 저희 프로그램을 Sendbird 서버에 연결하면 기본적인 채팅 기능을 사용할 수 있습니다.

    Sendbird를 사용하여 채팅 애플리케이션 기능 구축


    등록/로그인 기능 개발


    사용자가 애플리케이션에 액세스할 수 있도록 하는 등록/로그인 기능에 대해 살펴보겠습니다.프로젝트에서 고유한 사용자 ID를 사용하여 인증을 사용합니다.
    인증에 대해 서버에 사용자 데이터 연결을 요청합니다.그리고 서버는 연결 요청에 따라 데이터베이스를 조회해서 일치하는지 확인합니다.일치하는 사용자 ID를 찾을 수 없으면 서버에서 사용자 ID를 사용하여 새 사용자 계정을 생성합니다. 기존 사용자 ID를 찾으면 직접 로그인할 수 있습니다.따라서 Sendbird SDK는 추가 요청에 대해 사용자가 계정에서 로그아웃할 때까지 로그인할 필요가 없습니다.우리의 예제 채팅 애플리케이션에서 어떻게 구현되는지 살펴보십시오.
    import React, { useState } from 'react';
    import { View, StyleSheet } from 'react-native';
    import { Input, Button } from 'react-native-elements';
    import SendBird from 'sendbird';
    import AsyncStorage from '@react-native-async-storage/async-storage';
    import { LoginSendBirdProps } from '../../navigation/types';
    import { SENDBIRD_API, USER_DATA } from '../consts';
    import { useDispatch } from 'react-redux';
    import { userLogin } from '../../store/actions';
    
    const LoginSendBird = ({ navigation }: LoginSendBirdProps) => {
      const [userId, setUserId] = useState('');
      const [nickname, setNickname] = useState('');
      const [error, setError] = useState({
        code: 0,
        message: '',
      });
      const dispatch = useDispatch();
    
      const onButtonPress = () => {
        const sb = new SendBird({ appId: SENDBIRD_API });
        sb.connect(userId, (user, err) => {
          if (err) {
            setError(err);
          } else {
            sb.updateCurrentUserInfo(nickname, '', async (user, err) => {
              if (err) {
                setError(err);
              } else {
                dispatch(userLogin({ nickname, userId }));
                await AsyncStorage.setItem(
                  USER_DATA,
                  JSON.stringify({ userId, nickname })
                );
                setUserId('');
                setNickname('');
                setError({ code: 0, message: '' });
              }
            });
          }
        });
      };
    
      return (
        <View style={styles.container}>
          <View style={styles.box}>
            <Input
              label="User ID"
              value={userId}
              labelStyle={{ color: '#000' }}
              onChangeText={setUserId}
              errorMessage={error.message}
              autoCapitalize="none"
            />
          </View>
          <View style={styles.box}>
            <Input
              label="Nickname"
              value={nickname}
              labelStyle={styles.input}
              onChangeText={setNickname}
              errorMessage={error.message}
              autoCapitalize="none"
            />
          </View>
          <View style={styles.box}>
            <Button
              buttonStyle={styles.button}
              title="Connect"
              onPress={onButtonPress}
            />
          </View>
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: {
        backgroundColor: '#fff',
        flex: 1,
        justifyContent: 'center',
        paddingHorizontal: 20,
      },
      box: {
        marginTop: 10,
      },
      button: { backgroundColor: '#2096f3' },
      input: { color: '#000' },
    });
    
    export default LoginSendBird;
    
    이 ID는 Sendbird 응용 프로그램에서 다른 응용 프로그램(예를 들어 서비스의 흩어진 전자 우편 주소나 전화번호)과 구분할 수 있도록 유일해야 합니다.

    채널 접속 및 채널 목록 기능 개발


    Sendbird의 SDK 및 API는

  • 채널을 열어 경련을 일으키는 공공 채팅누구든지 허락 없이 대화에 참여하고 참여할 수 있다.

  • 그룹 채널 - 제한된 수의 사용자 간에 밀접한 상호작용을 할 수 있는 채팅을 허용한다.모든 사용자가 초대하지 않아도 공공 그룹 채널에 가입할 수 있다.만약 사용자가 원한다면, 그들은 이 채널에 자유롭게 들어갈 수 있다.한편, 개인 그룹 채널은 이미 채팅방의 구성원인 다른 사용자의 초대를 통해 채팅에 가입할 수 있다.
  • 메시지를 수신하고 발송하기 시작하려면 사용자는 반드시 개방 채널에 들어가야 한다.사용자는 한 번에 최대 10개의 열린 채널을 입력할 수 있으며, 이 채널들은 현재 연결에서만 유효합니다.
    기본적으로 그룹 채널은 1~100명의 구성원으로 구성될 수 있습니다.요청마다 기본 구성원 수를 늘릴 수 있습니다.사용자는 자신이 속한 채널의 목록을 보고 처리할 수 있습니다.
    다음은 이 기능이 우리의 예시 채팅 응용 프로그램에서 작동하는 원리이다.
    import React, { useState, useCallback, useEffect } from 'react';
    import { FlatList, View, RefreshControl, StyleSheet } from 'react-native';
    import { ListItem, Avatar, Button } from 'react-native-elements';
    import AsyncStorage from '@react-native-async-storage/async-storage';
    import { useDispatch } from 'react-redux';
    import axios from 'axios';
    import SendBird from 'sendbird';
    import { MASTER_API_TOKEN, SENDBIRD_API, USER_DATA } from '../consts';
    import { MenuSendBirdProps } from '../../navigation/types';
    import { userLogout } from '../../store/actions';
    
    type SendBirdUser = {
      created_at: number;
      discovery_keys: [];
      has_ever_logged_in: boolean;
      is_active: boolean;
      is_hide_me_from_friends: boolean;
      is_online: boolean;
      last_seen_at: number;
      metadata: Object;
      nickname: string;
      phone_number: string;
      preferred_languages: [];
      profile_url: string;
      require_auth_for_profile_image: boolean;
      user_id: string;
    };
    
    const MenuScene = (props: MenuSendBirdProps) => {
      const [users, setUsers] = useState([]);
      const [isRefreshing, setRefreshing] = useState(false);
      const dispatch = useDispatch();
    
      const getData = useCallback(async () => {
        try {
          setRefreshing(true);
          const response = await axios.get(
            `https://api-${SENDBIRD_API}.sendbird.com/v3/users`,
            {
              headers: {
                'Content-Type': 'application/json; charset=utf8',
                'Api-Token': MASTER_API_TOKEN,
              },
            }
          );
          setUsers(response.data.users);
          setRefreshing(false);
        } catch (error) {
          setRefreshing(false);
          console.error(error);
        }
      }, [users]);
    
      useEffect(() => {
        props.navigation.setOptions({
          title: 'Chat List',
          headerStyle: {
            backgroundColor: '#a5a8b3',
          },
          headerTintColor: '#454851',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        });
        getData();
      }, []);
    
      const logout = async () => {
        await AsyncStorage.removeItem(USER_DATA);
        dispatch(userLogout());
        // console.log(await AsyncStorage.getItem(USER_DATA));
        // console.log(store.getState());
      };
    
      const startChat = (receiverId: string) => {
        const sb = SendBird.getInstance();
    
        sb.GroupChannel.createChannelWithUserIds(
          [receiverId],
          true,
          (createdChannel, error) => {
            if (error) {
              console.error(error);
            } else {
              props.navigation.navigate('ChatSendBird', {
                channel: createdChannel,
              });
            }
          }
        );
      };
    
      const renderItem = ({ item }: { item: SendBirdUser }) => (
        <ListItem
          key={item.user_id}
          bottomDivider
          onPress={() => startChat(item.user_id)}
        >
          <Avatar rounded source={require('../images/user.png')} />
          <ListItem.Content>
            <ListItem.Title>
              {item.nickname}
              <ListItem.Title style={styles.listItemTitle}>
                #{item.user_id}
              </ListItem.Title>
            </ListItem.Title>
            <ListItem.Subtitle>
              {item.is_online ? (
                <ListItem.Title style={styles.listItemTitleOnline}>
                  Online
                </ListItem.Title>
              ) : (
                <ListItem.Title style={styles.listItemTitleOffline}>
                  Offline
                </ListItem.Title>
              )}
            </ListItem.Subtitle>
          </ListItem.Content>
        </ListItem>
      );
    
      return (
        <View style={styles.container}>
          <FlatList
            style={styles.flatListStyle}
            contentContainerStyle={styles.flatListContentStyle}
            data={users}
            renderItem={renderItem}
            refreshControl={
              <RefreshControl
                refreshing={isRefreshing}
                onRefresh={() => getData()}
              />
            }
            keyExtractor={(item, index) => `${item.created_at} ${item.nickname}`}
          />
          <Button
            buttonStyle={styles.button}
            title="Logout from SendBird"
            onPress={logout}
          />
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: { flex: 1, backgroundColor: '#fff', paddingHorizontal: 20 },
      flatListStyle: { flex: 1 },
      flatListContentStyle: { flexGrow: 1 },
      listItemContent: { flexDirection: 'row', justifyContent: 'space-between' },
      listItemTitle: { color: '#0000f0', fontSize: 14 },
      listItemTitleOnline: { color: 'green', fontSize: 14 },
      listItemTitleOffline: { color: 'red', fontSize: 14 },
      button: {
        marginBottom: 40,
      },
    });
    
    export default MenuScene;
    

    채팅 기능


    마지막으로 우리의 첫 번째 메시지를 보냅니다.채팅 기능을 사용하면 사용자가 들어오는 채팅방에서 실시간으로 메시지를 보내고 받을 수 있다.세 가지 유형이 있습니다. 사용자 메시지입니다. 이것은 순수한 텍스트입니다.파일 메시지는 바이너리 파일(예: 이미지 또는 PDF)입니다.대시보드나 채팅 플랫폼 API를 통해 전송되는 일반 텍스트라는 관리 메시지도 있습니다.
    첫 번째 단계에서는 채팅 UI 구성 요소를 만들어야 합니다.이를 위해 우리는 react-native-gifted-chat을 사용했다. 이것은 확장 가능한 소스 라이브러리로 대량의 맞춤형 구성 요소를 포함하고 채팅 UI를 구축할 때 많은 시간과 개발 작업을 절약할 수 있다.
    그리고 우리는 들어오는 채팅방에서 실시간으로 메시지를 보낼 수 있다.채팅 애플리케이션의 예제를 살펴보십시오.
    import React, { useState, useEffect, useReducer } from 'react';
    import { useSelector } from 'react-redux';
    import { GiftedChat } from 'react-native-gifted-chat';
    import SendBird from 'sendbird';
    import { ChatSendBirdProps } from '../../navigation/types';
    import { chatReducer } from '../../store/chatReducer';
    import { withAppContext } from '../../store/context';
    import { AppState } from 'react-native';
    
    const ChatScene = (props: ChatSendBirdProps) => {
      const { navigation, route } = props;
      const { channel } = route.params;
    
      const sendbird = SendBird.getInstance();
    
      const user = useSelector((state: any) => state.user);
    
      const [query, setQuery] = useState(null);
    
      const [state, dispatch] = useReducer(chatReducer, {
        channel,
        messages: [],
        messageMap: {}, // redId => boolean
        loading: false,
        input: '',
        empty: '',
        error: '',
      });
    
      // on state change
      useEffect(() => {
        props.navigation.setOptions({
          // @ts-ignore
          title: channel.members[0].nickname,
          headerStyle: {
            backgroundColor: '#a5a8b3',
          },
          headerTintColor: '#454851',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        });
        sendbird.addConnectionHandler('chat', connectionHandler);
        sendbird.addChannelHandler('chat', channelHandler);
        AppState.addEventListener('change', handleStateChange);
        if (!sendbird.currentUser) {
          sendbird.connect(user.userId, (err, _) => {
            if (!err) {
              refresh();
              console.log('refreshed');
            } else {
              console.log('refresh error ', err);
              dispatch({
                type: 'error',
                payload: {
                  error: 'Connection failed. Please check the network status.',
                },
              });
            }
          });
        } else {
          refresh();
        }
    
        return () => {
          sendbird.removeConnectionHandler('chat');
          sendbird.removeChannelHandler('chat');
          AppState.removeEventListener('change', handleStateChange);
        };
      }, []);
    
      /// on query refresh
      useEffect(() => {
        if (query) next();
      }, [query]);
    
      /// on connection event
      const connectionHandler = new sendbird.ConnectionHandler();
      connectionHandler.onReconnectStarted = () => {
        dispatch({
          type: 'error',
          payload: {
            error: 'Connecting..',
          },
        });
      };
      connectionHandler.onReconnectSucceeded = () => {
        dispatch({
          type: 'error',
          payload: {
            error: '',
          },
        });
        refresh();
      };
      connectionHandler.onReconnectFailed = () => {
        dispatch({
          type: 'error',
          payload: {
            error: 'Connection failed. Please check the network status.',
          },
        });
      };
    
      /// on channel event
      const channelHandler = new sendbird.ChannelHandler();
      channelHandler.onMessageReceived = (targetChannel, message) => {
        if (targetChannel.url === channel.url) {
          dispatch({ type: 'receive-message', payload: { message: message } });
        }
      };
      channelHandler.onMessageUpdated = (targetChannel, message) => {
        if (targetChannel.url === channel.url) {
          dispatch({ type: 'update-message', payload: { message } });
        }
      };
      channelHandler.onMessageDeleted = (targetChannel, messageId) => {
        if (targetChannel.url === channel.url) {
          dispatch({ type: 'delete-message', payload: { messageId } });
        }
      };
    
      const handleStateChange = (newState) => {
        if (newState === 'active') {
          sendbird.setForegroundState();
        } else {
          sendbird.setBackgroundState();
        }
      };
    
      const refresh = () => {
        channel.markAsRead();
        setQuery(channel.createPreviousMessageListQuery());
        dispatch({ type: 'refresh' });
        console.log('refreshed');
      };
    
      const next = () => {
        if (query.hasMore) {
          dispatch({ type: 'error', payload: { error: '' } });
          query.limit = 50;
          query.reverse = true;
          query.load((fetchedMessages, err) => {
            if (!err) {
              console.log('loadmore');
              dispatch({
                type: 'fetch-messages',
                payload: { messages: fetchedMessages },
              });
            } else {
              console.log('fetch error', err);
              dispatch({
                type: 'error',
                payload: { error: 'Failed to get the messages.' },
              });
            }
          });
        }
      };
    
      const sendUserMessage = () => {
        if (state.input.length > 0) {
          const params = new sendbird.UserMessageParams();
          params.message = state.input;
    
          const pendingMessage = channel.sendUserMessage(params, (message, err) => {
            if (!err) {
              dispatch({ type: 'send-message', payload: { message } });
            } else {
              setTimeout(() => {
                dispatch({
                  type: 'error',
                  payload: { error: 'Failed to send a message.' },
                });
                dispatch({
                  type: 'delete-message',
                  payload: { reqId: pendingMessage.reqId },
                });
              }, 500);
            }
          });
          dispatch({
            type: 'send-message',
            payload: { message: pendingMessage, clearInput: true },
          });
        }
      };
    
      return (
        <GiftedChat
          messages={state.messages}
          onSend={sendUserMessage}
          text={state.input}
          renderUsernameOnMessage
          onInputTextChanged={(content) => {
            if (content.length > 0) {
              channel.startTyping();
            } else {
              channel.endTyping();
            }
            dispatch({ type: 'typing', payload: { input: content } });
          }}
          user={{ _id: user.userId, name: user.nickname }}
        />
      );
    };
    
    export default withAppContext(ChatScene);
    
    메시지를 저장하고 처리하며 여러 화면에서 공유 데이터를 관리하기 위해 Redux 라이브러리를 사용합니다.다음은 Reducer(Redux state holder)의 몇 줄 코드입니다.
    const initialState = {
    }
    
    export const chatReducer = (state = initialState, action) => {
        switch (action.type) {
            case 'refresh': {
                return {
                    ...state,
                    messageMap: {},
                    messages: [],
                    loading: false,
                    error: null
                };
            }
            case 'fetch-messages': {
                const { messages } = action.payload || {};
    
                const distinctMessages1 = messages.filter(message => !state.messageMap[message.reqId]);
                const distinctMessages = distinctMessages1.map((chatMessage) => {
                    let gcm = {
                        _id: chatMessage.messageId,
                        text: chatMessage.message,
                        createdAt: chatMessage.createdAt,
                        user: {
                            _id: chatMessage?._sender?.userId,
                            name: `${chatMessage._sender?.nickname}#${chatMessage._sender?.userId}`,
                        }
                    };
                    return gcm;
                });
                const mergedMessages = [...state.messages, ...distinctMessages];
                for (let i = 0; i < mergedMessages.length - 1; i++) {
                    mergedMessages[i].hasSameSenderAbove =
                        mergedMessages[i]._sender &&
                        mergedMessages[i + 1]._sender &&
                        mergedMessages[i]._sender.userId === mergedMessages[i + 1]._sender.userId;
                }
    
                const messageMap = {};
                for (let i in distinctMessages) {
                    const message = distinctMessages[i];
                    messageMap[message.reqId] = true;
                }
                return {
                    ...state,
                    messages: mergedMessages,
                    messageMap,
                    empty: mergedMessages.length === 0 ? 'Start conversation.' : ''
                };
            }
            case 'send-message':
            case 'receive-message':
            case 'update-message': {
                const { message, clearInput } = action.payload || {};
                if (!state.messageMap[message.reqId]) {
                    if (state.messages.length > 0) {
                        message.hasSameSenderAbove =
                            message._sender && state.messages[0]._sender && message._sender.userId === state.messages[0]._sender.userId;
                    }
                    return {
                        ...state,
                        messages: [message, ...state.messages],
                        messageMap: { ...state.messageMap, [message.reqId]: true },
                        input: clearInput ? '' : state.input,
                        empty: ''
                    };
                } else {
                    for (let i in state.messages) {
                        if (state.messages[i].reqId === message.reqId) {
                            const updatedMessages = [...state.messages];
                            message.hasSameSenderAbove = updatedMessages[i].hasSameSenderAbove;
                            const messageCopy = {
                                _id: message.messageId,
                                text: message.message,
                                createdAt: message.createdAt,
                                user: {
                                    _id: message?._sender?.userId,
                                    name: `${message._sender?.nickname}#${message._sender?.userId}`,
                                }
                            };
                            updatedMessages[i] = messageCopy;
                            return {
                                ...state,
                                input: clearInput ? '' : state.input,
                                messages: updatedMessages
                            };
                        }
                    }
                }
                break;
            }
            case 'delete-message': {
                const { messageId, reqId } = action.payload || {};
                for (let i in state.messages) {
                    if (state.messages[i].messageId === messageId || state.messages[i].reqId === reqId) {
                        const updatedMessages = state.messages.filter(m => m.reqId !== reqId && m.messageId !== messageId);
                        for (let i = 0; i < updatedMessages.length - 1; i++) {
                            updatedMessages[i].hasSameSenderAbove =
                                updatedMessages[i]._sender &&
                                updatedMessages[i + 1]._sender &&
                                updatedMessages[i]._sender.userId === updatedMessages[i + 1]._sender.userId;
                        }
                        return {
                            ...state,
                            messages: updatedMessages
                        };
                    }
                }
                break;
            }
            case 'typing': {
                const { input } = action.payload || {};
                return { ...state, input };
            }
            case 'start-loading': {
                return { ...state, loading: true, error: '' };
            }
            case 'end-loading': {
                const { error } = action.payload || {};
                return { ...state, loading: false, error };
            }
            case 'error': {
                const { error } = action.payload || {};
                return { ...state, error };
            }
        }
        return state;
    };
    

    Twilio와 Sendbird: 주요 기능 비교


    지금까지 우리는 Twilio와 Sendbird 두 개의 실시간 채팅과 메시지 플랫폼을 이용하여 React 본기 채팅 응용 프로그램의 예시를 구축하는 모든 주요 절차를 마쳤다.채팅 기능을 설정하고 구축한 다음 클라이언트 웹이나 모바일 응용 프로그램에 통합하는 데 필요한 작업량을 최소화할 수 있다.그러나 어떤 해결 방안이 당신의 업무 수요를 더욱 잘 만족시킬 수 있는지 설명하기 위해서, 우리는 관건적인 기능을 통해 Twilio와 Sendbird를 비교하여 더욱 좋은 노출률을 얻도록 합니다.

    그렇다면 채팅 기능을 구축하고 실현하는 가장 좋은 대안은 무엇일까?
    Twilio는 플랫폼 즉 서비스(PaaS) 모델 원칙을 바탕으로 하는 선도적인 클라우드 통신 플랫폼이다.Twilio는 소프트웨어 기반 플랫폼을 제공하지만 다른 플랫폼처럼 앱 내 채팅 앱에 들어가지 않는다.그것도 개발자의 플랫폼으로 여겨진다.따라서 영업사원이나 비개발자가 사용할 수 없다.이 공급자는 주로 프로그래밍 가능한 채팅 API를 대상으로 사용자가 즉시 전화를 걸고 받거나 문자 메시지를 보내고 받을 수 있도록 한다.
    Sendbird는 채팅 API와 메시지 전달 SDK 플랫폼으로 SaaS(소프트웨어 즉 서비스) 모델을 채택한다.SaaS 모드이기 때문에 고객은 변경 사항 없이 사용 가능한 기능을 갖춘 애플리케이션을 간단히 사용할 수 있습니다.Sendbird는 소프트웨어를 구입, 설치, 유지 관리 또는 업데이트하지 않고도 사용할 수 있습니다.
    판결 결과는 어떻습니까?답은 보잘것없을 수도 있지만, Twilio와 Sendbird 사이에서 선택하는 곤경은 업무 목표, 사용 가능한 기술 기능, 클라이언트 응용 프로그램에 필요한 채팅 기능에 있다.

    결어


    클라이언트 애플리케이션에 채팅 기능을 구축하기로 최종 결정했다면 React Native는 가장 유행하는 프레임워크 중 하나입니다.혼합 응용 프로그램과 로컬 응용 프로그램의 종합적인 장점을 효과적으로 통합시킬 수 있기 때문이다.이 문서의 마지막 부분에서는 React Native의 이점에 대해 자세히 설명합니다.
    채팅 프로그램의 백엔드로서, 우리는 Twilio와 Sendbird를 선택하기로 결정했다. 우리는 이것들이 React 원본 프로그램 중 가장 좋은 메시지 SDK 중 하나라고 생각한다.채팅 기능을 설정하고 구축하며 웹이나 모바일 응용 프로그램에 통합할 수 있지만, 다양한 기능을 가지고 있습니다.Twilio와 Sendbird가 제공하는 관건적인 기능을 비교했습니다. 이곳의 주요 목표는 당신의 업무 목표와 당신이 찾고 있는 채팅 프로그램 기능을 선택하는 것입니다.
    우리는 개발의 모든 단계를 매우 간단하고 질서정연하게 하며, 동시에 몇 단락의 코드로 채팅 응용의 맞춤형, 내비게이션, 설정을 설명하려고 한다.따라서 이 두 부분은 React Native를 사용하여 응용 프로그램에서 채팅 기능을 구축하는 데 도움을 줄 수 있기를 바랍니다.
    이 문장을 좋아합니까?dev.to의 Upsilon IT를 주목하고 최신 기술 노하우, 최고의 소프트웨어 개발 실천, 그리고 업계 전문가들의 통찰력이 풍부한 사례 연구를 이해합니다!당신의 사랑과 댓글은 우리의 미래 댓글의 연료입니다!

    좋은 웹페이지 즐겨찾기