๐Ÿ“ก 77. React Native์—์„œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ ์™„์ „ ์ •๋ฆฌ โ€” Socket.io, WebSocket, Firebase ๋น„๊ต

JM_Devยท2025๋…„ 8์›” 13์ผ
0
post-thumbnail

์•ฑ์—์„œ ์ฑ„ํŒ… ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜๋‹ค.
React Native์—์„œ๋Š” ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•˜๋ฉฐ, ๋„คํŠธ์›Œํฌ ์ƒํƒœ๊ฐ€ ๋ถˆ์•ˆ์ •ํ•ด๋„ ์•ˆ์ •์ ์ธ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ ์ „๋žต์„ ์ •๋ฆฌํ•˜๊ณ , ๊ฐ ๊ธฐ์ˆ ๋ณ„ ์žฅ๋‹จ์ ์„ ๋น„๊ตํ•œ๋‹ค.


โœ… ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์ด ์–ด๋ ค์šด ์ด์œ 

  • ๋„คํŠธ์›Œํฌ ์ง€์—ฐ: ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ๋Š” Wi-Fi, 4G/5G, ์ด๋™ ๊ฐ„ ์‹ ํ˜ธ ๋ถˆ์•ˆ์ •์ด ๋นˆ๋ฒˆํ•˜๋‹ค.
  • ๋™์‹œ ์ ‘์† ์ฒ˜๋ฆฌ: ๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ์ฑ„ํŒ…ํ•  ๊ฒฝ์šฐ ์„œ๋ฒ„ ๋ถ€ํ•˜๊ฐ€ ์ปค์ง„๋‹ค.
  • ๋ฉ”์‹œ์ง€ ๋™๊ธฐํ™”: ์ฝ์Œ ํ‘œ์‹œ, ๋ฉ”์‹œ์ง€ ์ˆœ์„œ, ์ค‘๋ณต ์ „์†ก ๋ฐฉ์ง€ ๋“ฑ ๋ณต์žกํ•œ ๋™๊ธฐํ™” ๋กœ์ง์ด ํ•„์š”ํ•˜๋‹ค.
  • ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ฒ˜๋ฆฌ: ์•ฑ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์— ์žˆ์„ ๋•Œ ํ‘ธ์‹œ ์•Œ๋ฆผ๊ณผ ๋™๊ธฐํ™” ์ „๋žต์ด ํ•„์š”ํ•˜๋‹ค.

๐Ÿ”Œ 1. WebSocket ๊ธฐ๋ฐ˜ ๊ตฌํ˜„

WebSocket์€ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์ง€์›ํ•œ๋‹ค.
React Native์—์„œ๋Š” react-native-websocket ๋˜๋Š” Socket.io-client๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.

์˜ˆ์‹œ โ€” Socket.io ์‚ฌ์šฉ

npm install socket.io-client
// chatSocket.ts
import { io } from 'socket.io-client';

export const socket = io('https://your-chat-server.com', {
  transports: ['websocket'],
});
// ChatScreen.tsx
import { useEffect, useState } from 'react';
import { View, Text, TextInput, Button } from 'react-native';
import { socket } from './chatSocket';

export default function ChatScreen() {
  const [messages, setMessages] = useState<string[]>([]);
  const [input, setInput] = useState('');

  useEffect(() => {
    socket.on('receiveMessage', (msg) => {
      setMessages((prev) => [...prev, msg]);
    });

    return () => {
      socket.off('receiveMessage');
    };
  }, []);

  const sendMessage = () => {
    socket.emit('sendMessage', input);
    setInput('');
  };

  return (
    <View>
      {messages.map((m, i) => (
        <Text key={i}>{m}</Text>
      ))}
      <TextInput value={input} onChangeText={setInput} />
      <Button title="์ „์†ก" onPress={sendMessage} />
    </View>
  );
}

๐Ÿ”ฅ 2. Firebase Realtime Database / Firestore

Firebase๋Š” ๋ณ„๋„์˜ ์„œ๋ฒ„ ๊ตฌ์ถ• ์—†์ด ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
์žฅ์ ์€ ๋น ๋ฅธ ๊ฐœ๋ฐœ๊ณผ ์•ˆ์ •์„ฑ, ๋‹จ์ ์€ ๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ ์‹œ ๋น„์šฉ ์ฆ๊ฐ€๋‹ค.

npm install @react-native-firebase/app @react-native-firebase/firestore
// chatService.ts
import firestore from '@react-native-firebase/firestore';

export function sendMessage(roomId: string, message: string) {
  return firestore().collection('rooms').doc(roomId).collection('messages').add({
    text: message,
    createdAt: new Date(),
  });
}

export function subscribeMessages(roomId: string, callback: (msgs: any[]) => void) {
  return firestore()
    .collection('rooms')
    .doc(roomId)
    .collection('messages')
    .orderBy('createdAt', 'asc')
    .onSnapshot((snapshot) => {
      callback(snapshot.docs.map((doc) => doc.data()));
    });
}

๐Ÿ“Š 3. ๊ธฐ์ˆ  ๋น„๊ต

๊ธฐ์ˆ ์žฅ์ ๋‹จ์ ์ถ”์ฒœ ์‚ฌ์šฉ ์‚ฌ๋ก€
WebSocket / Socket.io๋น ๋ฅธ ์‘๋‹ต, ์ž์œ ๋กœ์šด ๊ตฌํ˜„์„œ๋ฒ„ ๊ตฌ์ถ• ํ•„์š”๋Œ€๊ทœ๋ชจ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…
Firebase๋น ๋ฅธ ๊ฐœ๋ฐœ, ์„œ๋ฒ„ ๋ถˆํ•„์š”๋Œ€๊ทœ๋ชจ ์‹œ ๋น„์šฉ ๋ถ€๋‹ด์Šคํƒ€ํŠธ์—… MVP, ์†Œ๊ทœ๋ชจ ์ฑ„ํŒ…
Pusher / Ably์„œ๋ฒ„๋ฆฌ์Šค, ์•ˆ์ •์„ฑ์‚ฌ์šฉ๋Ÿ‰ ์ œํ•œ, ๋น„์šฉ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅ

๐Ÿง  ์‹ค์ „ ํŒ

  1. ๋„คํŠธ์›Œํฌ ๋ณต๊ตฌ ์‹œ ์žฌ์—ฐ๊ฒฐ ๋กœ์ง์„ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•œ๋‹ค.
  2. ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€์— ๋กœ์ปฌ ID๋ฅผ ๋ถ€์—ฌํ•ด ์ค‘๋ณต ์ „์†ก์„ ๋ฐฉ์ง€ํ•œ๋‹ค.
  3. ์ฝ์Œ ํ‘œ์‹œ(read receipts)๋Š” ๋ณ„๋„ ์ปฌ๋ ‰์…˜ ๋˜๋Š” ์ƒํƒœ ๊ด€๋ฆฌ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.
  4. ์ด๋ฏธ์ง€, ํŒŒ์ผ ์ „์†ก์€ Cloud Storage + ๋ฉ”์‹œ์ง€ URL ์ €์žฅ ๋ฐฉ์‹์ด ํšจ์œจ์ ์ด๋‹ค.
  5. ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์—์„œ๋Š” ํ‘ธ์‹œ ์•Œ๋ฆผ๊ณผ ํ•จ๊ป˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋™๊ธฐํ™”ํ•œ๋‹ค.

๐Ÿ’ฌ "์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์€ ๊ธฐ์ˆ ๋ณด๋‹ค ์šด์˜ ์ „๋žต์ด ๋” ์ค‘์š”ํ•˜๋‹ค."


profile
๊ฐœ๋ฐœ์ž๋กœ ์ทจ์—…์„ ์ค€๋น„ ์ค‘ ์ด๋ฉฐ, ์—ด์‹ฌํžˆ ๊ณต๋ถ€ ์ค‘ ์ž…๋‹ˆ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€