Node.js CRUD 게시판 생성을 정리합니다.
Update입니다.
<!DOCTYPE html>
<html>
<head>
<title>글 수정하기</title>
<link rel='stylesheet' href='../../../css/style.css' />
</head>
<body>
<div class="ContentField">
<form action="/board/update" method="post">
<table frame=void>
<input type="hidden" name="idx" value="<%=rows[0].idx%>"/>
<tr>
<td colspan="2">
<input type="text" name="title" value="<%=rows[0].title%>" >
</td>
</tr>
<tr>
<td colspan="2">
<textarea style="border:none; width:100%; height:100%; padding-top:20px; font-size:1.3em" name="content" required ><%=rows[0].content%></textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:right;">
<button type="submit">글 수정</button>
<button type="button" onclick="location.href='../list/post/'+<%=rows[0].idx%>">뒤로 가기</button>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
글 수정 페이지는 글 작성자가 수정 버튼을 클릭해야 접근할 수 있습니다.
역시 마찬가지로, 파일 업로드와 관련된 부분은 모두 제외했습니다.
딱히 특이사항은 없으며, 글 제목과 내용이 서버로 전달됩니다.
router.get('/board/update/:idx',(req,res)=>{
const idx = req.params.idx;
req.session.updateIdx = idx;
conn.getConnection((err,connection)=>{
if (err) throw err;
const query = connection.query('SELECT idx, title, name, content FROM board WHERE idx='+idx, function(err,rows){
if (err) throw err;
if (rows[0].name==req.session.displayName){
res.render('boardHTML/postDetail.html',{rows:rows});
}else{
res.send("<script>alert('작성자가 아닙니다.'); document.location.href='/board/list'</script>")
}
connection.release();
})
})
})
글 수정 버튼을 누르면 포스트의 ID가 파라미터로 서버에 넘겨집니다.
이 파라미터를 통해 렌더링되는 html에 기존의 제목과 내용을 넘깁니다.
특이사항이라면, 혹시나 글 작성자가 아닌 사용자가 URL로 직접 접근한 경우
작성자가 아니라는 alert를 발생시키고, 게시판 페이지로 보냅니다.
실제로 값을 업데이트하는 post 라우터는 두 개의 Promise로 나뉩니다.
let selQuery = function(){
return new Promise(function(resolve,reject){
const sql = 'SELECT uploadfilepath FROM board WHERE idx=?';
connection.query(sql,[idx],(err,rows)=>{
if (err) reject(err);
if (rows.length==0 || (rows[0].uploadfilepath==null || rows[0].uploadfilepath=='')){
reject('There is no path in DB');
}else{
fileList = rows[0].uploadfilepath;
resolve('Detect path from DB');
}
})
})
첫 번째 Promise는 해당 포스트에 첨부된 파일이 있는지 여부를 검사합니다.
첨부된 파일이 있다면 fileList 변수에 DB에 저장된 경로값을 가져옵니다.
만약 없다면 fileList = '' 입니다.
연결해서, 컬럼에 값이 있다면 fulfill을, 없다면 reject를 반환합니다.
let updateQuery = function(){
return new Promise(function(resolve,reject){
const sql = 'UPDATE board SET title=?, content=?, uploadfilepath=?, modidate=NOW() WHERE idx=?'
connection.query(sql,[title,content,filepath,idx],function(err,rows){
if (err) reject(err);
res.send("<script>alert('작성되었습니다.'); document.location.href='/board/list'</script>")
connection.release();
resolve('Update path in DB');
})
})
}
두 번째 Promise는 단순한 Update 쿼리입니다.
전달받은 제목, 내용을 DB에 업데이트합니다.
파일 경로는 선행된 첫 번째 Promise의 결과에 따라서
- 기존 경로값 유지
- 새로운 경로값 생성
- 경로가 없음
셋 중 하나로 결정됩니다.
첫 번째 Promise가 fulfill 상태였다면 1, 또는 2로 파일 경로가 정해져 후행됩니다.
첫 번째 Promise가 reject 상태였다면 3으로 파일 경로가 정해지고 후행됩니다.
let worker = async function(){
try{
console.log(await selQuery());
if (filepath!=null){
filepath = fileList+'+'+filepath;
}else{
filepath=fileList;
}
console.log(await updateQuery());
}catch{
console.log(await updateQuery());
}
}
worker();
Promise 실행부입니다.
첫 번째 Promise는 파일 경로가 있으면 fulfill, 없으면 reject상태를 반환합니다.
따라서 try, catch 문법을 통해 수행을 분기합니다.
만약 파일 경로가 존재하는 경우 업데이트할 파일 경로를 정하고
두 번째 Promise를 수행합니다.
존재하지 않는다면 파일 경로를 정하는 부분을 제외하고, 두 번째 Promise를 곧바로 수행합니다.
파일 다운로드 구현에서 Async, await를 만난 이후
처음으로 콜백 방식으로 되어있던 것을 수정했던 Update 부분입니다.
다행(?)스럽게도 현재 구현된 기능들 중
작성된 글을 보는 것과 글을 작성하는 post 라우터 정도를 제외하면
콜백 방식에서 변경할 필요성은 보이지 않는 것 같습니다.
Async/await 방식을 사용해보며 계속 체감하고있는 것은
Node.js의 비동기적처리를 보기 쉽게 순차적으로 정리하면서 코드가 깔끔해지고
주석달기, 실행 순서를 제어하는 부분에 대해 편리함을 느끼고 있습니다.