Vue로 PWA 개발 - 그랜파 개발자
마이로그의 조회수는 사용자가 로그인을 하지 않아도 카운트되며, 한 사용자에 대해 하루에 여러번 조회를 해도 하루에 한번만 카운트합니다.
Firestore를 사용하여 작성된 글에 대해, 회원이든 비회원이든 하루에 여러 번 방문해도 조회수를 한 번만 증가시키는 방법을 구현할 수 있습니다. 이 작업은 Firestore에 사용자별로 조회 기록을 저장하고, 하루에 한 번만 조회수를 증가시키는 방식으로 해결할 수 있습니다.
/posts/{postId}
/views/{postId}/users/{userId or anonymousId}
아래 코드는 Firestore에서 조회수를 관리하는 함수입니다. 이 함수는 사용자가 해당 글을 이미 오늘 조회했는지 확인하고, 조회하지 않았다면 조회수를 1 증가시킵니다.
import { db } from './firebase'; // Firestore 초기화
import { doc, getDoc, setDoc, increment, 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);
const postDocRef = doc(db, 'posts', postId);
const viewDoc = await getDoc(viewDocRef);
// 사용자가 오늘 조회한 기록이 있는지 확인
if (viewDoc.exists()) {
const lastViewed = viewDoc.data().lastViewed.toDate();
if (isSameDay(lastViewed, now)) {
console.log("이미 오늘 조회하였습니다.");
return;
}
}
// Firestore에 조회 기록 추가 (또는 업데이트)
await setDoc(viewDocRef, {
lastViewed: serverTimestamp() // 서버 시간 저장
});
// 게시글의 조회수 1 증가
await setDoc(postDocRef, {
viewCount: increment(1) // 조회수 1 증가
}, { merge: true });
console.log("조회수가 증가되었습니다.");
}
// 날짜 비교 함수
function isSameDay(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
}
// 비회원 고유 ID 생성 (쿠키나 로컬 스토리지에서 ID 관리)
function getAnonymousId() {
let anonymousId = localStorage.getItem('anonymousId');
if (!anonymousId) {
anonymousId = 'anon_' + Math.random().toString(36).substr(2, 9); // 랜덤 ID 생성
localStorage.setItem('anonymousId', anonymousId); // 로컬 스토리지에 저장
}
return anonymousId;
}
작성된 글을 조회할 때마다 위 updateViewCount 함수를 호출하여 조회수를 업데이트합니다. 이때, 로그인한 사용자는 userId를, 비회원은 익명 ID를 사용해 조회수를 관리합니다.
<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>
비회원의 경우 쿠키나 로컬 스토리지를 사용하여 고유한 익명 ID를 생성하고 저장합니다. 이 익명 ID를 통해 비회원도 하루에 한 번만 조회수가 증가하도록 관리할 수 있습니다.
Firestore의 posts 컬렉션에는 각 게시글의 조회수가 저장됩니다. 예를 들어, Firestore에서 posts 컬렉션을 확인하면 다음과 같이 조회수를 확인할 수 있습니다:
/posts/{postId}
/views/{postId}/users/{userId or anonymousId}
게시글마다 viewCount 필드가 있고, 이 필드는 조회수가 증가될 때마다 1씩 증가합니다.
이 방법을 통해 회원이든 비회원이든 하루에 여러 번 방문하더라도 조회수를 한 번만 증가시키는 기능을 구현할 수 있습니다. Firestore의 views 컬렉션에서 사용자별 조회 기록을 관리하고, 날짜를 비교하여 조회수를 하루에 한 번만 증가시키는 로직을 적용했습니다.