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

11. Vue3 Firebase 프로젝트 채팅앱 VSignal - 접속 시간 상대적으로 표시

그랜파 개발자 2025. 3. 22. 04:36

🔥 마지막 접속 시간 상대적으로 표시하기 (예: "5분 전 접속")

Firebase 서버 타임스탬프를 상대적 시간("5분 전")으로 변환하여 화면에 나타낼 수 있습니다.
date-fns를 활용하여 자동 업데이트 가능하고,
1:1 채팅에서 마지막 접속 시간이 상대적으로 표시함으로써 직관적입니다.

1. 상대적 시간 포맷팅 (예: "방금 전", "5분 전")

date-fns 라이브러리를 사용하여 상대적인 시간을 계산
Firebase 서버 시간을 기준으로 "몇 분 전", "몇 시간 전" 등의 형식으로 변환

2. date-fns 라이브러리 설치

npm install date-fns

3. Store에서 마지막 접속 시간을 상대적으로 변환

📌 store/userStore.js 수정

import { defineStore } from "pinia";
import { getDatabase, ref, onValue, serverTimestamp } from "firebase/database";
import { auth } from "@/firebase";
import { formatDistanceToNow } from "date-fns"; // ⏳ 상대적 시간 변환

export const useUserStore = defineStore("user", {
  state: () => ({
    currentChatUserStatus: "offline",
    lastSeen: null,
  }),

  getters: {
    // ✅ 마지막 접속 시간을 상대적 표현으로 변환 (예: "5분 전")
    relativeLastSeen: (state) => {
      if (!state.lastSeen) return "정보 없음";
      return formatDistanceToNow(new Date(state.lastSeen), { addSuffix: true });
    },
  },

  actions: {
    // ✅ 특정 사용자 온라인 상태 + 마지막 접속 시간 감지
    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;
        }
      });
    },
  },
});

✔ formatDistanceToNow() → lastSeen 시간을 상대적 표현으로 변환
✔ "5분 전", "2시간 전", "하루 전" 등 자연스럽게 표시

4. UI에서 상대적 마지막 접속 시간 표시

📌 ChatRoom.vue 수정

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

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

onMounted(() => {
  userStore.listenForUserStatus(chatUserId);
});
</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'">
      마지막 접속: {{ userStore.relativeLastSeen }}
    </v-card-subtitle>

    <v-divider></v-divider>

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

✅ 상대방이 오프라인이면 "마지막 접속: 5분 전" 같은 상대적 시간 표시
✅ 시간이 지나면 자동으로 "1시간 전" → "2시간 전" 으로 업데이트됨

🎯 결론

✅ Firebase 서버 타임스탬프를 상대적 시간("5분 전")으로 변환
✅ date-fns를 활용하여 자동 업데이트 가능
✅ 1:1 채팅에서 마지막 접속 시간이 직관적으로 표시됨 🚀

📆 date-fns란?

date-fns는 JavaScript 날짜 및 시간을 다룰 때 사용되는 가볍고 강력한 라이브러리입니다.
Moment.js보다 가볍고, 현대적인 함수형 API를 제공하며 트리 셰이킹(Tree Shaking)이 가능하여 성능 최적화에 유리합니다.

1. date-fns의 특징

✔ 가벼움: 필요한 기능만 가져올 수 있어 번들 크기가 작음
✔ 함수형 API: 각각의 기능이 독립적인 함수로 제공됨
✔ 트리 셰이킹 지원: 사용하지 않는 함수는 제거되어 번들 크기 최소화
✔ 다국어 지원: 다양한 언어의 날짜 포맷을 지원
✔ 타입스크립트 지원: TypeScript를 기본 지원

2. date-fns 설치

프로젝트에서 사용하려면 npm 또는 yarn을 이용하여 설치합니다.

npm install date-fns

3. date-fns 기본 사용법

📌 1) 현재 날짜 가져오기

import { format } from "date-fns";

const now = new Date();
console.log(format(now, "yyyy-MM-dd HH:mm:ss")); // 2025-03-06 14:30:15

📌 2) 상대적인 시간 차이 계산

import { formatDistanceToNow } from "date-fns";

const pastDate = new Date(2025, 2, 1); // 2025년 3월 1일
console.log(formatDistanceToNow(pastDate, { addSuffix: true }));  // "5일 전"

📌 3) 날짜 더하기 / 빼기

import { addDays, subHours } from "date-fns";

const today = new Date();
console.log(addDays(today, 5)); // 5일 후 날짜
console.log(subHours(today, 3)); // 3시간 전 날짜

📌 4) 날짜 비교

import { isBefore, isAfter } from "date-fns";

const date1 = new Date(2025, 2, 10);
const date2 = new Date(2025, 2, 15);

console.log(isBefore(date1, date2)); // true (date1이 date2보다 이전)
console.log(isAfter(date2, date1));  // true (date2가 date1보다 이후)

📌 5) 한국어 날짜 포맷 적용

import { format } from "date-fns";
import { ko } from "date-fns/locale";

const now = new Date();
console.log(format(now, "PPP", { locale: ko })); // "2025년 3월 6일"

🎯 결론

🚀 date-fns는 가볍고 강력한 날짜 처리 라이브러리로, Vue 프로젝트에서도 쉽게 적용 가능합니다.
📌 moment.js보다 성능 최적화에 유리하고, Intl.DateTimeFormat보다 더 유연한 포맷팅 기능을 제공합니다.

 

📆 Vue + Firebase 채팅 앱에서 "마지막 접속 시간", "메시지 읽음 시간" 같은 기능을 구현할 때 매우 유용합니다! 🎉