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 />);
}