작은 도서관
article thumbnail

개요

  • 스키마와 모델
  • 스키마와 모델 구현하기
  • 라우터에서 데이터 받아오기
  • 데이터 CRUD 구현하기

스키마와 모델

DBMS에서 스키마란, 데이터베이스를 구성하는 데이터의 구조와 타입, 데이터간의 관계, 검색 방법, 속성등을 정의한 것을 뜻합니다.

모델이 바로 이런 스키마를 이용해서 만든 객체를 뜻합니다.

서버에선 모델을 통해 데이터베이스에 실제로 작업을 하게 됩니다.

스키마와 모델 구현하기

그럼 실제로 한번 구현해봅시다.

우리는 게시물을 저장하는 라우터를 구현해 두었습니다.

인터넷 게시판의 게시물을 분석해보자면, 어떤 값이 눈에 띄나요?

제목, 생성일자, 내용이 있습니다.

각각 타입으로 생각한다면 제목과 내용은 문자열, 생성일자는 Date타입이 되겠네요.

이를 코드로 한번 옮겨보겠습니다.

 

src 아래에 model이라는 폴더를 하나 생성하고, 그 안에 다시 post.js파일을 만든 뒤 다음 코드를 작성해주세요.

// ./src/model/post.js
import mongoose from "mongoose";

const postSchema = new mongoose.Schema({
  title: { type : string, required: true },
  content: { type : string, required: true },
},
{
  timestamps: true
});

module.exports = mongoose.model('Post', postSchema);

스키마 객체를 만들때는 인자로 스키마의 타입과 옵션을 받습니다.

스키마의 타입을 지정할때는 필드명과 값, 속성을 Object 형식으로 지정해줘야 하는데, 코드에서는 title의 타입을 문자열, 속성중 require(필수 여부)를 지정해주고 있습니다.

만약 필수 여부를 지정하지 않을거라면 다음과 같이 작성할수도 있습니다.

import mongoose from "mongoose";

const postSchema = new mongoose.Schema({
  title: string,
  content: string,
},
{
  timestamps: true
});

module.exports = mongoose.model('Post', postSchema);

이 경우 require의 기본값은 false입니다.

 

두 번째 인자인 스키마의 옵션을 보자면, timestamps를 사용하고 있습니다.

최종적으로, 이 모델로 데이터를 생성한다면 다음과 같은 데이터가 생성됩니다.

{
	_id: String(자동 생성됨),
	title: String,
	content: String,
	createdAt: Date(자동 생성됨),
	updatedAt: Date(자동 생성됨)
}

_id는 자동으로 생성되는 식별 아이디, createdAt과 updatedAt이 바로 timestamps를 활성화했을 때 자동으로 생성되는 생성시간, 수정시간입니다.

 

이처럼 간단하게 스키마와 모델을 구현해 보았습니다.

라우터에서 데이터 받아오기

지금까진 postman으로 api테스트를 진행할 때, 사용자로부터 값을 받아온 적은 없습니다.

값을 받아오는 방법은 두 가지가 있습니다.

  • 사용자가 body에 데이터를 주는 경우
  • URL PARAMS를 사용하는 경우

후자의 경우는 이미 받아온 경험이 있습니다. 전자를 한번 구현해봅시다.

우선, 사용자는 다음과 같은 데이터를 서버로 전송한다고 가정합니다.

{
	"title": String,
	"content": String,
}

이 데이터가 바로 req.body안에 담기게 됩니다.

// ./router/post.js

...
postRouter.post("/", (req, res) => {
  const data = req.body;
  const title = data.title;
  const content = data.content;
  res.send(title, content);
});
...

index.js 파일에선 body를 읽어올 수 있도록 설정해줘야 합니다.

코드 두 줄을 index.js파일에 추가해주세요.

import express from 'express';
import postRouter from './router/post.js';
import 'dotenv/config';
import mongoose from 'mongoose';

const app = express();
app.use(express.json())
app.use(express.urlencoded({extended:false}));

app.use("/post", postRouter);
mongoose.connect(process.env.DB_URI);

app.listen(process.env.PORT, () => {
    console.log(`server on port: ${process.env.PORT}`);
});

다시 post 요청을 보낸다면, 응답으로 title과 content를 받는것을 볼 수 있습니다.

데이터 CRUD 구현하기 - Create

편의상 라우터 파일 안에서 전부 구현하겠습니다.

먼저, 앞서 생성한 model을 불러와야 제대로된 CRUD를 구현할 수 있겠죠?

Create 먼저 구현해보겠습니다.

import Post from '../model/post'

...
postRouter.post("/", async (req, res) => {
  const data = req.body;
  console.log(data);
  const title = data.title;
  const content = data.content;
  const post = new Post({
    title: title,
    content: content,
  })
  await post.save();
  res.send("데이터가 생성되었습니다.");
});	
...

새 Post 객체를 만든 다음, 필요한 값을 넣고 save()메서드를 사용하면 구현할 수 있습니다.

이때, save는 promise를 반환하기 때문에 async-await을 사용해야 동기적으로 처리할 수 있습니다.

테스트를 위해 서버를 켜고, Postman을 열어봅시다.

요청으로 "데이터가 생성되었습니다."를 받으면 성공입니다.

MongoDB Cluster를 확인해볼까요?

잘 저장되었네요.

 

데이터 CRUD 구현하기 - Read

다음으로, 데이터 조회를 구현해봅시다.

데이터 조회는 두 가지가 있는데, 모든 데이터 조회와 특정 데이터 조회가 있습니다.

모든 데이터를 조회할 때는 데이터에 대한 정보가 필요 없지만, 특정 데이터를 조회할땐 글의 id가 필요하겠죠?

...
postRouter.get("/", (req, res) => {
  
});

postRouter.get("/:id", (req, res) => {
  
});
...

그러므로 라우터 두 개를 준비합니다.

postRouter.get("/", async (req, res) => {
  const data = await Post.find();
  res.send(data);
});

postRouter.get("/:id", async (req, res) => {
  const data = await Post.findById(req.params.id);
  res.send(data);
});

사용하는 메서드만 다른것을 볼 수 있습니다.

역시 Promise를 반환하기 때문에, 비동기 처리를 해줍니다.

 

전체 조회 테스트입니다. 배열로 응답받으며, 글이 더 늘어난다고 해도 한번에 조회할 수 있습니다.

저 _id 필드를 복사해서 url 뒤에 붙여넣어봅시다.

이번엔 배열이 아니라, 단 하나의 객체를 응답으로 받습니다.

 

데이터 CRUD 구현하기 - Update

업데이트는 조금 이질적입니다.

수정해야하는 데이터의 id를 params로 받으며, 수정해야하는 값은 request.body로 받습니다.

postRouter.patch("/:id", async (req, res) => {
  const data = await Post.findByIdAndUpdate(req.params.id, req.body);
  res.send(data);
});

이번엔 findByIdAndUpdate(해당 모델에서 Id로 검색한 후 수정) 메서드를 사용합니다.

이 메서드는 두번째 인자로 업데이트할 값을 받습니다.

테스트를 해보면 이렇습니다. 응답으로 원래 있던 데이터가 나오네요.

실제 데이터는 잘 바뀌었습니다.

 

데이터 CRUD 구현하기 - Delete

postRouter.delete("/:id", async (req, res) => {
  const data = await Post.findByIdAndDelete(req.params.id);
  res.send(data);
});

이번엔 findByIdAndDelete 메서드를 사용합니다.

원래 있던 데이터를 응답으로 받고, 실제 데이터는 삭제됩니다.

이것으로 게시물에 대한 CRUD는 완성되었습니다.

profile

작은 도서관

@Flrea

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!