목표
1. 할 일 메모 사이트의 Create, Read 기능을 구현한다.
2. 데이터 유효성 검사 기능에 대해 알아보고, 해당 기능을 추가한다.
01. [할 일 메모 사이트] - Create, Read 구현하기
1) [할 일 메모 사이트] - Create, Read API 정리하기
Method | URL | Request | Response | |
할일 | POST | /api/todos/ | { "value":"제로 콜라 500ml 구매하기" } | { "todo": { "value": "제로 콜라 500ml 구매하기", "order": 1, "_id": "64bd3e6a8f9c069e092ee5c4", "__v": 0, "todoId": "64bd3e6a8f9c069e092ee5c4", "id": "64bd3e6a8f9c069e092ee5c4" } } |
할일 목록 조회 | GET | /api/todos/ | { } //추가옵션설정X //전달데이터X |
{ "todos": [ { "_id": "64bd3e6a8f9c069e092ee5c4", "value": "제로 콜라 500ml 구매하기", "order": 1, "__v": 0, "todoId": "64bd3e6a8f9c069e092ee5c4", "id": "64bd3e6a8f9c069e092ee5c4" } ] } |
2) 할 일 Router(라우터) 추가하기
할 일 메모 사이트의 API를 구현하기 위해서는, 해야할 일의 기능을 사용하는 라우터(Router)를 생성하고, app.js 파일에서 해당하는 Router를 등록해야합니다.
여기서, 라우터(Router)란, 여러 가지 경로(route)를 관리하는 모듈이라고 생각하세요
/routes/todos.router.js 파일을 생성한 후, 아래의 코드스니펫을 복사해주세요!
// /routes/todos.router.js
import express from 'express';
const router = express.Router();
export default router;
app.js의 전역 미들웨어에 생성한 Router를 연결
app.js에 라우터를 가져오고 사용하는 코드 추가하기
import todosRouter from "./routes/todos.router.js";
// api 주소로 접근하였을 때, router와 TodosRouter로 클라이언트의 요청이 전달됩니다.
app.use("/api", [router, todosRouter]);
3) 할 일 등록 API 만들기
힐일 등록 API 만들기 -> 할일 조회 API 만들기 -> API 구현
order는 ‘해야할 일’ 데이터가 생성될 때마다 순서를 가질 수 있게 만들어주는 필드에요. 즉, 가장 최근에 추가된 ‘해야할 일’은 order값이 높을 것이고, order값이 높은 데이터는 할 일 목록의 상단에 위치하게 될 것입니다.
이번에는 클라이언트에게 전달받은 데이터를 MongoDB에 저장하는 API를 구현해보도록 하겠습니다
할 일 추가 API, routes/todos.router.js
// /routes/todos.router.js
import express from "express";
import Todo from "../schemas/todo.schema.js";
// 라우터 생성
const router = express.Router();
/** 할일등록 API **/
// 할일 등록은 .post메소드 사용
// URL : /todos
// DB사용하려면 async, 즉 비동기 함수를 사용해야 합니다. 데이터를 조회할 동안 프로그램이 기다리도록 만들어야 합니다.
router.post("/todos", async (req, res, next) => {
// next는 데스트용.
// 1. 클라이언트에게 전달받은 value 데이터를 변수에 저장합니다.
const { value } = req.body;
// 2. 해당하는 마지막 order 데이터를 조회 (MongoDB에서 'order' 값이 가장 높은 '해야할 일')
// findOne : 한개의 데이터 조회
// sort(컬럼) : 지정 컬럼을 기준으로 정렬
// sort('컬럼이름') : 오름차순 정렬
// sort('-컬럼이름') : 내림차순 정렬
// .exec(); : 몽구스 DB에서 조회시 무조건 마지막에 붙여야 오류 안남
// promis로 반환하는데, .exec()가 없으면 await가 작동하지 않습니다.
// Todo 컬렉션에서 'order'차트를 내림차순으로 맨 위의 것(제일 큰 값)을 하나 가져옴니다.
const todoMaxOrder = await Todo.findOne().sort("-order").exec();
// 3. 만약 존재한다면 현재 할 일에 +1, order 데이터가 존재하지 않는다면 1로 할당합니다.('order' 값이 가장 높은 도큐멘트의 1을 추가하거나 없다면, 1을 할당합니다.)
const order = todoMaxOrder ? todoMaxOrder.order + 1 : 1;
// 4. 해야할 일 등록
// todo를 실제 인스턴스형식으로 만듦
const todo = new Todo({ value, order });
// 실제로 DB에 저장
await todo.save();
// 5. 해야할 일을 클라이언트에게 반환
return res.status(201).json({ todo });
});
export default router;
exec() 메서드
mongoose에서 exec()는 결과를 반환하기 위해 쿼리를 실행하고, 이 결과로 Promise를 반환하게 됩니다.
만약, exec() 메서드를 사용하지 않는다면, 해당 쿼리는 결과값이 Promise로 반환되지 않기 때문에, 아직 데이터를 전달받지 않은 상태에서 다음 코드를 실행하게될 수 있습니다.
결국, 사용하려는 데이터가 null로 정의되어 있어, TypeError: Cannot read properties of null (reading 'id') 에러가 발생하게 될 것입니다.
4) 데이터 유효성 검사 기능 추가하기
데이터 유효성 검사(Validation)란, 전달받은 데이터가 예상한 형식과 일치하는지 확인하기 위한 작업을 뜻합니다.
MongoDB에 비어 있는 데이터를 저장하려고 한다면, 아래와 같은 에러가 발생할 수 있습니다.
그렇기 때문에, value 데이터의 유무를 미리 판단하고, 데이터가 존재하지 않을 때, 클라이언트에게 현재 상황을 전달함과 동시에 더이상 다음 코드로 실행되지 않도록 코드를 구현해야합니다.
할 일 추가 API에 데이터 유효성 검사 기능 추가하기
// /routes/todos.router.js
...
router.post('/todos', async (req, res) => {
// 클라이언트에게 전달받은 value 데이터를 변수에 저장합니다.
const { value } = req.body;
// value가 존재하지 않을 때, 클라이언트에게 에러 메시지를 전달합니다.
if (!value) {
return res
.status(400)
.json({ errorMessage: '해야할 일 데이터가 존재하지 않습니다.' });
}
...
// /routes/todos.router.js
import express from "express";
import Todo from "../schemas/todo.schema.js";
// 라우터 생성
const router = express.Router();
/** 할일등록 API **/
// 할일 등록은 .post메소드 사용
// URL : /todos
// DB사용하려면 async, 즉 비동기 함수를 사용해야 합니다. 데이터를 조회할 동안 프로그램이 기다리도록 만들어야 합니다.
router.post("/todos", async (req, res, next) => {
// next는 데스트용.
// 1. 클라이언트에게 전달받은 value 데이터를 변수에 저장합니다.
const { value } = req.body;
// 1-5. 데이터 유효성 검사 기능 추가
// value가 존재하지 않을 때, 클라이언트에게 에러 메시지를 전달합니다.
if (!value) {
// 값이 없을 때
return res
.status(400) // 400 : 클라이언트 잘못으로 오류 발생
.json({ errorMessage: "해야할 일 데이터가 존재하지 않습니다." }); // 리턴 데이터 형태: json
}
// 2. 해당하는 마지막 order 데이터를 조회 (MongoDB에서 'order' 값이 가장 높은 '해야할 일')
// findOne : 한개의 데이터 조회
// sort(컬럼) : 지정 컬럼을 기준으로 정렬
// sort('컬럼이름') : 오름차순 정렬
// sort('-컬럼이름') : 내림차순 정렬
// .exec(); : 몽구스 DB에서 조회시 무조건 마지막에 붙여야 오류 안남
// promis로 반환하는데, .exec()가 없으면 await가 작동하지 않습니다.
// Todo 컬렉션에서 'order'차트를 내림차순으로 맨 위의 것(제일 큰 값)을 하나 가져옴니다.
const todoMaxOrder = await Todo.findOne().sort("-order").exec();
// 3. 만약 존재한다면 현재 할 일에 +1, order 데이터가 존재하지 않는다면 1로 할당합니다.('order' 값이 가장 높은 도큐멘트의 1을 추가하거나 없다면, 1을 할당합니다.)
const order = todoMaxOrder ? todoMaxOrder.order + 1 : 1;
// 4. 해야할 일 등록
// todo를 실제 인스턴스형식으로 만듦
const todo = new Todo({ value, order });
// 실제로 DB에 저장
await todo.save();
// 5. 해야할 일을 클라이언트에게 반환
return res.status(201).json({ todo });
});
export default router;
insomnia 로 테스트 하기
app.js 파일을 실행해 포트를 열어놓으세요
insomnia 컬렉션 만들기
Url : post localhost:3000/api/todos
// body는 json
{
"value" : "해야할일을 추가합니다. insomnia"
}
결과 : 할일이 추가 되었습니다.
'order'이 1로 할당 되었습니다.('order'데이터가 없어서)
고유 id인 _id도 정상적으로 등록되었습니다.
'send' 버튼을 누를 때 마다 'order' 숫자가 정상적으로 증가합니다.
'value'가 비었을 때의 오류처리도 정상적으로 됩니다.
이제 서버는 데이터가 존재하지 않다면, 더이상 MongoDB에 데이터를 저장하는 작업을 수행하지 않습니다.
5) 할 일 목록 조회 API 만들기
order 라는 값을 기준으로 내림차순(.sort("-order"))해서 Todo 데이터를 가져오도록 하겠습니다.
3개 이상의 할 일을 등록하고, order 값을 기준으로 내림차순해서 가장 높은 order값을 가지고 있는 ‘해야할 일’을 제일 상단에 위치하도록 코드를 작성하기
/** 해야할 일 목록 조회 API**/
// API등록은 router에서 합니다.
router.get("/todos", async (req, res, next) => {
// 1. 해야할 일 목록 조회를 진행한다.
const todos = await Todo.find().sort("-order").exec();
// 2. 해야할 일 목록 조회 결과를 클라이언트에게 반환 한다.
return res.status(200).json({ todos });
});
// /routes/todos.router.js
import express from "express";
import Todo from "../schemas/todo.schema.js";
// 라우터 생성
const router = express.Router();
/** 할일등록 API **/
// 할일 등록은 .post메소드 사용
// URL : /todos
// DB사용하려면 async, 즉 비동기 함수를 사용해야 합니다. 데이터를 조회할 동안 프로그램이 기다리도록 만들어야 합니다.
router.post("/todos", async (req, res, next) => {
// next는 데스트용.
// 1. 클라이언트에게 전달받은 value 데이터를 변수에 저장합니다.
const { value } = req.body;
// 1-5. 데이터 유효성 검사 기능 추가
// value가 존재하지 않을 때, 클라이언트에게 에러 메시지를 전달합니다.
if (!value) {
// 값이 없을 때
return res
.status(400) // 400 : 클라이언트 잘못으로 오류 발생
.json({ errorMessage: "해야할 일 데이터가 존재하지 않습니다." }); // 리턴 데이터 형태: json
}
// 2. 해당하는 마지막 order 데이터를 조회 (MongoDB에서 'order' 값이 가장 높은 '해야할 일')
// findOne : 한개의 데이터 조회
// sort(컬럼) : 지정 컬럼을 기준으로 정렬
// sort('컬럼이름') : 오름차순 정렬
// sort('-컬럼이름') : 내림차순 정렬
// .exec(); : 몽구스 DB에서 조회시 무조건 마지막에 붙여야 오류 안남
// promis로 반환하는데, .exec()가 없으면 await가 작동하지 않습니다.
// Todo 컬렉션에서 'order'차트를 내림차순으로 맨 위의 것(제일 큰 값)을 하나 가져옴니다.
const todoMaxOrder = await Todo.findOne().sort("-order").exec();
// 3. 만약 존재한다면 현재 할 일에 +1, order 데이터가 존재하지 않는다면 1로 할당합니다.('order' 값이 가장 높은 도큐멘트의 1을 추가하거나 없다면, 1을 할당합니다.)
const order = todoMaxOrder ? todoMaxOrder.order + 1 : 1;
// 4. 해야할 일 등록
// todo를 실제 인스턴스형식으로 만듦
const todo = new Todo({ value, order });
// 실제로 DB에 저장
await todo.save();
// 5. 해야할 일을 클라이언트에게 반환
return res.status(201).json({ todo });
});
/** 해야할 일 목록 조회 API**/
// API등록은 router에서 합니다.
router.get("/todos", async (req, res, next) => {
// 1. 해야할 일 목록 조회를 진행한다.
const todos = await Todo.find().sort("-order").exec();
// 2. 해야할 일 목록 조회 결과를 클라이언트에게 반환 한다.
return res.status(200).json({ todos });
});
export default router;
테스트 : 서버 다시 켜기 -> insumnia에서 get localhost:3000/api/todos
[Response] GET /routes/todos 할 일 목록 조회 API
3개의 할 일을 등록해놓은 상태. order값을 기준으로 내림차순 정렬이 되는지 확인하기
이 응답(Response)에서 todos 키 아래 배열이 위치해 있으며, 배열의 각 요소는 할 일을 나타내는 객체입니다. 각 객체는 할 일의 고유 아이디(id), 내용(value), 순서(order)를 가지고 있습니다.
{
"todos": [
{
"_id": "64bd3eea8f9c069e092ee5cc",
"value": "맥도날드 초코콘 사오기",
"order": 3,
"__v": 0,
"id": "64bd3eea8f9c069e092ee5cc"
},
{
"_id": "64bd3ee48f9c069e092ee5c9",
"value": "클라이밍 10문제 풀기",
"order": 2,
"__v": 0,
"id": "64bd3ee48f9c069e092ee5c9"
},
{
"_id": "64bd3e6a8f9c069e092ee5c4",
"value": "제로 콜라 500ml 구매하기",
"order": 1,
"__v": 0,
"id": "64bd3e6a8f9c069e092ee5c4"
}
]
}
'내일배움 강의 > 강의- Node.js 입문, 숙련' 카테고리의 다른 글
입문 2주차 10 배포를 위한 Git 학습 (0) | 2024.11.24 |
---|---|
입문 2주차 11 AWS 배포하기 (0) | 2024.11.24 |
입문 2주차 5. Mongoose Schema 설계 (0) | 2024.11.22 |
입문 2주차 4.할 일 메모 사이트 설계 (0) | 2024.11.21 |
입문 2주차 3 mongoose (1) | 2024.11.21 |