Develop/NEXT
[Next.js] 게시판 만들기(7) 댓글 기능 구현하기 feat.mongoDB
임성장
2023. 8. 15. 10:52
728x90
해당 내용은 코딩애플의 Next.js 강의 내용을 기반으로 하고 있다는 것을 알려드립니다.
핵심 로직
- 댓글 기능 UI 만들기
- 전송 버튼 누르면 댓글 데이터 서버에 전송하기
- 받은 데이터 서버에서 확인하고 DB에 댓글 저장하기
- 서버에 댓글 데이터 요청하기
- DB에서 댓글 데이터 가져와서 출력하기
댓글 기능 UI 만들기
Hint & Idea
- 클라이언트 컴포넌트 사용하기
- useState 사용하기
⬇정답 보기⬇
더보기
"use client";
import { useState } from "react";
export default function Comment() {
const [comment, setComment] = useState("")
return(
<input type="text" value={comment} onChange={(e)=>{
setComment(e.target.value)
}}/>
)
}
전송 버튼 누르면 댓글 데이터 서버에 전송하기
Hint & Idea
- button 태그를 활용해서 전송 버튼 만들기
- fetch를 통해 서버에 댓글 데이터 보내주기
- fetch를 통해 서버에 어떤 글의 댓글인지 알 수 있는 데이터 보내주기
⬇정답 보기⬇
더보기
"use client";
import { useParams } from "next/navigation";
import { useState } from "react";
export default function Comment() {
const [comment, setComment] = useState("")
// URL에 나와있는 해당 글의 ID 값을 가져오기 위해 사용
const params = useParams()
return(
<input type="text" value={comment} onChange={(e)=>{
setComment(e.target.value)
}}/>
<button onClick={()=>{
// 데이터 전송하기 때문에 method는 POST,
// body에는 댓글 내용과 어느 글의 댓글인지 알 수 있게 부모 글의 ID를 담는다.
fetch('서버 URL', {
method: 'POST',
body: JSON.stringify({comment, params})
})
setComment('')
}}>댓글 전송</button>
)
}
받은 데이터 서버에서 확인하고 DB에 댓글 저장하기
Hint & Idea
- button 태그를 활용해서 전송 버튼 만들기
- fetch를 통해 서버에 댓글 데이터 보내주기
- fetch를 통해 서버에 어떤 글의 댓글인지 알 수 있는 데이터 보내주기
⬇정답 보기⬇
더보기
import { connectDB } from "@/util/database";
import { getServerSession } from "next-auth";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { ObjectId } from "mongodb";
export default async function handler(req, res) {
if (req.method == "POST") {
// JSON 데이터를 객체로 변환
const { comment, params } = JSON.parse(req.body);
// 현재 로그인되어 있는 유저 정보 가져오기
let session = await getServerSession(req, res, authOptions);
if (comment) {
const db = (await connectDB).db("DB 이름");
// 댓글 작성자, 댓글 내용, 부모 글의 ID를 DB에 저장
db.collection("컬렉션 이름").insertOne({
author: session.user.email,
comment,
// DB에 저장되는 형식을 맞추기 위해 ObjectID 사용
parent: new ObjectId(params.id),
});
return res.status(200).json("저장 완료");
} else {
return res.status(500).json("댓글을 입력해주세요");
}
}
서버에 댓글 데이터 요청하기
Hint & Idea
- useEffect 사용하여 서버에 요청하기
- fetch()로 get 요청하기
- state에 받아온 데이터 저장하기
⬇정답 보기⬇
더보기
"use client";
import { useEffect, useState } from "react";
export default function Comment() {
// 서버로부터 가져온 댓글 데이터를 저장
const [allComment, setAllComment] = useState([]);
// 컴포넌트가 처음 마운트될 때와 댓글 데이터가 추가되면 컴포넌트가 다시 마운트됨.
// fetch를 사용해서 새로고침 없이 서버와 통신 가능
useEffect(() => {
// GET 요청을 처리하는 함수
const fetchComments = async () => {
try {
// query string을 통해 부모글의 ID 서버에 전달
const response = await fetch(`/api/comment?id=${params.id}`);
} catch (error) {
console.error("댓글 데이터를 가져오는 중 오류 발생:", error);
}
};
// 컴포넌트가 마운트될 때 GET 요청 실행
fetchComments();
}, [allComment]);
(생략)
}
DB에서 댓글 데이터 가져와서 출력하기
Hint & Idea
- server
- 요청의 method 확인하기
- query string으로 보낸 데이터 받기
- 부모 글의 id를 통해 DB에서 데이터 가져오기
- 가져온 데이터를 알맞는 형식으로 클라이언트 컴포넌트로 전달하기
- client
- 서버로부터 전달받은 데이터를 알맞은 형식으로 변환하기
- 변환한 데이터를 state에 저장하기
- map 함수를 통해 댓글 데이터 출력하기
⬇정답 보기⬇
더보기
import { connectDB } from "@/util/database";
import { getServerSession } from "next-auth";
import { ObjectId } from "mongodb";
export default async function handler(req, res) {
(생략)
else if (req.method == "GET") {
// query string으로 보낸 부모 글의 id 변수에 저장
const id = req.query.id;
const db = (await connectDB).db("DB 이름");
const result = await db
.collection("컬렉션 이름")
// 부모 글의 ID로 그 글의 댓글 데이터를 가져오기
.find({ parent: new ObjectId(id) })
// 배열 형태로 만들기
.toArray();
// DB에서 가져온 데이터 클라이언트 컴포넌트에 전달하기
return res.status(200).json(result);
}
}
"use client";
import { useEffect, useState } from "react";
export default function Comment() {
// 서버로부터 가져온 댓글 데이터를 저장
const [allComment, setAllComment] = useState([]);
// 컴포넌트가 처음 마운트될 때와 댓글 데이터가 추가되면 컴포넌트가 다시 마운트됨.
// fetch를 사용해서 새로고침 없이 서버와 통신 가능
useEffect(() => {
// GET 요청을 처리하는 함수
const fetchComments = async () => {
try {
// query string을 통해 부모글의 ID 서버에 전달
const response = await fetch(`/api/comment?id=${params.id}`);
// 서버로부터 받아온 데이터를 json 형식으로 저장
const data = await response.json();
// 데이터를 state에 저장
setAllComment(data);
} catch (error) {
console.error("댓글 데이터를 가져오는 중 오류 발생:", error);
}
};
// 컴포넌트가 마운트될 때 GET 요청 실행
fetchComments();
}, [allComment]);
return (
<div>
<div>
// map 함수를 활용해서 해당 글의 모든 댓글 출력하기
{allComment.map((item, idx) => (
<div key={item._id}>
<p>{item.author}</p>
<p>{item.comment}</p>
</div>
))}
</div>
(생략)
</div>
}
728x90