57. 글 조회수 추가
ChatGPT에게 물었습니다.
post의 조회수를 알고 싶어.
I want to know the number of views of the post
To track and display the number of views for each post, you'll need to update the Firestore document to include a view count and increment it each time the post is viewed. Here's how you can achieve this:
각 게시물의 조회수를 추적하고 표시하려면 조회수를 포함하고 게시물을 볼 때마다 증가하도록 Firestore 문서를 업데이트해야 합니다. 이를 달성하는 방법은 다음과 같습니다.
Steps
- Modify the post structure to include a view count.
조회수를 포함하도록 게시물 구조를 수정하세요. - Increment the view count each time the post is viewed.
포스트를 볼 때마다 조회수가 증가합니다. - Display the view count in the post details and list.
게시물 세부정보 및 목록에 조회수를 표시합니다.
1. Modify the Post Structure
1. 게시물 구조 수정
When you save a post, initialize a views field with a value of 0.
게시물 세부정보 및 목록에 조회수를 표시합니다.
<!-- views/WritePost.vue -->
<template>
<v-container>
<v-form @submit.prevent="submitPost">
<v-text-field v-model="title" label="Title" required></v-text-field>
<v-textarea v-model="content" label="Content" rows="10" required></v-textarea>
<v-btn type="submit" color="primary">Submit</v-btn>
</v-form>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
title: '',
content: '',
};
},
methods: {
async submitPost() {
const user = auth.currentUser;
if (user) {
try {
await db.collection('users').doc(user.uid).collection('posts').add({
title: this.title,
content: this.content,
userName: user.displayName, // Ensure the user's name is available
createdAt: new Date(),
views: 0, // Initialize view count
});
this.$router.push('/user-posts');
} catch (error) {
console.error("Error writing document: ", error);
}
} else {
console.error("User not authenticated");
}
},
},
};
</script>
2. Increment the View Count
2. 조회수 늘리기
Each time a post is viewed, increment the view count in Firestore.
게시물을 볼 때마다 Firestore의 조회수가 증가합니다.
<!-- views/PostDetailView.vue -->
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<div v-if="post">
<h1>{{ post.title }}</h1>
<div>{{ post.userName }} - {{ formatDate(post.createdAt) }}</div>
<div>{{ post.content }}</div>
<div>Views: {{ post.views }}</div>
</div>
</v-container>
</template>
<script>
import { db } from '../firebase';
export default {
data() {
return {
post: null,
loading: false,
error: null
};
},
async created() {
const postId = this.$route.params.id;
this.loading = true;
try {
const user = auth.currentUser;
if (user) {
const postRef = db.collection('users').doc(user.uid).collection('posts').doc(postId);
const postDoc = await postRef.get();
if (postDoc.exists) {
this.post = { id: postDoc.id, ...postDoc.data() };
await postRef.update({ views: firebase.firestore.FieldValue.increment(1) });
} else {
this.error = { message: 'Post not found' };
}
} else {
this.error = { message: 'User not authenticated' };
}
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
},
methods: {
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
}
}
};
</script>
3. Display the View Count
3. 조회수 표시
Update the component that displays the list of posts to include the view count.
조회수를 포함하도록 게시물 목록을 표시하는 구성요소를 업데이트합니다.
<!-- views/UserPosts.vue -->
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<v-list v-if="!loading">
<v-list-item v-for="post in posts" :key="post.id" @click="goToPostDetail(post.id)">
<v-list-item-content>
<v-list-item-title>{{ post.title }}</v-list-item-title>
<v-list-item-subtitle>
<div>{{ post.userName }}</div>
<div>{{ formatDate(post.createdAt) }}</div>
<div>Views: {{ post.views }}</div>
</v-list-item-subtitle>
<v-list-item-subtitle>{{ post.content }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
posts: [],
loading: false,
error: null
};
},
async created() {
this.loading = true;
const user = auth.currentUser;
if (user) {
try {
const querySnapshot = await db.collection('users').doc(user.uid).collection('posts').get();
this.posts = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
} else {
this.error = { message: 'User not authenticated' };
this.loading = false;
}
},
methods: {
goToPostDetail(postId) {
this.$router.push({ name: 'PostDetailView', params: { id: postId } });
},
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
}
}
};
</script>
Summary 요약
- Modify Post Submission: Include an initial view count when saving a post.
게시물 수정: 게시물을 저장할 때 초기 조회수를 포함합니다. - Increment View Count: Increment the view count each time the post is viewed.
조회수 증가: 게시물을 볼 때마다 조회수가 증가합니다. - Display View Count: Fetch and display the view count along with the post details.
조회수 표시: 게시물 세부정보와 함께 조회수를 가져와 표시합니다.
By following these steps, you can track and display the number of views for each post. 다음 단계를 따르면 각 게시물의 조회수를 추적하고 표시할 수 있습니다.
ChatGPT에게 물었습니다.
Even if the same person views it multiple times on the same day, I want the number of views to be 1.
같은 사람이 같은 날 여러번 조회해도 조회수는 1로 하고 싶어.
To ensure that the same person viewing the post multiple times on the same day only increments the view count once, you can implement a system to track unique views. One way to achieve this is by storing the user IDs and dates of views in a separate subcollection or field within the post document.
동일한 사람이 같은 날 게시물을 여러 번 보는 경우 조회수가 한 번만 증가하도록 하려면 고유한 조회수를 추적하는 시스템을 구현할 수 있습니다. 이를 달성하는 한 가지 방법은 사용자 ID와 조회 날짜를 게시물 문서 내의 별도 하위 컬렉션이나 필드에 저장하는 것입니다.
Here's how you can implement this:
이를 구현하는 방법은 다음과 같습니다.
Steps
- Modify the post structure to include a viewedBy field.
'viewedBy' 필드를 포함하도록 게시물 구조를 수정하세요. - Update the view count logic to track unique views per user per day.
조회수 로직을 업데이트하여 사용자별 일일 고유 조회수를 추적하세요. - Display the unique view count in the post details and list.
게시물 세부정보 및 목록에 순 조회수를 표시합니다.
1. Modify the Post Structure
1. 게시물 구조 수정
When you save a post, initialize a viewedBy field as an empty array or subcollection.
게시물을 저장할 때 viewedBy 필드를 빈 배열 또는 하위 컬렉션으로 초기화하세요.
views/WritePost.vue
<template>
<v-container>
<v-form @submit.prevent="submitPost">
<v-text-field v-model="title" label="Title" required></v-text-field>
<v-textarea v-model="content" label="Content" rows="10" required></v-textarea>
<v-btn type="submit" color="primary">Submit</v-btn>
</v-form>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
title: '',
content: '',
};
},
methods: {
async submitPost() {
const user = auth.currentUser;
if (user) {
try {
await db.collection('users').doc(user.uid).collection('posts').add({
title: this.title,
content: this.content,
userName: user.displayName, // Ensure the user's name is available
createdAt: new Date(),
views: 0, // Initialize view count
viewedBy: [] // Initialize viewedBy array
});
this.$router.push('/user-posts');
} catch (error) {
console.error("Error writing document: ", error);
}
} else {
console.error("User not authenticated");
}
},
},
};
</script>
2. Update the View Count Logic
2. 조회수 로직 업데이트
Each time a post is viewed, check if the user has already viewed it on the same day. If not, increment the view count and update the viewedBy field.
게시물을 볼 때마다 해당 사용자가 같은 날 이미 해당 게시물을 봤는지 확인하세요. 그렇지 않은 경우 조회수를 늘리고 'viewedBy' 필드를 업데이트하세요.
views/PostDetailView.vue
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<div v-if="post">
<h1>{{ post.title }}</h1>
<div>{{ post.userName }} - {{ formatDate(post.createdAt) }}</div>
<div>{{ post.content }}</div>
<div>Views: {{ post.views }}</div>
</div>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
import firebase from 'firebase/app';
export default {
data() {
return {
post: null,
loading: false,
error: null
};
},
async created() {
const postId = this.$route.params.id;
this.loading = true;
try {
const user = auth.currentUser;
if (user) {
const postRef = db.collection('users').doc(user.uid).collection('posts').doc(postId);
const postDoc = await postRef.get();
if (postDoc.exists) {
this.post = { id: postDoc.id, ...postDoc.data() };
const today = new Date().toISOString().split('T')[0];
const alreadyViewed = this.post.viewedBy.some(view => view.userId === user.uid && view.date === today);
if (!alreadyViewed) {
await postRef.update({
views: firebase.firestore.FieldValue.increment(1),
viewedBy: firebase.firestore.FieldValue.arrayUnion({ userId: user.uid, date: today })
});
this.post.views += 1; // Update the local view count
}
} else {
this.error = { message: 'Post not found' };
}
} else {
this.error = { message: 'User not authenticated' };
}
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
},
methods: {
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
}
}
};
</script>
3. Display the View Count
3. 조회수 표시
Update the component that displays the list of posts to include the view count.
조회수를 포함하도록 게시물 목록을 표시하는 구성요소를 업데이트합니다.
views/UserPosts.vue
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<v-list v-if="!loading">
<v-list-item v-for="post in posts" :key="post.id" @click="goToPostDetail(post.id)">
<v-list-item-content>
<v-list-item-title>{{ post.title }}</v-list-item-title>
<v-list-item-subtitle>
<div>{{ post.userName }}</div>
<div>{{ formatDate(post.createdAt) }}</div>
<div>Views: {{ post.views }}</div>
</v-list-item-subtitle>
<v-list-item-subtitle>{{ post.content }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
posts: [],
loading: false,
error: null
};
},
async created() {
this.loading = true;
const user = auth.currentUser;
if (user) {
try {
const querySnapshot = await db.collection('users').doc(user.uid).collection('posts').get();
this.posts = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
} else {
this.error = { message: 'User not authenticated' };
this.loading = false;
}
},
methods: {
goToPostDetail(postId) {
this.$router.push({ name: 'PostDetailView', params: { id: postId } });
},
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
}
}
};
</script>
Summary 요약
- Modify Post Submission: Include a viewedBy field when saving a post.
게시물 제출 수정: 게시물을 저장할 때 viewedBy 필드를 포함합니다. - Unique View Count Logic: Check if the user has already viewed the post on the same day before incrementing the view count.
순 조회수 논리: 조회수를 늘리기 전에 사용자가 같은 날 게시물을 이미 조회했는지 확인합니다. - Display View Count: Fetch and display the unique view count along with the post details.
조회수 표시: 게시물 세부정보와 함께 고유 조회수를 가져와 표시합니다.
By following these steps, you can ensure that the same person viewing the post multiple times on the same day only increments the view count once.
다음 단계를 수행하면 동일한 사람이 같은 날 게시물을 여러 번 보는 경우 조회수가 한 번만 증가하도록 할 수 있습니다.
ChatGPT에게 물었습니다.
I want to include views even if I'm not a member.
회원이 아닌 경우에도 조회수를 포함하고 싶어.
To track views for both authenticated and unauthenticated users while ensuring that multiple views from the same user on the same day are counted as one, you can use a combination of cookies/local storage and Firestore to store view information.
인증된 사용자와 인증되지 않은 사용자 모두의 조회수를 추적하는 동시에 같은 날 동일한 사용자의 여러 조회수가 1회로 계산되도록 하려면 쿠키/로컬 저장소와 Firestore의 조합을 사용하여 조회 정보를 저장할 수 있습니다.
Here's a detailed approach:
자세한 접근 방식은 다음과 같습니다.
1. Store the view data in Firestore.
Firestore에 뷰 데이터를 저장합니다.
2. Use cookies/local storage to track views for unauthenticated users.
쿠키/로컬 저장소를 사용하여 인증되지 않은 사용자의 조회수를 추적합니다.
3. Ensure that views from the same user on the same day are counted as one.
같은 날 같은 사용자의 조회수가 1회로 집계되는지 확인하세요.
4. Increment the view count accordingly.
따라서 조회수를 늘리세요.
1. Storing View Data in Firestore
1. Firestore에 뷰 데이터 저장
When saving a post, include a viewedBy field to track who viewed the post and when.
게시물을 저장할 때 'viewedBy' 필드를 포함하면 누가 언제 게시물을 봤는지 추적할 수 있습니다.
2. Track Views for Unauthenticated Users Using Cookies/Local Storage
2. 쿠키/로컬 저장소를 사용하는 인증되지 않은 사용자에 대한 추적 보기
Store the view data (e.g., post ID and date) in the user's browser using cookies or local storage to prevent multiple views on the same day from being counted.
같은 날에 여러 번 조회한 횟수가 집계되지 않도록 쿠키 또는 로컬 저장소를 사용하여 조회 데이터(예: 게시물 ID 및 날짜)를 사용자의 브라우저에 저장합니다.
Example Implementation 구현 예
Post Detail Component (PostDetailView.vue)
This component displays the post details and tracks views.
이 구성 요소는 게시물 세부 정보를 표시하고 보기를 추적합니다.
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<div v-if="post">
<h1>{{ post.title }}</h1>
<div>{{ post.userName }} - {{ formatDate(post.createdAt) }}</div>
<div>{{ post.content }}</div>
<div>Views: {{ post.views }}</div>
</div>
</v-container>
</template>
<script>
import { db } from '../firebase';
import firebase from 'firebase/app';
import { auth } from '../firebase';
import { v4 as uuidv4 } from 'uuid';
export default {
data() {
return {
post: null,
loading: false,
error: null
};
},
async created() {
const postId = this.$route.params.id;
this.loading = true;
try {
const postRef = db.collection('posts').doc(postId);
const postDoc = await postRef.get();
if (postDoc.exists) {
this.post = { id: postDoc.id, ...postDoc.data() };
const today = new Date().toISOString().split('T')[0];
let userId;
if (auth.currentUser) {
userId = auth.currentUser.uid;
} else {
userId = this.getOrCreateAnonymousUserId();
}
const alreadyViewed = this.post.viewedBy.some(view => view.userId === userId && view.date === today);
if (!alreadyViewed) {
await postRef.update({
views: firebase.firestore.FieldValue.increment(1),
viewedBy: firebase.firestore.FieldValue.arrayUnion({ userId, date: today })
});
this.post.views += 1; // Update the local view count
}
} else {
this.error = { message: 'Post not found' };
}
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
},
methods: {
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
},
getOrCreateAnonymousUserId() {
let userId = localStorage.getItem('anonymousUserId');
if (!userId) {
userId = uuidv4();
localStorage.setItem('anonymousUserId', userId);
}
return userId;
}
}
};
</script>
List Component (UserPosts.vue)
This component displays the list of posts and their view counts.
이 구성 요소는 게시물 목록과 조회수를 표시합니다.
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<v-list v-if="!loading">
<v-list-item v-for="post in posts" :key="post.id" @click="goToPostDetail(post.id)">
<v-list-item-content>
<v-list-item-title>{{ post.title }}</v-list-item-title>
<v-list-item-subtitle>
<div>{{ post.userName }}</div>
<div>{{ formatDate(post.createdAt) }}</div>
<div>Views: {{ post.views }}</div>
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
posts: [],
loading: false,
error: null
};
},
async created() {
this.loading = true;
try {
const querySnapshot = await db.collection('posts').get();
this.posts = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
},
methods: {
goToPostDetail(postId) {
this.$router.push({ name: 'PostDetailView', params: { id: postId } });
},
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
}
}
};
</script>
Summary 요약
- Store View Data: Include a viewedBy field in your Firestore post document to track views.
뷰 데이터 저장: 조회수를 추적하려면 Firestore 게시물 문서에 'viewedBy' 필드를 포함하세요. - Track Unique Views: Use local storage to store an anonymous user ID for unauthenticated users to ensure unique views.
고유 조회수 추적: 로컬 저장소를 사용하여 인증되지 않은 사용자에 대한 익명 사용자 ID를 저장하여 고유 조회수를 보장합니다. - Update View Count: Increment the view count only if the user (authenticated or not) has not already viewed the post on the same day.
조회수 업데이트: 사용자(인증 여부와 상관없이)가 같은 날 게시물을 아직 조회하지 않은 경우에만 조회수를 늘립니다. - Display View Count: Fetch and display the unique view count along with the post details.
조회수 표시: 게시물 세부정보와 함께 고유 조회수를 가져와 표시합니다.
This approach ensures that the view count accurately reflects the number of unique users who have viewed the post on a given day, regardless of whether they are authenticated or not.
이 접근 방식을 사용하면 인증 여부에 관계없이 특정 날짜에 게시물을 본 고유 사용자 수가 조회수에 정확하게 반영됩니다.
'PWA' 카테고리의 다른 글
ChatGPT와 함께 PWA Blog 개발 - 댓글 (0) | 2024.08.23 |
---|---|
ChatGPT와 함께 PWA Blog 개발 - 조회수 구현 (0) | 2024.08.22 |
ChatGPT와 함께 PWA Blog 개발 - 리스트에 글쓴이 (0) | 2024.08.21 |
ChatGPT와 함께 PWA Blog 개발 - 글쓴이 (0) | 2024.08.21 |
ChatGPT와 함께 PWA Blog 개발 - 글 상세보기 HTML (0) | 2024.08.16 |