수정 기능 구현
SeoMiYoung opened this issue · comments
게시물 수정 기능을 구현하는 과정을 살펴봅시다.
🔶 과정
🔸 수정 페이지 만들기
edit.ejs
에 수정할 수 있는 페이지를 만들었습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="/css/main.css" rel="stylesheet"/>
</head>
<body class="grey-bg">
<%- include('nav.ejs') %>
<form class="form-box" action="/edit" method="POST">
<h4>수정하기</h4>
<input type="hidden" name="id" value="<%= result._id %>">
<input name="title" value="<%= result.title %>">
<input name="content" value="<%= result.content %>">
<button type="submit">수정 완료</button>
</form>
</body>
</html>
🔸 '수정하기'를 클릭하면, 클릭한 글에 대한 수정페이지로 이동 (GET)
특정 글에서 수정을 원하면, 어쩌구/edit/id번호
로 페이지를 이동시킵니다.
// server.js 코드
app.get('/edit/:id', async(요청, 응답) => {
try {
// collection에 있는 조건에 맞는 가장 첫번째 document만 가져와주세요.
let result = await db.collection('shopData').findOne({ _id : new ObjectId(요청.params.id)})
if (result == null) {
응답.status(404).send('url에 해당하는 id없음')
}
else {
응답.render('edit.ejs', {result: result})
}
} catch(e) {
응답.status(404).send('url이 이상해서 에러 발생')
}
})
🔸 DB의 글을 수정합시다 (POST)
// server.js 코드
// 굳이 PUT쓰고 싶으면, ajax또는 외부 라이브러리 설치해서 쓰면 됨
app.post('/edit', async (요청, 응답) => {
// user가 입력한 데이터를 출력하기 위해
console.log(요청.body)
try {
if (요청.body.title == '') {
응답.send('제목을 입력해주세요.')
}
else if (요청.body.content == '') {
응답.send('내용을 입력해주세요.')
}
else {
await db.collection('shopData').updateOne(
{ _id: new ObjectId(요청.body.id) },
{
$set: {
title: 요청.body.title,
content: 요청.body.content
}
}
);
// 데이터를 DB에 저장하고 나서, redirect로 다른 페이지 이동
응답.redirect('/detail/'+ 요청.body.id)
}
} catch(e) {
// 어떤 에러인지 출력해보고 싶다면?
console.log(e)
응답.status(500).send('서버에 에러가 발생했습니다.')
}
})
[왜 POST를 사용했냐?]
form태그에서는 GET과 POST만 사용할 수 있고, PUT이나 DELETE는 사용할 수 없습니다. PUT같은거 쓰면 좀 더 이쁜 API를 만들 수 있으나, ajax나 외부라이브러리 이런거 가져다가 써야해서 쉽게 가져다가 쓸 수 있는게 아닙니다.. method-override쓰면 될 수도 있습니다.
[updateOne 추가 문법]
- $set: 기존값을 덮어쓰기 해줌
- $inc: 기존값에 추가 (ex. 숫자 덧셈 뺄셈)
- $mul: 기존값에 곱셈
- $unset: 기존에 있던 필드를 삭제해줌 (그치만 이것보다는 그냥 빈 문자열에 0을 집어넣거나 하는 경우가 더 편할 수 있으니 알아만 두삼)
[만약에 여러 document수정을 원한다면?]
뭐 여러개의 updateOne을 써도 되는데, 그냥 updateMany를 쓰면 편합니다.
예를 들면, title이 '안녕하세용'으로 되어있는 document들을 다 찾아서 수정을 해줄수도 있고, 아니면 원하면 num같은게 10이상인 document들만 찾아서 전부 수정하는 식으로, $gt, $lt 연산자를 활용해서 조건문을 넣어줄수도 있습니다.
=> 필요하면 그때 그때 찾아서 사용하는게 좋음!
🔶 결과
🔶 고려해 볼 예외처리
- 유저가 글의 id를 보내지 않으면?
- 수정할 글을 보냈는데 글이 비어있으면?
- 글이 너무 길면?
- DB에서 수정이 실패하고 에러가 나면?
<input type="hidden" name="id" value="<%= result._id %>">
이렇게 아무리 숨겨도, 사용자 입장에서 개발자도구 같은걸로 조작 가능하기 때문에,
서버측에서 한번 더 검사해서 걸러주는 작업이 추가로 필요할 듯 하다.