next.js를 급하게 사용해야하는 상황이 생겼다 !
next.js는 사용해보진 않았는데, pages폴더 안의 파일 이름으로 라우팅이 되고, react의 프레임워크다 보니 코드를 짜는 방법은 react와 크게 다르지 않다는 정도만 알고 next로 프로젝트를 만들어 나가기 시작했다.
대부분의 프로젝트를 react를 사용해 만들어서인지 next를 처음 적용해 보아도 그렇게 어렵다는 생각이 들지 않았고, 오히려 react-router-dom을 사용하지 않아서 더 간편하다는 생각이 들기도 했다!
react처럼 컴포넌트를 만들어 페이지를 만들고 data를 fetching하는데 에러가 발생했다!
react에서 하던 것처럼 fetching을해서 컴포넌트로 넘겼는데 promise형식으로 넘어오는 것이었다!
react에서 되던것이 next에선 되지 않아써 찾아보다가 next는 서버사이드 렌더링을해 preRendering을 지원하기 때문에 Data fetching에서 문제가 발생하게 된 것이었다!
next.js에서는 data fetching을 위해 getStaticProps와 getServerSideProps라는 함수가 존재하는데, pages안의 폴더에서 함수를 export하면 data를 fetching 할 수 있다고 한다.
getStaticProps는 함수명에서 알 수 있듯이 정적으로 데이터를 받아온다. 즉, 빌드할 때에 데이터를 가져오는 것이다. 동적 라우팅이 필요하지 않은 곳에서 데이터를 받아올 때 유용해 보였다.
export async function getStaticProps() {
const client = await MongoClient.connect(
`mongodb+srv://sojeong:${process.env.NEXT_PUBLIC_PASSWORD}@cluster0.ujbdnkg.mongodb.net/meetups?retryWrites=true&w=majority`
);
const db = client.db();
const meetupsCollection = db.collection("meetups");
const meetups = await meetupsCollection.find().toArray();
client.close();
return {
props: {
meetups: meetups.map((meetup) => ({
title: meetup.title,
address: meetup.address,
image: meetup.image,
id: meetup._id.toString(),
})),
},
revalidate: 3600,
};
}
이 부분 코드는 next.js 데이터 패칭 관련 강의를 듣다가 mongodb에서 데이터를 받아오는 부분을 가져와 보았다!
(여담이지만 next에서는 index.js에 있는 함수들은 빌드에만 사용되어서 client에서는 api키들을 볼 수 없게 보안이 된다고 한다! 하지만 나는 깃헙에 올리고 싶으니까 .env파일로 키를 관리해주었다!)
이렇게 받아온 데이터는 페이지 컴포넌트 내에서 props.meetups.title이런식으로 꺼내서 사용할 수 있다!
return의 revalidate는 만약 주기적으로 업데이트되어야하는 데이터라면 그 업데이트 주기를 설정할 수 있다고 한다.
또 다른 활용법으로는 파라미터를 받는 것이있다.
export async function getStaticProps(context) {
//fetch data for a single meetups
const meetupId = context.params.meetupId;
const client = await MongoClient.connect(
`mongodb+srv://sojeong:${process.env.NEXT_PUBLIC_PASSWORD}@cluster0.ujbdnkg.mongodb.net/meetups?retryWrites=true&w=majority`
);
const db = client.db();
const meetupsCollection = db.collection("meetups");
const selectedMeetups = await meetupsCollection.findOne({
_id: ObjectId(meetupId),
});
client.close();
return {
props: {
meetupData: {
id: selectedMeetups._id.toString(),
title: selectedMeetups.title,
address: selectedMeetups.address,
image: selectedMeetups.image,
description: selectedMeetups.description,
},
},
};
}
이렇게 파라미터를 받아 getStaticProps 함수를 사용하면 const meetupId = context.params.meetupId;
이 부분에서 동적 라우팅 url을 파싱해서 [id].jsx파일에서 각 id의 데이터를 받아올 수 있다.
받아온 데이터는 역시 props.meetupData.id이렇게 페이지 컴포넌트 안에서 활용할 수 있다.
getStaticPaths는 동적라우팅에서 getStaticProps를 사용할 때, 어떤 경로(ex. id값이 1번)를 미리 정적으로 생성할지 정할때 필요한 함수이다. 즉, 반드시 getStaticProps와 함께 사용해야하며, page파일이 아닌 곳에서는 사용하지 못한다.
export async function getStaticPaths() {
const client = await MongoClient.connect(
`mongodb+srv://sojeong:${process.env.NEXT_PUBLIC_PASSWORD}@cluster0.ujbdnkg.mongodb.net/meetups?retryWrites=true&w=majority`
);
const db = client.db();
const meetupsCollection = db.collection("meetups");
const meetups = await meetupsCollection.find({}, { _id: 1 }).toArray();
client.close();
return {
fallback: 'blocking',
paths: meetups.map((meetup) => ({
params: { meetupId: meetup._id.toString() },
})),
};
}
getStaticPaths를 사용할 때에는 return값에 fallback을 반드시 적어줘야한다. false | true | 'blocking' 을 값으로 가질 수 있는데,
fallback: false
: getStaticPaths에서 리턴하지 않은 페이지는 모두 404로 연결!
fallback: true
: 404 페이지로 연결되지 않고, 로딩페이지를 보여준다!
fallback: 'blocking'
: getStaticPaths에서 return하지 않은 페이지에 접속 시, 사용자에게 빌드시 getStaticProps로 받아온 static 페이지를 보여주기!
getServerSideProps는 사용자가 데이터를 요청하면 데이터를 불러와야할 때 사용하는 함수이다. 로그인이나 지도상의 위치 정보를 불러올때 유용하게 사용할 수 있다고 한다.
이렇게 받아온 데이터 역시 해당 페이지 안에서 props를 통해 컴포넌트 내에서 활용할 수 있었다!
next를 급하게 적용한 프로젝트는 무사히 제출하였지만.... 구글 메일의 오류로 3통이나 제출메일이 전송되어 팡인이 된것만 같은...쥬륵... 제출하고나니 좀 더 개선해야할 부분이 보이기 시작해 아쉬움이 많이 남은 과제였다...ㅠㅜ