이번 글에서는 Todo CRUD 기능을 구현한 내용을 정리했습니다.
사용자의 할 일 목록을 추가, 조회, 수정, 삭제할 수 있도록 API를 만들었습니다.
1. 전체 목록 조회 (GET /todos)
export async function getAllTodos(req, res, next) {
await connectToDB();
const todos = await Todo.find({ userID: req.user.id });
res.status(200).send(todos);
}
- find({ userID: req.user.id })를 사용해 해당 유저의 todo만 조회한다.
2. 할 일 추가 (POST /todos)
export async function addTodo(req, res, next) {
if (!req.body || !req.body.title) {
return next(createError(404, '내용을 입력해주세요.'));
}
await connectToDB();
const newTodo = new Todo({ title: req.body.title, userID: req.user.id });
await newTodo.save();
res.status(201).json(newTodo);
}
- 새로운 Todo 객체를 생성한 후 DB에 저장.
- 저장된 Todo를 클라이언트에 반환.
3. 특정 할 일 조회 (GET /todos/:id)
export async function getTodo(req, res, next) {
try {
await connectToDB();
const todo = await Todo.findById(req.params.id);
if (!todo) return next(createError(404, '할 일을 찾을 수 없습니다.'));
if (todo.userID.toString() !== req.user.id)
return next(createError(403, '권한이 없습니다.'));
res.status(200).send(todo);
} catch (error) {
next(createError(404, '할 일을 찾을 수 없습니다.'));
}
}
- 요청 id 값을 기반으로 Todo를 찾는다.
- Todo의 userID와 요청한 사용자의 userID가 다르면 권한 없음 에러 반환.
- 정상적으로 조회되면 해당 Todo 데이터를 반환.
4. 할 일 수정 (PUT /todos/:id)
export async function updateTodo(req, res, next) {
if (!req.body) return next(createError(404, '입력값이 없습니다.'));
try {
await connectToDB();
const todo = await Todo.findById(req.params.id);
if (!todo) return next(createError(404, '할 일을 찾을 수 없습니다.'));
if (todo.userID.toString() !== req.user.id)
return next(createError(403, '권한이 없습니다.'));
todo.title = req.body.title || todo.title;
if (req.body.isCompleted !== undefined) {
todo.isCompleted = req.body.isCompleted;
}
await todo.save();
res.status(200).json({ message: '할 일이 수정되었습니다.' });
} catch (error) {
next(createError(404, '할 일을 찾을 수 없습니다.'));
}
}
- findById로 해당 Todo를 찾고, 사용자 검증 후 수정 진행.
- req.body.title이 있으면 제목 수정, isCompleted 값이 있으면 완료 여부 변경.
- 수정 후 "할 일이 수정되었습니다." 메시지 반환.
5. 할 일 삭제 (DELETE /todos/:id)
export async function deleteTodo(req, res, next) {
try {
await connectToDB();
const todo = await Todo.deleteOne({
_id: req.params.id,
userID: req.user.id,
});
if (!todo.deletedCount)
return next(createError(400, '할 일을 찾을 수 없습니다.'));
res.status(200).json({ message: '할 일이 삭제되었습니다.' });
} catch (error) {
next(createError(400, '할 일을 찾을 수 없습니다.'));
}
}
- deleteOne({ _id, userID })를 사용해 Todo 삭제.
- 삭제 성공 시 "할 일이 삭제되었습니다." 메시지 반환.
전체 코드
import { connectToDB } from '../utils/connect.js';
import Todo from '../models/todoModel.js';
import { createError } from '../utils/error.js';
// 전체 할 일 목록 조회
export async function getAllTodos(req, res, next) {
await connectToDB();
const todos = await Todo.find({ userID: req.user.id });
res.status(200).send(todos);
}
// 할 일 추가
export async function addTodo(req, res, next) {
if (!req.body || !req.body.title) {
return next(createError(404, '내용을 입력해주세요.'));
}
await connectToDB();
const newTodo = new Todo({ title: req.body.title, userID: req.user.id });
await newTodo.save();
res.status(201).json(newTodo);
}
// 특정 할 일 조회
export async function getTodo(req, res, next) {
try {
await connectToDB();
const todo = await Todo.findById(req.params.id);
if (!todo) return next(createError(404, '할 일을 찾을 수 없습니다.'));
if (todo.userID.toString() !== req.user.id)
return next(createError(403, '권한이 없습니다.'));
res.status(200).send(todo);
} catch (error) {
next(createError(404, '할 일을 찾을 수 없습니다.'));
}
}
// 할 일 수정
export async function updateTodo(req, res, next) {
if (!req.body) return next(createError(404, '입력값이 없습니다.'));
try {
await connectToDB();
const todo = await Todo.findById(req.params.id);
if (!todo) return next(createError(404, '할 일을 찾을 수 없습니다.'));
if (todo.userID.toString() !== req.user.id)
return next(createError(403, '권한이 없습니다.'));
todo.title = req.body.title || todo.title;
if (req.body.isCompleted !== undefined) {
todo.isCompleted = req.body.isCompleted;
}
await todo.save();
res.status(200).json({ message: '할 일이 수정되었습니다.' });
} catch (error) {
next(createError(404, '할 일을 찾을 수 없습니다.'));
}
}
// 할 일 삭제
export async function deleteTodo(req, res, next) {
try {
await connectToDB();
const todo = await Todo.deleteOne({
_id: req.params.id,
userID: req.user.id,
});
if (!todo.deletedCount)
return next(createError(400, '할 일을 찾을 수 없습니다.'));
res.status(200).json({ message: '할 일이 삭제되었습니다.' });
} catch (error) {
next(createError(400, '할 일을 찾을 수 없습니다.'));
}
}
'Node.js > Todo' 카테고리의 다른 글
JWT 인증 방식 개선: 쿠키 기반에서 토큰 기반으로 전환 (0) | 2025.02.24 |
---|---|
회원가입 및 로그인 기능 구현 (0) | 2025.02.20 |
쿠키 기반 JWT 인증 및 로그인/로그아웃 기능 (0) | 2025.02.18 |
MongoDB 연결 및 회원가입 구현 (0) | 2025.02.17 |
Node.js 서버 초기 설정 및 라우팅 구성 (0) | 2025.02.17 |