실시간 채팅 컴포넌트 만들기
WebSocket 이벤트와 React 상태를 사용해 스크롤되는 채팅 목록에 실시간 메시지를 표시합니다.
실시간 채팅 컴포넌트 만들기은(는) CoddyKit의 무료 React Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
채팅 컴포넌트 아키텍처
실시간 채팅은 메시지 목록(표시), 메시지 입력(전송), WebSocket/Socket.IO 연결 계층의 세 부분으로 구성됩니다. 소켓 로직은 사용자 지정 훅에 두십시오.
메시지 데이터 형태
채팅 메시지에 대한 TypeScript 인터페이스를 정의하여 컴포넌트 전체에서 타입 안전성을 유지하십시오.
interface Message {
id: string;
text: string;
sender: string;
timestamp: number;
}
const [messages, setMessages] = useState<Message[]>([]);useChat 훅
연결, 메시지 상태, 전송 함수를 하나의 훅으로 캡슐화하십시오.
function useChat(roomId: string) {
const [messages, setMessages] = useState<Message[]>([]);
useEffect(() => {
socket.connect();
socket.emit('join-room', roomId);
socket.on('message', (msg: Message) => setMessages(m => [...m, msg]));
return () => {
socket.off('message');
socket.emit('leave-room', roomId);
socket.disconnect();
};
}, [roomId]);
const sendMessage = useCallback((text: string) => {
const msg: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
socket.emit('message', msg);
}, []);
return { messages, sendMessage };
}메시지 목록 컴포넌트
스크롤할 수 있는 목록에 메시지를 렌더링하십시오. 하단 감시 요소에 useRef를 사용하고 새 메시지가 도착하면 해당 요소로 스크롤하십시오.
function MessageList({ messages }: { messages: Message[] }) {
const bottomRef = useRef<HTMLDivElement>(null);
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
return (
<div className="message-list">
{messages.map(msg => (
<div key={msg.id} className={`msg ${msg.sender === 'me' ? 'mine' : 'theirs'}`}>
<span>{msg.sender}</span>
<p>{msg.text}</p>
</div>
))}
<div ref={bottomRef} />
</div>
);
}메시지 입력 컴포넌트
Enter 키를 누르거나 button을 클릭할 때 이벤트를 발생시키는 제어 입력입니다. 보낸 후 입력을 지우십시오.
function MessageInput({ onSend }: { onSend: (text: string) => void }) {
const [text, setText] = useState('');
const handleSend = () => {
if (!text.trim()) return;
onSend(text.trim());
setText('');
};
return (
<div className="input-row">
<input
value={text}
onChange={e => setText(e.target.value)}
onKeyDown={e => e.key === 'Enter' && handleSend()}
placeholder="Type a message..."
/>
<button onClick={handleSend}>Send</button>
</div>
);
}채팅 UI 조합
훅과 하위 컴포넌트를 하나의 ChatRoom 컴포넌트로 조합하십시오.
function ChatRoom({ roomId }: { roomId: string }) {
const { messages, sendMessage } = useChat(roomId);
return (
<div className="chat-room">
<h2>Room: {roomId}</h2>
<MessageList messages={messages} />
<MessageInput onSend={sendMessage} />
</div>
);
}optimistic 업데이트
서버가 확인하기 전에 메시지를 로컬 상태에 즉시 추가하여 즉각적인 피드백을 제공하십시오. 서버에서 오류를 반환하면 상태를 조정하거나 메시지를 제거하십시오.
const sendMessage = useCallback((text: string) => {
const optimistic: Message = { id: crypto.randomUUID(), text, sender: 'me', timestamp: Date.now() };
setMessages(m => [...m, optimistic]); // instant feedback
socket.emit('message', optimistic, (err) => {
if (err) setMessages(m => m.filter(msg => msg.id !== optimistic.id));
});
}, []);입력 중 표시기
입력이 변경될 때(디바운스하여) typing 이벤트를 발생시키고 다른 사용자의 입력 중 이벤트를 수신하여 표시기를 보여 주십시오.
const emitTyping = useMemo(() => debounce(() => socket.emit('typing'), 300), []);
useEffect(() => {
socket.on('user-typing', (user) => setTypingUser(user));
return () => socket.off('user-typing');
}, []);메시지 타임스탬프
로케일에 맞게 표시하려면 Intl.DateTimeFormat으로 타임스탬프를 형식화하십시오.
function formatTime(ts: number) {
return new Intl.DateTimeFormat('en', { hour: '2-digit', minute: '2-digit' }).format(ts);
}
<span className="timestamp">{formatTime(msg.timestamp)}</span>읽음 확인
사용자가 메시지를 볼 때 read 이벤트를 발생시키고 서버에서 읽음 확인을 수신하여 확인 표시를 보여 주십시오.
가상화된 메시지 목록
채팅 기록이 긴 경우 react-window 또는 react-virtual을 사용하여 메시지 목록을 가상화하고 보이는 행만 렌더링하십시오.
메시지 기록 제한
긴 세션에서 메모리가 제한 없이 증가하지 않도록 상태의 메시지 배열에 상한을 설정하십시오.
socket.on('message', (msg: Message) => {
setMessages(prev => [...prev.slice(-499), msg]); // keep last 500
});빠른 확인
채팅 목록에 새 메시지가 도착했을 때 하단 감시용 div 요소로 스크롤하는 목적은 무엇입니까?
복습
소켓 로직을 캡슐화하는 useChat 훅, 자동 스크롤 기능이 있는 MessageList, 전송 후 입력을 지우는 MessageInput으로 실시간 채팅을 구축하십시오. 즉각적인 피드백에는 optimistic 업데이트를 사용하고 메모리 누수를 방지하도록 메시지 기록에 상한을 설정하십시오.
자주 묻는 질문
“실시간 채팅 컴포넌트 만들기” 강의는 무료인가요?
네 — “실시간 채팅 컴포넌트 만들기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Academy 강의 전체를 잠금 해제할 수 있습니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“실시간 채팅 컴포넌트 만들기”에서 뭘 배우나요?
WebSocket 이벤트와 React 상태를 사용해 스크롤되는 채팅 목록에 실시간 메시지를 표시합니다. 브라우저에서 직접 실행하는 실습 코드로 React Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
React Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 React Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“실시간 채팅 컴포넌트 만들기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 React Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 React Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 브라우저에서 WebSocket 기초 익히기
- React에서 Socket.IO 사용하기
- 실시간 채팅 컴포넌트 만들기
- 재연결, 오류 처리와 정리