Next.js - MongoDB에서 데이터 가져오기

지은·2023년 5월 12일
0

NEXT.js

목록 보기
5/6

이제 홈 화면에서 더미 데이터가 아닌 MongoDB 데이터베이스에 있는 데이터들을 가져와서 보여주도록 하자.

이 작업 또한 새로운 API 라우트를 생성하고 handler 함수를 작성하여, API를 이용해 데이터를 fetch해오도록 할 수 있지만.. 이 방식은 불필요한 요청을 보내는 방식이다.
따라서 API 경로를 생성하고 요청을 보낼 필요 없이 그냥 getStaticProps() 함수 내에서 바로 데이터베이스에 연결하고, 데이터를 가져오는 코드를 작성하도록 한다.

// pages/index.js
import MeetupList from '../components/meetups/MeetupList';

function HomePage(props) {
	return <MeetupList meetups={props.meetups} />;
}

export async function getStaticProps() {
	
    // fetch('/api/meetups')... ❌
  
	return {
		props: {
			meetups: DUMMY_MEETUPS, // 더미 데이터
		},
	};
}

export default HomePage;

컬렉션의 모든 문서 가져오기

new-meetup 페이지에서 했던 같은 방식으로 MongoDB 데이터베이스와 연결하고, meetupCollection을 가져온다.

find() 메소드를 이용해 해당 컬렉션 안에 있는 모든 문서들을 가져올 수 있으며, toArray() 메소드로 배열 형태로 변환할 수 있다.

MongoDB의 각 문서들은 MongoDB에서 자체적으로 부여한 유니크한 값인 _id 필드를 가지게 되는데, 이 값은 ObjectId라는 특수한 객체로 표현된다. 따라서 toString() 메소드를 이용해 문자열로 변환해 사용해야 한다.

import MeetupList from '../components/meetups/MeetupList';
import { MongoClient } from 'mongodb';

function HomePage(props) {
	return <MeetupList meetups={props.meetups} />;
}

export async function getStaticProps() {
	const client = await MongoClient.connect('mongodb+srv://janechun22:janechun22@cluster0.jrwnfs4.mongodb.net/?retryWrites=true&w=majority');
	const db = client.db();
	const meetupCollection = db.collection('meetups');

	const meetups = await meetupCollection.find().toArray();

	client.close();

	return {
		props: {
			meetups: meetups.map((meetup) => ({
				id: meetup._id.toString(), // 문자열로 변환
				title: meetup.title,
				address: meetup.address,
				image: meetup.image,
			})),
		},
	};
}

export default HomePage;

상세 페이지

컬렉션에서 특정 필드만 불러와 getStaticPaths()의 paths로 전달하기

meet up 게시글을 클릭하면 상세 페이지로 이동하게 된다.
이때 /id 경로로 이동되도록 하고, 상세 페이지에서는 params로 얻어온 id를 이용해 해당 id를 가진 값을 컬렉션에서 찾아 해당 문서 1개만 불러오도록 해보자.

getStaticPaths() 함수 내에서도 MongoDB에서 컬렉션을 불러오고 find() 메소드를 이용해 컬렉션 안의 문서를 불러올 수 있다.
이때, find() 메소드 안에 매개변수를 전달하여 컬렉션 안의 문서를 원하는 방식으로 필터링하여 불러올 수 있다.

아래 코드에서는 meetupCollection 컬렉션 안의 모든 문서를 가져오는데, 가져오는 문서들은 _id 필드만 포함하도록 필터링한다.

import React from 'react';
import MeetupDetail from '../../components/meetups/MeetupDetail';
import { MongoClient, ObjectId } from 'mongodb';

function MeetupDetails(props) {
	return (
		<MeetupDetail
			// ...
		/>
	);
}

export async function getStaticPaths() {
	const client = await MongoClient.connect('mongodb+srv://janechun22:janechun22@cluster0.jrwnfs4.mongodb.net/?retryWrites=true&w=majority');
	const db = client.db();
	const meetupCollection = db.collection('meetups');

	const meetups = await meetupCollection.find({}, { _id: 1 }).toArray();
    // {} ➡️ 필터 X, 모든 문서 불러옴
    // {_id: 1} ➡️ _id 필드만 가져온다.

	client.close();

	return {
		fallback: false,
		paths: meetups.map((meetup) => ({ // id만 담고있는 meetups를 paths 형태에 맞게 가공해야 한다.
			params: {
				meetupId: meetup._id.toString(),
			},
		})),
	};
}

params로 받아온 값으로 컬렉션에서 특정 문서 가져오기

findOne() 메소드를 이용해 컬렉션에서 문서 1개를 가져올 수 있다.
_id 필드가 params에서 받아온 meetupId와 일치하는 조건은 아래처럼 입력하면 된다.
이때 문자열을 ObjectId 객체로 바꿔줘야 하므로 new ObjectId()를 사용해야 한다.

export async function getStaticProps(context) {
	const meetupId = context.params.meetupId; // params에서 받아온 meetupId

	const client = await MongoClient.connect('mongodb+srv://janechun22:janechun22@cluster0.jrwnfs4.mongodb.net/?retryWrites=true&w=majority');
	const db = client.db();
	const meetupCollection = db.collection('meetups');

	const selectedMeetup = await meetupCollection.findOne({ _id: new ObjectId(meetupId) }); //

	return {
		props: {
			meetupData: {
				id: selectedMeetup._id.toString(),
				title: selectedMeetup.title,
				image: selectedMeetup.image,
				description: selectedMeetup.description,
			},
		},
	};
}

export default MeetupDetails;
profile
블로그 이전 -> https://janechun.tistory.com

5개의 댓글

comment-user-thumbnail
2023년 5월 12일

고생하셨습니다 혼자서 하시는건가요? 대단합니다 ㅎㅎ

1개의 답글
comment-user-thumbnail
2023년 5월 14일

몽고 DB는 처음 봐서 어렵네요. getStaticPaths는 알고있었는데 사용법 보고 이렇게 사용하구나~ 알고 갑니당

답글 달기
comment-user-thumbnail
2023년 5월 14일

저도 이번에 몽고 디비 써봤는데 잘 보고 갑니닷 !

답글 달기
comment-user-thumbnail
2023년 5월 14일

헉스 백엔드도 공부하시는 건가요 !!

답글 달기