티스토리 뷰

Web/nextjs

[nextjs] mongodb 연결

HAN_PY 2022. 9. 30. 00:09
반응형

mongodb를 nextjs에 연결을 해보자. 연결하는 방법은 여러가지가 있다. 오늘은 mongoose를 활용하여 필요한 위치에서 SSR을 활용하여 바로 사용하는 방법에 대해 알아보자. nextjs는 아래와 같은 명령어를 통해서 만들었다.

$ npx create-next-app@latest

 

기본적으로 mongoDB 설치는 되어 있다 가정하고 nextjs 로직위주로 설명하겠다. 개인적으로 docker로 실행하면 편하다. 

 

도커(Docker) 기초 정리

 

 

 

1. mongoose 설치하기

아래의 명령어를 통해서 mongoose를 설치한다. mongoose를 사용하는 이유는 schema를 지정할 수 있기 때문이다. 사실 mongodb는 관계형 db가 아니기 때문에 아무꺼나 넣으면 막들어간다. 이러한 문제를 schema 지정을 통해 어느정도 해결이 가능하다.

$ npm install mongoose

 

 

 

2. mongoose 연결하기

여기서는 페이지마다 필요한 위치에서 SSR을 통해서 DB연결을 하고 데이터를 가지고 올 것이다. 물론 _app.js에서 한번만 mongodb를 연결하고 사용하는 방법이 있자만, 이는 Nextjs에서 자동으로 static generation을 최적화를 못하게 하고 전부 SSR로만 렌더되게하는 치명적인 문제점이 있어서 우리는 아래와 같은 방식을 통해서 DB 연동을 진행하려 한다. 

 

위와 같이 파일을 만들어주자. dbConnect.js에는 아래의 code를 넣어준다.

 

import mongoose from 'mongoose'

const connection = {} 

async function dbConnect() {
  if (connection.isConnected) {
    return
  }

  const db = await mongoose.connect(process.env.MONGODB_URI)
  connection.isConnected = db.connections[0].readyState
}

export default dbConnect

 

간단히 설명을 하면, connection.isConnected 부분은 연결이 되어 있다면, 재연결을 하지 않는 코드라고 할 수 있다. 그리고 connection은 {} 객체로 이루어져 있는데, 이는 다른 mongodb url도 연결이 가능함을 알 수 있다. 관련 부분은 다른 글에서 다루겠다.

 

process.env 관련 내용은 다룰 내용이 많기 때문에 아래의 내용에서 참고하고 오자.

 

[nextjs] 실무 개발 환경/배포 환경 설정(.env)

 

 

3. schema 만들기

import mongoose from 'mongoose'

const ItemSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Please provide a name for this pet.'],
    maxlength: [20, 'Name cannot be more than 60 characters'],
  },
  owner_name: {
    type: String,
    required: [true, "Please provide the pet owner's name"],
    maxlength: [20, "Owner's Name cannot be more than 60 characters"],
  },
  species: {
    type: String,
    required: [true, 'Please specify the species of your pet.'],
    maxlength: [30, 'Species specified cannot be more than 40 characters'],
  },
  age: {
    type: Number,
  },
  poddy_trained: {
    type: Boolean,
  },
  diet: {
    type: Array,
  },
  image_url: {
    required: [true, 'Please provide an image url for this pet.'],
    type: String,
  },
  likes: {
    type: Array,
  },
  dislikes: {
    type: Array,
  },
})

export default mongoose.models.Item || mongoose.model('item', ItemSchema)

 

필요한 컬럼들을 넣어주고, 관련 속성값들을 넣어주면된다. type에는 들어갈 타입을 넣어주면되고, required에는 필수값인지 아닌지를 넣어주면된다. 관련부분은 다른 자료에서도 많이 다루기 때문에 생략하겠다. 

 

mongoose.models.Item || mongoose.model('item', ItemSchema) 이 부분도 중복해서 mongoose models 객체를 만들지 않기 위한 장치라고 생각하면 좋을 것 같다. 넣어주는 위치는 아래와 같다. 폴더는 정답은 없으니 알아서 적절한 곳에 넣어주면 좋을 것 같다.

 

 

4. page 에서 사용하기

간단히 사용법만 넣기 위해 Board라는 component를 만들었다. 코드는 아래와 같다.

import dbConnect from "../../utils/db/dbConnect"
import Item from "../../utils/db/schemas/Item"


const Board = ({items}) => {
  return (
   <>
    {items.map((item) => (
      <div key={item._id}>
        <img src={item.image_url} />
        <h5 className="item-name">{item.name}</h5>
        <div>
          <p className="item-name">{item.name}</p>
          <p className="owner">Owner: {item.owner_name}</p>
        </div>
        <div>
          <p className="label">Likes</p>
          <ul>
            {item.likes.map((data, index) => (
              <li key={index}>{data} </li>
            ))}
          </ul>
        </div>
        <div>
          <p className="label">Dislikes</p>
          <ul>
            {item.dislikes.map((data, index) => (
              <li key={index}>{data} </li>
            ))}
          </ul>
        </div>
      </div>
    ))}
   </>
  )
}


export async function getServerSideProps() {
    await dbConnect()
    const result = await Item.find({})
    const items = result.map((doc) => {
      const item = doc.toObject()
      item._id = item._id.toString()
      return item
    })
  
    return { props: { items: items } }
  }

  export default Board;

위의 코드에서 핵심만 말해보면, getServerSideProps를 통해 SSR에서 DB 조회를 진행한다. 그리고 _id값을 가지고 가서 map 을 통한 key로 사용하는 것을 확인 할 수 있다. 

 

위와 같은 방법을 통해 확장해서 schema를 사용할수 있다. 이제 필요한 페이지에서 구현을 시작해 보자.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함