[Next.js] 나만의 학습 블로그 만들기 #2 - 방문자 수 측정하기(feat. Firebase)

3 min read

내용 기록 외에도 방문자 수랑 댓글 기능도 넣으려고 한다.!
이번 글에서는 방문자 수 측정 기능 구현을 적어보겠다🤭
나는 서버가 없으니 파이어베이스를 선택해줬다…!
- 파이어베이스 사이트에 들어가서 프로젝트를 생성해주고 Firestore Database를 클릭해주자
- 클릭하면 이런 화면이 나옴
- 데이터베이스 만들기를 클릭
프로덕션 모드에서 시작
- 그러면 이런 화면이 뜬다 ! 여기서 규칙을 수정해주자
기본 파이어베이스에서 제공해주는 코드를 해석해보면
→ 모든 경로에 대해 읽기와 쓰기 전부 금지! 안전하긴 하지만 아무것도 하지 못하기 때문에 수정을 해줘야한다.
📬 조회수 측정은 가능할 수 있도록
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /views/{slug} {
allow read: if true;
allow update: if
request.resource.data.keys().hasOnly(['count']) &&
request.resource.data.count is int &&
request.resource.data.count > resource.data.count;
allow create: if
request.resource.data.keys().hasOnly(['count']) &&
request.resource.data.count == 1;
}
match /{document=**} {
allow read, write: if false;
}
}
}
이렇게 수정하고 게시를 눌러줘서 반영해줬다 !
- Firebase 프로젝트 클릭하면 상단 가운데 아이콘 중
</>
(웹 앱 추가) 클릭해주고 하라는대로 해주면
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
이런 설정객체들을 알려주는데
firebase.js
폴더를 만들어줘서 넣어줬다.
import { initializeApp, getApps } from "firebase/app";
import { getAnalytics, isSupported } from "firebase/analytics";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
const app =
getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
let analytics = null;
if (typeof window !== "undefined") {
isSupported().then((yes) => {
if (yes) {
analytics = getAnalytics(app);
}
});
}
export { app };
이렇게 하면 firebase 준비는 끝났다 !!!!!
이제 vscode에서 설정해보자
incrementView.js
import { db } from "./firebase.js";
import {
collection,
getDocs,
doc,
getDoc,
setDoc,
updateDoc,
increment,
} from "firebase/firestore";
export async function incrementViewCount(slug) {
const ref = doc(db, "views", slug);
const snap = await getDoc(ref);
if (snap.exists()) {
await updateDoc(ref, {
count: increment(1),
});
} else {
await setDoc(ref, {
count: 1,
});
}
}
export async function getViewCount(slug) {
const ref = doc(db, "views", slug);
const snap = await getDoc(ref);
return snap.exists() ? snap.data().count : 0;
}
export async function getTotalViews() {
const snapshot = await getDocs(collection(db, "views"));
let total = 0;
snapshot.forEach((doc) => {
total += doc.data().count || 0;
});
return total;
}
TotalView.js
import { useEffect, useState } from "react";
import { getTotalViews } from "../../lib/incrementView";
export default function TotalView() {
const [total, setTotal] = useState(0);
useEffect(() => {
getTotalViews()
.then(setTotal)
.catch(() => setTotal(0));
}, []);
return (
<div className="text-right sm:text-sm text-xs text-gray-600 dark:text-gray-400">
조회수 | <span className="font-semibold">{total.toLocaleString()}회</span>
</div>
);
}
만든 컴포넌트를 _app.js
에 넣어줬다
이렇게 틀은 만들었고 아직 만든 페이지가 없어서 slug를 홈에만 넣어주려고 한다.
index.js
import { useEffect } from "react";
import { incrementViewCount } from "../../lib/incrementView";
export default function Home() {
useEffect(() => {
incrementViewCount("home");
}, []);
return <div className="max-w-[940px] mx-auto"></div>;
}
설정 완료 ~~~ ! 🤭
아직은 배포를 안 해서 조회수는 증가가 안되지만 기능 자체는 잘 붙여서 뿌듯하다.
역시 파이어베이스는 프엔한테 최고다…🙌🏻
0
Subscribe to my newsletter
Read articles from 송수빈 directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
