Vue3, Firebase 프로젝트 - 채팅앱 VSignal

10. Vue3 Firebase 프로젝트 채팅앱 VSignal - 마지막 접속 시간 표시

그랜파 개발자 2025. 3. 21. 04:42

🔥 마지막 접속 시간 표시 기능 추가

실시간으로 상대방 온라인/오프라인 상태 확인 가능 합니다.
상대방이 오프라인일 경우 UI가 자동 업데이트되면서 마지막 접속 시간 표시할 수 있습니다.

1. Firebase에 마지막 접속 시간 저장

사용자가 오프라인으로 변경될 때 현재 시간을 기록
Firebase Realtime Database에 "lastSeen" 필드 추가

2. Store에서 마지막 접속 시간 관리

📌 store/userStore.js 수정

import { defineStore } from "pinia";
import { getDatabase, ref, set, onValue, serverTimestamp } from "firebase/database";
import { auth } from "@/firebase";

export const useUserStore = defineStore("user", {
  state: () => ({
    onlineUsers: {},
    currentChatUserStatus: "offline",
    lastSeen: null, // 마지막 접속 시간
  }),

  actions: {
    // ✅ 로그인 후 온라인 상태 설정
    async setOnlineStatus() {
      const db = getDatabase();
      const user = auth.currentUser;
      if (!user) return;

      const userRef = ref(db, `users/${user.uid}`);
      await set(userRef, {
        status: "online",
        lastSeen: serverTimestamp(), // 서버 타임스탬프 추가
      });

      // 🔥 오프라인 시 마지막 접속 시간 업데이트
      onValue(ref(db, `users/${user.uid}/status`), async (snapshot) => {
        if (!snapshot.exists() || snapshot.val() === "offline") {
          await set(ref(db, `users/${user.uid}/lastSeen`), serverTimestamp());
        }
      });
    },

    // ✅ 특정 사용자 온라인 상태 + 마지막 접속 시간 감지 (1:1 채팅용)
    listenForUserStatus(userId) {
      if (!userId) return;
      const db = getDatabase();
      const userRef = ref(db, `users/${userId}`);

      onValue(userRef, (snapshot) => {
        if (snapshot.exists()) {
          const data = snapshot.val();
          this.currentChatUserStatus = data.status || "offline";
          this.lastSeen = data.lastSeen || null;
        } else {
          this.currentChatUserStatus = "offline";
          this.lastSeen = null;
        }
      });
    },
  },
});
 

✔ "lastSeen" 필드에 Firebase 서버 타임스탬프 저장
✔ 사용자가 오프라인이 될 때 자동으로 마지막 접속 시간 업데이트

3. UI에서 마지막 접속 시간 표시

📌 ChatRoom.vue 수정

<script setup>
import { useUserStore } from "@/store/userStore";
import { useRoute } from "vue-router";
import { onMounted, computed } from "vue";

const userStore = useUserStore();
const route = useRoute();
const chatUserId = route.params.userId;

onMounted(() => {
  userStore.listenForUserStatus(chatUserId);
});

// ✅ 마지막 접속 시간을 읽기 쉬운 형식으로 변환
const formattedLastSeen = computed(() => {
  if (!userStore.lastSeen) return "정보 없음";
  const date = new Date(userStore.lastSeen);
  return date.toLocaleString(); // ex: "2025-03-06 14:30:00"
});
</script>

<template>
  <v-card>
    <v-card-title>
      상대방 상태:
      <v-icon :color="userStore.currentChatUserStatus === 'online' ? 'green' : 'grey'">
        mdi-circle
      </v-icon>
      {{ userStore.currentChatUserStatus === "online" ? "온라인" : "오프라인" }}
    </v-card-title>

    <v-card-subtitle v-if="userStore.currentChatUserStatus === 'offline'">
      마지막 접속: {{ formattedLastSeen }}
    </v-card-subtitle>

    <v-divider></v-divider>

    <v-card-text>
      <!-- 채팅 메시지 영역 -->
    </v-card-text>
  </v-card>
</template>

✅ 상대방이 오프라인이면 "마지막 접속 시간" 표시
✅ Firebase의 서버 시간을 로컬 시간 형식으로 변환하여 가독성 개선

🎯 결론

✅ 실시간으로 상대방 온라인/오프라인 상태 확인 가능
✅ 상대방이 오프라인일 경우 마지막 접속 시간 표시
✅ Firebase 서버 타임스탬프를 활용하여 정확한 시간 저장
✅ 1:1 채팅에서 UI가 자동 업데이트! 🚀