프론트엔드에서 우리는 보통 이런 형태로 데이터를 다룹니다:
const posts = [
{
id: 1,
title: "첫 번째 글",
content: "내용입니다"
},
{
id: 2,
title: "두 번째 글",
content: "내용입니다"
}
];
하지만 이렇게 하면 서버를 재시작할 때마다 데이터가 사라지죠. 이 데이터를 영구적으로 저장하고 관리하는 곳이 바로 '데이터베이스'입니다.
MongoDB는 JavaScript 객체와 매우 비슷한 형태로 데이터를 저장하는 데이터베이스입니다.
// React에서 state 사용
const [post, setPost] = useState({
title: "제목",
content: "내용"
});
// MongoDB에 저장된 데이터
{
_id: "자동생성되는ID",
title: "제목",
content: "내용"
}
React에서 state를 사용하는 것처럼, MongoDB는 데이터를 저장하고 관리합니다. 단지 서버를 껐다 켜도 데이터가 유지된다는 점이 다릅니다!
Mongoose는 MongoDB를 더 쉽게 사용할 수 있게 해주는 도구입니다.
React에서 props의 타입을 체크하기 위해 PropTypes를 사용하듯이, Mongoose는 데이터의 형태를 미리 정의하고 체크합니다.
// React PropTypes
Post.propTypes = {
title: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
views: PropTypes.number
};
// Mongoose Schema
const postSchema = new mongoose.Schema({
title: { type: String, required: true },
content: { type: String, required: true },
views: { type: Number, default: 0 }
});
마치 React에서 context를 설정하는 것처럼, 데이터베이스 연결을 설정합니다
환경 변수 파일에 MongoDB URI를 추가합니다:
// .env
MONGODB_URI=mongodb+srv://<username>:<password>@cluster0.xxxxx.mongodb.net/<database>?retryWrites=true&w=majority
연결 유틸리티 함수를 작성합니다:
// src/lib/mongodb.js
import mongoose from 'mongoose';
async function connectDB() {
// MongoDB에 연결
await mongoose.connect(process.env.MONGODB_URI);
}
export default connectDB;
React 컴포넌트를 만드는 것처럼, 데이터의 형태를 정의합니다:
// models/Post.js
import mongoose from 'mongoose';
// 데이터 형태 정의 (마치 interface나 type 정의하듯이)
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true // 필수값 (props의 isRequired와 비슷)
},
content: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now // 기본값 설정
}
});
// 모델 생성 (마치 컴포넌트를 export 하듯이)
// 이미 생성된 모델이 있다면 재사용
const Post = mongoose.models.Post || mongoose.model('Post', postSchema);
export default Post;
프론트엔드에서 axios로 API를 호출하면, 이렇게 처리합니다:
// app/api/posts/route.js
import { NextResponse } from 'next/server';
import connectDB from '@/lib/mongodb';
import Post from '@/models/Post';
// GET 요청 처리 (/api/posts)
export async function GET() {
try {
// 1. 데이터베이스 연결
await connectDB();
// 2. 전체 게시글 가져오기 (마치 setState 하듯이)
// sort()로 최신 게시글부터 가져오기
const posts = await Post.find().sort({ createdAt: -1 });
// 3. 클라이언트에 데이터 반환
return NextResponse.json(posts);
} catch (error) {
return NextResponse.json(
{ error: '게시글을 불러오는데 실패했습니다.' },
{ status: 500 }
);
}
}
// POST 요청 처리 (/api/posts)
export async function POST(req) {
try {
// 1. 데이터베이스 연결
await connectDB();
// 2. 클라이언트가 보낸 데이터 가져오기
const data = await req.json();
// 3. 새 게시글 생성 (마치 setState 하듯이)
const post = await Post.create(data);
// 4. 생성된 게시글 반환
return NextResponse.json(post, { status: 201 });
} catch (error) {
return NextResponse.json(
{ error: '게시글 작성에 실패했습니다.' },
{ status: 500 }
);
}
}
이제 평소처럼 axios로 API를 호출하면 됩니다:
// pages/posts.js
import axios from 'axios';
// 게시글 목록 가져오기
const fetchPosts = async () => {
const { data } = await axios.get('/api/posts');
setPosts(data);
};
// 새 게시글 작성하기
const createPost = async (postData) => {
const { data } = await axios.post('/api/posts', postData);
setPosts(prev => [...prev, data]);
};
브라우저 → (프론트엔드 async) → 서버 → (라우트 async) → 데이터베이스
이제 서버를 껐다 켜도 데이터가 사라지지 않고, 여러 사용자가 같은 데이터를 공유할 수 있게 됩니다!