채팅앱에 접속한 상태라면 메시지가 실시간으로 업데이트 되어야 합니다.
Firestore의 onSnapshot()을 이용하여 새로운 메시지가 추가될 때마다 자동으로 화면을 업데이트 할 수 있다고 하네요.
나의 말:
실시간 메시지 업데이트부터 구현해 보자
ChatGPT의 말:
좋아! Firestore의 onSnapshot()을 사용해서 실시간 메시지 업데이트를 구현해보자.
1. Firestore에서 실시간 메시지 수신
Firebase Firestore의 onSnapshot()을 이용하면 새로운 메시지가 추가될 때마다 자동으로 화면을 업데이트할 수 있어.
firebase.js에서 실시간 메시지 가져오기 함수 추가
// src/firebase.js
import { getFirestore, collection, addDoc, query, where, orderBy, onSnapshot } from "firebase/firestore";
const db = getFirestore();
// 🔹 특정 채팅방의 실시간 메시지 수신
const listenForMessages = (chatId, callback) => {
const messagesRef = collection(db, `chats/${chatId}/messages`);
const q = query(messagesRef, orderBy("timestamp"));
return onSnapshot(q, (snapshot) => {
const messages = snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
callback(messages);
});
};
export { listenForMessages };
설명:
✔ onSnapshot(q, callback) → Firestore에서 실시간 데이터 수신
✔ 메시지가 변경될 때마다 callback 함수를 실행하여 UI 업데이트
2. Vue에서 실시간 메시지 적용
이제 ChatView.vue에서 실시간 메시지 업데이트를 적용해보자.
ChatView.vue 업데이트
<!-- src/views/ChatView.vue -->
<template>
<v-container class="fill-height d-flex flex-column">
<v-card class="pa-5" width="400">
<v-card-title class="text-center text-h5">1:1 채팅</v-card-title>
<v-select v-model="selectedUser" :items="users" label="대화 상대 선택" />
<v-divider class="my-2"></v-divider>
<v-list v-if="messages.length > 0">
<v-list-item v-for="msg in messages" :key="msg.id">
<v-list-item-content>
<v-list-item-title>
<strong>{{ msg.sender === currentUser ? "나" : "상대" }}:</strong>
{{ msg.message }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
<v-text-field v-model="newMessage" label="메시지 입력" @keyup.enter="handleSendMessage" />
<v-btn color="primary" block class="mt-3" @click="handleSendMessage">전송</v-btn>
<v-btn color="red" block class="mt-3" @click="handleLogout">로그아웃</v-btn>
</v-card>
</v-container>
</template>
<script>
import { ref, watch, onUnmounted } from "vue";
import { auth, getOrCreateChat, sendMessage, listenForMessages } from "@/firebase";
import { useRouter } from "vue-router";
export default {
setup() {
const router = useRouter();
const currentUser = auth.currentUser?.email;
const selectedUser = ref(""); // 대화할 사용자 선택
const users = ref(["user1@example.com", "user2@example.com"]); // 예제 사용자 리스트
const chatId = ref(null);
const newMessage = ref("");
const messages = ref([]);
let unsubscribe = null; // Firestore 리스너 해제 함수
// 로그아웃
const handleLogout = async () => {
await auth.signOut();
router.push("/");
};
// 메시지 전송
const handleSendMessage = async () => {
if (newMessage.value.trim() === "" || !chatId.value) return;
await sendMessage(chatId.value, currentUser, newMessage.value);
newMessage.value = "";
};
// 채팅방 변경 감지 → Firestore 실시간 메시지 업데이트
watch(selectedUser, async (newUser) => {
if (unsubscribe) unsubscribe(); // 기존 리스너 해제
if (newUser) {
chatId.value = await getOrCreateChat(currentUser, newUser);
unsubscribe = listenForMessages(chatId.value, (newMessages) => {
messages.value = newMessages;
});
}
});
// 컴포넌트 언마운트 시 Firestore 리스너 해제
onUnmounted(() => {
if (unsubscribe) unsubscribe();
});
return { selectedUser, users, newMessage, handleSendMessage, messages, handleLogout, currentUser };
},
};
</script>
변경사항:
✔ Firestore에서 실시간 메시지 수신 (listenForMessages())
✔ 채팅방 변경 시 기존 리스너 해제 후 새로 등록
✔ 컴포넌트 언마운트 시 onUnmounted()로 Firestore 리스너 해제
3. 테스트하기
- 실시간 메시지 업데이트 테스트 방법
- 두 개의 브라우저 창을 열고 로그인
- 서로 다른 계정으로 대화 상대를 선택
- 한쪽에서 메시지를 입력하면, 실시간으로 상대방 화면에 나타나는지 확인
마무리 & 다음 단계
🔥 이제 실시간 메시지 업데이트가 동작해! 🚀
다음 할 일:
🔹 채팅 목록에서 최근 메시지 표시
🔹 메시지 전송 시간 표시
🔹 온라인/오프라인 상태 표시
👉 어떤 기능부터 추가하고 싶어? 😊
'Vue3, Firebase 프로젝트 - 채팅앱 VSignal' 카테고리의 다른 글
6. Vue3 프로젝트 실시간 채팅앱 VSignal - 1:1 채팅 UI 만들기 (0) | 2025.03.16 |
---|---|
5. Vue3 프로젝트 VSignal 채팅앱 - Vuetify로 UI 만들기 (0) | 2025.03.15 |
3. Vue3 프로젝트 - 실시간 채팅앱 VSignal 1:1 채팅 (0) | 2025.03.12 |
2. Vue3 프로젝트 - vite 빠른 프론트엔드 빌드 도구 (0) | 2025.03.11 |
1. Vue3와 Firebase 프로젝트 - 실시간 채팅앱 VSignal 개발 (0) | 2025.03.10 |