Written by
Lee Jongseo
on
on
Firebase - Channel Message기능 구현하기(6)
데이터베이스에 Messages 저장하기
채널을 개설하면 그 안에서 채팅을 할 수 있는 기능을 구현할 것이다. 각각의 채팅은 messages라는 collection에 저장되고, messages에서 데이터를 가져와 채팅창 화면을 보여분다.
Messages 스키마
messages collection 밑에 각각의 채널을 구분하는 고유 key가 있고 채널 밑에는 message document가 있다.
{
messages : [
uniqueChannelId: [
message1,
message2,
...
]
]
}
이런 식으로 message가 저장될 것이다.
child().push().set()
push() unique한 새로운 child 위치에 대한 reference를 반환한다. 여기에 데이터를 추가하는 메소드인 set()과 함께 쓰이면 child 위치에 고유 key를 생성하면서 그 key밑에 데이터를 생성하는 것이다.
const messagesRef = firebase.database().ref("messages"); // messages 레퍼런스 생성
messagesRef.child(채널 고유 key).push().set(메시지)
실제 메시지를 데이터베이스에 저장하는 함수를 작성하면 다음과 같이 작성할 수 있다.
/*
type Messasge = {
content: string
timestamp: Date
user: User
}
*/
const sendMessage = (channelId, message) => {
messagesRef
.child(channelId)
.push()
.set({
...message,
// timestamp를 client쪽에서 추가해준다.
timestamp: firebase.database.ServerValue.TIMESTAMP,
})
.then(() => {
// 성공
})
.catch(() => {
// 실패
});
};
컴포넌트에서 message 저장하기
컴포넌트에서 메시지를 데이터베이스에 저장하기 위해서는 먼저 사용자의 입력을 받을 수 있는 form이 있어야 한다. 그리고 사용자의 입력을 담을 수 있는 state도 필요할 것이다. 보내기 버튼을 클릭하면 메시지가 데이터베이스에 전송할 수 있도록 onClick 헨들러로 방금 정의한 함수를 달아야 할 것이다.
// MessageFormContainer.jsx
const currentChannel = useSelector((state) => state.channel.currentChannel);
const [message, setMessage] = useState(null);
// MessageForm.jsx
return (
// ...
<form>
{/*....*/}
<button onClick={() => sendMessage(currentChannel.id, message)}>
메시지 전송
</button>
</form>
);
물론 위 코드는 뼈대만 작성한 것이다.
데이터베이스에서 Messages 가져오기
on(“child_added”)
message를 데이터베이스에 저장하면 새로 추가된 message를 가져와 채팅창 화면에 보여줘야 할 것이다. on("child_added") 를 통해서 messages 에 리스너를 달아준다.
const [messages, setMessages] = useState([]);
useEffect(() => {
let loaded = [];
messagesRef.child(currentChannel.id).on("child_added", (snap) => {
loaded.push(snap.val());
setMessages([...loaded]);
});
}, []);
데이터베이스에서 가져온 messages는 state로 관리하게 되고 이를 화면에 보여준다.
{
messages.map((m) => <Message />);
}