MongoDB Atlas란?
우선 MongoDB는 NoSQL 데이터베이스입니다. 간단히 말하면 MySQL같은 데이터베이스랑은 달리 테이블을 만들고 정규화 시키고 할 필요 없이 그냥 저장하고 싶은대로 저장할 수 있습니다.
MongoDB Atlas는 MongoDB 클라우드 서비스입니다. 무료로 5GB까지 사용 가능하다고 합니다. Docker로 데이터베이스 올리고 앱 실행하고 그러기 귀찮아서 냅다 가입하고 써보려고 합니다. 몽고DB 아틀라스 공식페이지는 다음 주소로 가시면 됩니다.
https://www.mongodb.com/ko-kr/atlas/database
MongoDB Atlas Database | Multi-Cloud Database Service
멀티 클라우드 데이터베이스 서비스는 애플리케이션 데이터 플랫폼의 핵심 요소로, 데이터를 사용해 빠르고 손쉽게 구축하는 데 효과적입니다. MongoDB Atlas를 지금 체험해보세요!
www.mongodb.com
MongoDB Atlas 가입해서 URI랑 password 저장하기
가입해서 DataBase를 만들면 연결할 때 필요한 URI랑 password를 줍니다. 어딘가에 잘 적어두시면 됩니다. URI 형식은 다음과 같습니다.
mongodb+srv://<username>:<password>@<clusername>.xxxxxxx.mongodb.net/<dbname>?retryWrites=true&w=majority
NextJS에 연결해서 사용해보기
.env파일에 URI 적어놓기
프로젝트 루트 디렉토리에 .env파일을 만들고 위에서 받아온 URI를 저장합니다.
# .env
MONGODB_URI="아까 받아온 URI 적어넣기"
declare global로 타입 지정하기
DB연결을 계속 시도하는것이 아니라 연결이 되면 global에 캐싱해서 사용하려고 합니다. 따라서 다음과 같이 gobal에 타입을 추가해줍니다. 타입스크립트라서 이걸 안해놓으면 계속 타입오류 발생합니다.
// @types/mongodb.ts
import { Mongoose } from "mongoose";
/* eslint-disable no-var */
declare global {
var mongoose: {
promise: Promise<Mongoose> | null;
conn: Mongoose | null;
};
}
DB에 접속하기 위한 코드
mongoose를 사용해서 몽고DB 아틀라스에 접속하는 코드를 작성해줍니다. mongoose의 set() 메서드에는 자신이 원하는 설정을 넣으면 됩니다.
// lib/db/dbConnect.ts
import mongoose from "mongoose";
const DB_URI = process.env.MONGODB_URI || "";
let cached = global.mongoose;
if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}
async function dbConnect() {
if (cached.conn) return cached.conn;
if (!cached.promise) {
cached.promise = mongoose
.set({ debug: true, strictQuery: false })
.connect(`${DB_URI}`)
.then((mongoose) => mongoose);
}
cached.conn = await cached.promise;
return cached.conn;
}
export default dbConnect;
DB Schema 생성
간단하게 Test라는 이름의 스키마를 만들어 봤습니다. 몽고DB는 기본적으로 Object ID가 기본 키로 _id에 저장이 됩니다. auto increament 키를 사용하고 싶어서 testId 라는 필드도 추가해 봤습니다.
// lib/test/test.model.ts
import mongoose, { Schema, models } from "mongoose";
export const TestSchema = new Schema({
testId: {
type: Number,
},
title: {
type: String,
required: true,
},
content: {
type: String,
required: true,
},
});
const Test = models?.Test || mongoose.model("Test", TestSchema);
export default Test;
Auto Increment 구현하기
몽고DB는 기본적으로 Auto Increment를 지원하지 않기 때문에 직접 구현해야 하는데요. 공식 홈페이지에 보면 자세한 설명이 나와있습니다. 간단히 설명하면 Counter라는 모델을 하나 만들어서 Counter 모델에다 숫자를 저장하고 그걸 불러와서 저장하는 방식입니다. 다음 자료를 보고 참고해서 만들었습니다.
https://www.mongodb.com/docs/v3.0/tutorial/create-an-auto-incrementing-field/
Create an Auto-Incrementing Sequence Field — MongoDB Manual
Navigation This version of the documentation is archived and no longer supported. Create an Auto-Incrementing Sequence Field Synopsis MongoDB reserves the _id field in the top level of all documents as a primary key. _id must be unique, and always has an i
www.mongodb.com
// lib/counter/counter.model.ts
import mongoose, { models, Schema } from "mongoose";
export const CounterSchema = new Schema({
_id: {
type: String,
required: true,
},
seq: {
type: Number,
default: 0,
},
});
const Counter = models?.Counter || mongoose.model("Counter", CounterSchema);
export async function getNextSequenceValue(sequenceName: string) {
const sequenceDocument = await Counter.findByIdAndUpdate(
sequenceName,
{ $inc: { seq: 1 } },
{ new: true, upsert: true },
);
return sequenceDocument.seq;
}
export default Counter;
NextJS API 만들기
pages/api 경로에다 test를 만들어서 벡엔드 구현을 간단하게 해줍니다.
// pages/api/test/index.ts
import type { NextApiRequest, NextApiResponse } from "next";
import Test from "../../../lib/test/test.model";
import dbConnect from "../../../lib/db/dbConnect";
import { getNextSequenceValue } from "../../../lib/counter/counter.model";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method === "GET") {
try {
dbConnect();
const tests = Test;
const allTests = await tests.find({});
res.status(200).json(allTests);
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal server error" });
}
} else if (req.method === "POST") {
try {
dbConnect();
const tests = Test;
const { title, content } = req.body;
const testId = await getNextSequenceValue("testId");
const test = new tests({ testId, title, content });
await test.save();
res.status(200).json({ message: "Test created successfully" });
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal server error" });
}
}
}
실행해보기
yarn dev로 앱을 실행해봅시다. 그리고 Postman으로 loacalhost:3000/api/test로 POST요청을 보냅니다. 밑에 응답을 보면 올바르게 저장된 것을 확인할 수 있습니다.

GET 요청을 보내보면 또한 잘 동작하는걸 확인할 수 있습니다.

MongoDB Atlas에서 확인해보기
MongoDB Atlas에 접속해서 Collection탭을 누르면 현제 데이터베이스에 저장된 값을 확인할 수 있습니다. Counter랑 Test를 확인해봅시다.


둘다 잘 저장된 것을 확인할 수 있습니다. collection 이름은 소문자에 복수형으로 들어가는 것 같습니다.
결론
NextJS 어플리케이션을 MongoDB Atlas에 연결해 보았습니다. 5GB 까지는 무료니까 잘 사용해보면 좋을 것 같습니다. mongoDB atlas search 이런 것도 있는거 같은데 나중에 한번 해봐야겠네요.