프론트엔드 개발자를 위한 MongoDB & Mongoose 가이드

odada·2024년 12월 25일
0

node.js

목록 보기
10/11

1. 데이터베이스가 뭔가요?

프론트엔드에서 우리는 보통 이런 형태로 데이터를 다룹니다:

const posts = [
  {
    id: 1,
    title: "첫 번째 글",
    content: "내용입니다"
  },
  {
    id: 2,
    title: "두 번째 글",
    content: "내용입니다"
  }
];

하지만 이렇게 하면 서버를 재시작할 때마다 데이터가 사라지죠. 이 데이터를 영구적으로 저장하고 관리하는 곳이 바로 '데이터베이스'입니다.

2. MongoDB는 무엇인가요?

MongoDB는 JavaScript 객체와 매우 비슷한 형태로 데이터를 저장하는 데이터베이스입니다.

React의 state와 비교

// React에서 state 사용
const [post, setPost] = useState({
  title: "제목",
  content: "내용"
});

// MongoDB에 저장된 데이터
{
  _id: "자동생성되는ID",
  title: "제목",
  content: "내용"
}

React에서 state를 사용하는 것처럼, MongoDB는 데이터를 저장하고 관리합니다. 단지 서버를 껐다 켜도 데이터가 유지된다는 점이 다릅니다!

3. Mongoose는 무엇인가요?

Mongoose는 MongoDB를 더 쉽게 사용할 수 있게 해주는 도구입니다.

PropTypes와 비교

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 }
});

4. 실제 사용 예시

4-1. 데이터베이스 연결

마치 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;

4-2. 포스트 모델 정의하기

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;

4-3. API 라우트에서 사용하기

프론트엔드에서 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 }
    );
  }
}

4-4. 프론트엔드에서 사용하기

이제 평소처럼 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]);
};

5. 정리

브라우저 → (프론트엔드 async) → 서버 → (라우트 async) → 데이터베이스
  1. MongoDB = 데이터를 저장하는 창고
  2. Mongoose = 그 창고를 더 잘 사용할 수 있게 도와주는 도구
  3. 프론트엔드 = 평소처럼 API를 호출
  4. 서버 = 이 호출을 받아서 MongoDB에 저장하거나 가져오는 작업을 수행

이제 서버를 껐다 켜도 데이터가 사라지지 않고, 여러 사용자가 같은 데이터를 공유할 수 있게 됩니다!

0개의 댓글