개발자공부일기
Node.js 간단한 메모장 만들기 본문
// /app.js
import express from 'express';
import connect from './schemas/index.js';
import TodosRouter from './routes/todos.router.js';
const app = express();
const PORT = 3000;
connect();
// Express에서 req.body에 접근하여 body 데이터를 사용할 수 있도록 설정합니다.
app.use(express.json()); //미들웨어1
app.use(express.urlencoded({ extended: true }));//미들웨어2
// static Middleware, express.static()을 사용하여 정적 파일을 제공합니다.
app.use(express.static('./assets'));//미들웨어3
app.use((req, res, next) => {//미들웨어4
console.log('Request URL:', req.originalUrl, ' - ', new Date());
next();
});
const router = express.Router(); //라우터 생성
router.get('/', (req, res) => {
return res.json({ message: 'Hi!' }); //아무 요청에 Hi반환
});
// /api 주소로 접근하였을 때, router와 TodosRouter로 클라이언트의 요청이 전달됩니다.
app.use('/api', [router, TodosRouter]);//미들웨어 5
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
미들웨어는 위에서 아래로 실행되고 next()가 없으면 다음 미들웨어를 실행하지 않는다.
미들웨어를 사용할때 next() 또는 res.json()을 꼭 사용해야 한다.그렇지 않으면 무한정으로 요청은 대기한다.
// schemas/todo.schema.js
import mongoose from 'mongoose';
const TodoSchema = new mongoose.Schema({
value: {
type: String,
required: true, // value 필드는 필수 요소
},
order: {
type: Number,
required: true, // order 필드 또한 필수 요소
},
doneAt: {
type: Date, // doneAt 필드는 Date 타입
required: false, // doneAt 필드는 필수 요소가 아님
},
});
// 프론트엔드 서빙을 위한 코
TodoSchema.virtual('todoId').get(function () {
return this._id.toHexString();
});
TodoSchema.set('toJSON', {
virtuals: true,
});
// TodoSchema를 바탕으로 Todo모델을 생성하여, 외부로 내보낸다.
export default mongoose.model('Todo', TodoSchema);
각각의 key값이 어떤 유형인지 정의하는 스키마
// schemas/index.js
import mongoose from 'mongoose';
const connect = () => {
mongoose
.connect(
// MongoDB와 연결하기 위한 주소.userid에는 ID를 <password>에 설정한 password를 입력
'mongodb+srv://userid:<password>@express-mongo.ta3gl.mongodb.net/~~~~~',
{
dbName: 'todo_memo', // todo_memo 데이터베이스명을 사용합니다.
},
)
.then(() => console.log('MongoDB 연결에 성공하였습니다.'))
.catch((err) => console.log(`MongoDB 연결에 실패하였습니다. ${err}`));
};
mongoose.connection.on('error', (err) => {
console.error('MongoDB 연결 에러', err);
});
export default connect;
MongoDB에 연결하고 성공/실패 여부를 확인하기 위한 코드
// /routes/todos.router.js
import express from 'express';
// routes/todos.router.js
import Todo from '../schemas/todo.schema.js';
const router = express.Router();
router.post('/todos', async (req, res) => {//데이터를 조회하는동안 멈춰야 하니까 async
//1. 클라이언트로부터 받은 value데이터 가져오기
const { value } = req.body;
//1-5. 만약, 클라이언트가 value데이터를 전달하지 않았을 때,
//클라이언트에게 에러 메시지 전달
if (!value) {
return res
.status(400)
.json({ errorMessage: '해야할 일 데이터가 존재하지 않습니다.' });
}
// Todo모델을 사용해, MongoDB에서 'order' 값이 가장 높은 '해야할 일'을 찾습니다.
//2. 해당하는 마지막 order데이터 조회
// findOne = 1개의 데이터만 조회
// sort = 정렬한다. ->어떤 컬름을 기준으로?order
//exec를 안붙이면 앞에 코드가 promise로 동작하지 않는다=>await 사용불가
const todoMaxOrder = await Todo.findOne().sort('-order').exec();
// 'order' 값이 가장 높은 도큐멘트의 1을 추가하거나 없다면, 1을 할당합니다.
const order = todoMaxOrder ? todoMaxOrder.order + 1 : 1;
// Todo모델을 이용해, 새로운 '해야할 일'을 생성합니다.
const todo = new Todo({ value, order });
// 생성한 '해야할 일'을 MongoDB에 저장합니다.
await todo.save();
return res.status(201).json({ todo });
});
//해야할 일 목록 조회 API
router.get('/todos', async(req,res)=>{
//1.해야할일 목록 조회
const todos = await Todo.find().sort('-order').exec();
//2.조회 결과 클라이언트에 반환
return res.status(200).json({todos});
})
//해야할 일 순서 변경, 완료/해제,내용변경 API
router.patch('/todos/:todoId',async(req,res)=>{
//req.params는 URL에 정의된 모든 경로 변수들을 키-값 쌍으로 포함하는 객체
//ex)GET /todos/12345로 요청하면 req.params = { todoId: '12345' }
const {todoId} = req.params;
const {order,done,value} = req.body;
//현재 나의 order가 무엇인지 알아야 한다.
const currentTodo = await Todo.findById(todoId).exec(); //변경하려는 _id를 조회해서 저장
if(!currentTodo){
return res.status(404).json({errorMessage: ' 존재하지 않는 해야할 일 입니다.'});
}
if(order){
const targetTodo = await Todo.findOne({order}).exec(); //내가 바꾸고싶은 번호의 데이터를 조회
if(targetTodo){
targetTodo.order = currentTodo.order; //기존에 있던것과 바꾸려는것의 순서 변경
await targetTodo.save(); //저장
}
currentTodo.order = order; //변경하려던 데이터의 번호를 변경
}
if(done !== undefined){
currentTodo.doneAt = done ? new Date() : null; //done이 true면 지금 날짜 할당. 아니면 null
}
if(value) {
currentTodo.value = value; //메모바꾸기
}
await currentTodo.save();
return res.status(200).json({}); //200 상태메세지 반환
});
//할일 삭제
router.delete('/todos/:todoId',async(req,res)=>{
const {todoId} = req.params;
const todo = await Todo.findById(todoId).exec(); //삭제하려는 데이터 조회
if(!todo){
return res.status(400).json({errorMessage:'존재하지 않는 해야할 일 정보입니다.'});
}
await Todo.deleteOne({_id: todoId}); //그 id에 해당하는 데티어 삭제
return res.status(200).json({});
})
export default router;
todo list를 작성하고 순서를 변경하고 삭제하고 조회하는 코드들
전체적으로 많이 어려운 부분은 없었다. 항상 그렇듯 익숙하지 않아서 눈에 잘 안들어온다. 계속 익숙해지려고 코드 따라치고 계속 읽어보는 중이다. 확실히 점점 눈에 드는게 느껴진다 계속 하다보면 언젠가 되겠지
'TIL(Today I Learned)' 카테고리의 다른 글
AWS배포하기 프로세스가 종료되지 않는 문제 (0) | 2024.11.21 |
---|---|
1주차 서버와 클라이언트/ 웹 어플리케이션서버와 게임서버 (0) | 2024.11.20 |
Node.js 2일차 (0) | 2024.11.19 |
Node.js 1일차 (0) | 2024.11.18 |
정렬 알고리즘(버블/삽입/선택) (0) | 2024.11.15 |