Vue로 PWA 개발 - 그랜파 개발자
조회수에 대해 ‘/views/{postId}/users/{userId or anonymousId}’ 구조에 lastViewed 항목 즉 마지막 조회날짜 하나만 가진다면, 날짜별 조회수를 구할 수 없습니다. 사용자가 조회한 각 날짜 정보를 가져야 날짜별로 조회수를 구할 수 있습니다.
lastViewed 필드를 배열로 만들어 사용자가 해당 글을 조회할 때마다 조회 시간을 배열에 추가할 수 있습니다. Firestore는 배열 데이터를 지원하며, 배열에 항목을 추가하거나 업데이트할 수 있는 기능을 제공합니다. 이를 사용하면 사용자가 글을 조회할 때마다 조회 시간을 배열에 계속 추가할 수 있습니다.
Firestore에서 배열 필드를 업데이트할 때는 arrayUnion이라는 메서드를 사용합니다. arrayUnion은 해당 배열에 이미 존재하지 않는 값만 추가하며, 값이 중복되지 않도록 관리합니다. 이를 활용해 사용자가 글을 조회할 때마다 조회 시간을 배열로 저장할 수 있습니다.
/views/{postId}/users/{userId or anonymousId}
{
lastViewed: [Timestamp1, Timestamp2, Timestamp3, ...] // 조회 시간 배열
}
아래 코드는 사용자가 글을 조회할 때마다 조회 시간을 lastViewed 배열에 추가하는 방식으로 구현되었습니다.
import { db } from './firebase'; // Firestore 초기화
import { doc, getDoc, setDoc, arrayUnion, serverTimestamp } from 'firebase/firestore';
// 조회 기록 업데이트 함수
async function updateViewCount(postId, userId = null) {
const now = new Date();
let viewId;
// 비회원일 경우 로컬 스토리지 또는 쿠키를 사용하여 고유 ID 생성
if (!userId) {
viewId = getAnonymousId(); // 비회원에 대한 고유 ID 가져오기
} else {
viewId = userId; // 회원일 경우 사용자 ID
}
const viewDocRef = doc(db, 'views', postId, 'users', viewId);
// Firestore에서 해당 사용자의 조회 기록을 가져옵니다.
const viewDoc = await getDoc(viewDocRef);
if (viewDoc.exists()) {
// 오늘 조회 기록이 있는지 확인
const lastViewed = viewDoc.data().lastViewed;
const today = new Date().toDateString();
const viewedToday = lastViewed.some(view => view.toDate().toDateString() === today);
if (viewedToday) {
console.log("이미 오늘 조회하였습니다.");
return;
}
}
// Firestore의 lastViewed 배열에 조회 시간을 추가
await setDoc(viewDocRef, {
lastViewed: arrayUnion(serverTimestamp()) // 배열에 서버 시간을 추가
}, { merge: true });
console.log("조회수가 증가되었습니다.");
}
arrayUnion() 사용:
조회 기록 확인:
비회원 처리:
/views/abc123/users/user_1
{
lastViewed: [
September 5, 2024, 10:15:00 AM UTC,
September 6, 2024, 09:45:30 AM UTC
]
}
/views/abc123/users/anon_9sdfsdf
{
lastViewed: [
September 6, 2024, 08:15:42 AM UTC
]
}
이 기능을 Vue 컴포넌트에 적용하는 방식은 다음과 같습니다. 컴포넌트가 생성될 때 updateViewCount() 함수를 호출해 Firestore에 조회 시간을 추가합니다.
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<p>조회수: {{ post.viewCount }}</p>
</div>
</template>
<script>
import { db } from '../firebase';
import { doc, getDoc } from 'firebase/firestore';
import { updateViewCount } from '../utils/viewHandler'; // 조회수 업데이트 함수
export default {
data() {
return {
post: {},
};
},
async created() {
const postId = this.$route.params.id;
await this.fetchPost(postId);
const userId = this.$store.state.user ? this.$store.state.user.id : null; // 로그인 여부 확인
await updateViewCount(postId, userId); // 조회수 업데이트 및 기록
},
methods: {
async fetchPost(postId) {
const docRef = doc(db, 'posts', postId);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
this.post = docSnap.data();
} else {
console.log("게시글이 존재하지 않습니다.");
}
}
}
};
</script>
Firestore에서 lastViewed 배열을 사용하여 조회 기록을 계속 추가할 수 있습니다. arrayUnion() 함수를 사용해 중복되지 않는 새로운 조회 시간을 배열에 추가하고, 중복 조회를 방지합니다. 이 구조를 통해 사용자별로 조회 기록을 쉽게 관리할 수 있으며, 각 사용자의 조회 기록을 일자별로 추적할 수 있습니다.