api
라는 이름으로 폴더를 만들어야 한다.import {MongoClient} from "mongodb";
async function handler(req, res) {
if(req.method === "POST"){
const data = req.body;
const client = await MongoClient.connect("몽고db에서 제공하는 url")
const db = client.db();
const meetupsCollection = db.collection("콜렉션이름");
const result = await meetupsCollection.insertOne(data);
console.log(result);
client.close();
res.status(201).json({messge:"성공적으로 삽입됨"});
}
}
export default handler();
const router = useRouter();
async function addMeetupHandler(enteredMeetupData) {
const response = await fetch("/api/new-meetup",{ // 1.
method:"POST",
body: JSON.stringify(enteredMeetupData),
headers:{
"Content-Type":"application/json"
}
});
const data = await response.json();
router.replace("/");
}
return(
<NewMeetupForm onAddMeetup={addMeetupHandler}/> // 2.
)
API 폴더에 있는 new-meetup js 파일로 request가 전송되고 여기의 function을 trigger 한다.
그리고 request가 경로에 도달하면 NextJS가 이 function을 trigger 한다.
NewMeetupForm에 있는 form에 맞춰 stringfy 하여 data를 따로 구조분해 없이 보내도 된다. 왜냐면 몽고DB는 기본적으로 JSON통신을 하니까
export async function getStaticProps() {
const data = fetch("/api/meetups")
//fetch data from an API first then
return {
props:{
meetups: data,
},
revalidate:3
};
}
이런식으로 fetch에서 가져온 data를 사용하면 얼마나 편할까 하지만 이는 API의 endpoint에 request를 보내는 것은 불필요하고 중복될 수도 있기 때문에 좋은 코드는 아니다.
또한 getStaticProps함수 자체도 build 프로세스 때 실행되므로 클라이언트 사이드에서는 실행이 되지 않는다.
따라서 모든 data를 불러오려면 API 경로에 request를 보낼 필요가 없고 바로 여기서 코드를 실행해야 한다는 것이다.
그렇다면 드는 의문=> fetch에 어려 DB의 보안 정보들이 들어있는데 이를 클라이언트 사이드에서 실행하면 보안적으로 괜찮을 걸까?
아주 훌륭한 질문이다.
페이지 구성 요소 파일에서 항목을 import 하면 해당 import 항목은 getServerSide Props나 getStaticProps에서만 사용되는 경우 import 된 패키지는 클라이언트 측 번들에 포함되지 않는다. 이게 어떻게 가능할까?
NextJS가 이를 감지하여 클라이언트 측 번들에 포함시키지 않기 때문에 번들 크기뿐만 아니라 보안에도 유용하다!
즉, 서버 측 코드와 클라이언트 측 코드를 모두 import 할 수 있고 사용하는 위치에 따라 서로 독립적인 다른 번들에 포함 된다. NextJS에 내장된 아주 훌륭한 기능이다.
export async function getStaticProps() {
const client = await MongoClient.connect("몽고DBURL")
const db = client.db();
const meetupsCollection = db.collection("콜렉션이름");
const meetupsAry = await meetupsCollection.find().toArray();
client.close();
return {
props:{
meetups: meetupsAry.map(meetup=>({
title:meetup.title,
address:meetup.address,
image:meetup.image,
id:meetup._id.toString()
})),
},
revalidate:3
};
}
항상 주의해야할 점은 fetch 처럼 DB에서 값을 가져올 때 비동기로 처리하고 이때 반드시 await으로 promise 해주어야 한다!
export async function getStaticProps(context) {
const meetupId = context.params.meetupId;
const client = await MongoClient.connect("몽고DBURL")
const db = client.db();
const meetupsCollection = db.collection("콜렉션이름");
const selectedMeetup = await meetupsCollection.findOne({ _id: ObjectId(meetupId) });
client.close();
return {
props: {
meetupData: {
id: selectedMeetup._id.toString(),
title: selectedMeetup.title,
address: selectedMeetup.address,
image: selectedMeetup.image,
description: selectedMeetup.description
}
}
}
}