-
2. Node.js - 게시판 CRUD 구현Node.js 2022. 2. 7. 18:28
0. 목차
1. 기본설정
2. 게시판 목록 페이지
3. 글보기
4. 글쓰기
5. 글 삭제
6. 글 수정
1. 기본설정
1-1. 파일 구조
  - node_modules 폴더 : npm으로 다운받은 패키지가 들어있음. (+ package-lock.json, package.json 자동으로 다운 받아짐)
- public 폴더 : html파일에 함께 사용되는 정적 파일들이 들어있는 폴더 (css, js)
- views 폴더 : 라우팅에 사용되는 html 파일이 들어있는 폴더
- server.js : 메인 웹서버 파일
- data.js : 필요한 게시판 데이터를 저장한 파일
1-2. data.js 파일
const boardList = [ { subject: '제목1', username: 'HB', date: '2022-02-04' }, { subject: '제목2', username: 'HB', date: '2022-02-04' }, { subject: '제목3', username: 'HB', date: '2022-02-04' }, { subject: '제목4', username: 'HB', date: '2022-02-04' }, { subject: '제목5', username: 'HB', date: '2022-02-04' }, ] // ❗️파일을 export해서 외부 파일에서 사용 가능하도록 만들어주기 module.exports = { list: boardList }
👉 데이터를 만들고 해당 데이터를 module.exports 객체의 list라는 값에 담음.
1-3. server.js 파일 기본설정
const express = require('express') const nunjucks = require('nunjucks') const data = require('./data') //게시판 내용이 담긴 data.js 파일 가져오기 const list = [...data.list] // data.js에서 export한 객체 중 list를 복사해서 list에 담기 const app = express() app.use(express.static('public')) // public 폴더 내의 css파일 적용 app.use(express.urlencoded({ extended: true })) // POST요청 시 body부의 데이터 가지고 오기 app.set('view engine', 'html') nunjucks.configure('views', { express: app }) //nunjucks 사용 위한 세팅. views폴더의 html파일을 가져와 렌더링 할 수 있음
위 내용은 바로바로 칠 수 있도록 외워두는게 좋음
-외부파일을 가지고 와서 사용 가능하도록 세팅 (express, nunjucks 패키지 & data.js 파일)
- html파일 및 css파일 사용 가능하도록 설정
- post요청을 받은 경우 request body 부의 데이터를 받아올 수 있도록 설정
1-4. 서버 시작
app.get('/', (req, res) => { res.render('index') }) // path를 지정해주지 않은 메인 페이지 : views 폴더 내의 index.html 파일이 랜더링된다 app.listen(3000, () => { console.log("서버실행중") }) // 3000번 포트에서 서버가 실행되고 콘솔에 서버실행중이라는 문구가 출력된다
index.html
<h1><a href="/">LOGO</a></h1> <a href="/board/list">게시판 바로가기</a>
2. 게시판 목록 페이지
2-1. server.js 파일
app.get('/board/list', (req, res) => { res.render('board_list', { list: list }) })
/board/list 라는 경로로 들어가면 views 폴더의 board_list.html 파일이 랜더링 된다.
이때 render 메소드의 두번째 인자값으로 list를 담은 객체를 넣어주면 nunjucks 가 랜더링 시에 list데이터를 담아서 랜더링해준다.
2-2. board_list.html 파일
<h1><a href="/">LOGO</a></h1> <h2>게시판 목록</h2> <table> <tr> <td>글번호</td> <td>제목</a></td> <td>작성자</td> <td>작성일</td> </tr> {% for item in list %} <tr> <td>{{loop.index}}</td> <td><a href= "/board/view?index={{loop.index}}">{{item.subject}}</a></td> <td>{{item.username}}</td> <td>{{item.date}}</td> </tr> {% endfor %} </table> <a href="/board/write">글쓰기</a>
nunjucks문법의 이해가 필요하다.
server.js파일에서 넣어준 list 배열을 받아온다.
list는 각 인덱스마다 subject, username, date를 담은 객체가 들어있다. => 이 객체가 item이 됨
for in 으로 list의 length만큼 {% for ... %} 부터 (% endfor %} 로 감싸진 부분을 반복하며 출력한다.
이 반복문의 순서가 {{loop.index}}로 나타난다. (nunjucks에서 사용하는 문법임. 0이 아닌 1부터 시작하는 점에 유의)
게시물의 제목을 누르면 index=글번호 인 query를 가진 페이지로 이동하게 된다.
3. 글 보기
3-1. server.js 파일
app.get('/board/view', (req, res) => { const index = req.query.index res.render('board_view', { list: list, index: index }) })
list페이지에서 게시글의 제목을 누르면 board/view?index=(글번호)인 페이지로 넘어간다.
get요청은 위와같이 uri뒤의 query로 클라이언트의 요청정보를 서버로 받아온다. (post요청은 request body에서 요청정보를 받아옴)
이 정보는 req.query로 확인이 가능하다.
<get요청의 query string>
get요청은
url의 query string으로 객체를 생성한다.
www.HB.com/path1/path2?info1=abc&info2=def&info3=ghi
라는 url을 브라우저에 입력한다면
서버에서는
app.get('/path1/path2', (req,res)=>{ 요청을 처리하는 함수! })
이런 식으로 get메소드에서 해당 요청(url입력)을 처리하게 된다.
req.query = {
info1: abc,
info2: def,
info3: ghi
}
이런 객체가 생성된다❗️비교를 위하여 post요청시의 정보값을 받아오는 방법을 함께 정리해둔다.
<post요청의 request body>
post요청은
form태그 내의 name과 value로 객체를 생성한다.
form 태그 내에
<input name="info1" value="abc">
<input name="info2" value="def">
<input name="info3" value="ghi">
라는 인풋값이 있으면 submit을 눌렀을 때 이 값들이 post요청의 request body부로 전달된다.
서버에서는
app.post('/path1/path2', (req,res)=>{ 요청을 처리하는 함수! })
이런 식으로 post메소드에서 해당 요청(input값)을 처리하게 된다.
req.body = {
info1: abc,
info2: def,
info3: ghi
}
이런 객체가 생성된다
❗️
req.body로 값을 받아오기 위해서는 1-3에 작성한 것처럼
app.use(express.urlencoded({ extended: true }))
코드가 필요하다board_list.html에 작성한 코드에서는
게시물 제목을 클릭한다면
/board/view?index=(글번호)로 이동하도록 a태그를 작성하였으므로
req.query는 {index: (글번호)}라는 정보를 담은 객체가 된다.
url로 받아온 이 index 정보를 다시 html 파일로 넘겨주어 페이지 랜더링에 이용해야 한다.
res.render 메소드의 두번째 인자에 list데이터와 index값을 넘겨준다.
3-2. board_view.html 파일
<h1><a href="/">LOGO</a></h1> <h2>글보기</h2> <ul> <li> 글번호 : {{index}} </li> <li> 제목 : {{list[index-1].subject}}</li> <li> 작성자 : {{list[index-1].username}}</li> <li> 작성일 : {{list[index-1].date}}</li> </ul> <a href="/board/list">목록가기</a> <form method="post" action="/board/delete"> <input type="hidden" name="index" value={{index}}> <input type="submit" value="삭제하기"> </form> <a href="/board/update?index={{index}}">수정하기</a>
넘겨받은 index값(글번호)과 list로 nunjucks를 이용해 html을 작성한다.
list의 인덱스는 0부터 시작하므로 넘겨받은 index(글번호)에서 1을 빼준다
(글번호 1은 list[0]의 객체, 글번호 2는 list[1]의 객체가 되도록)
해당 객체의 subject, username, date를 각각 제목, 작성자, 작성일에 넣어준다.
글보기 페이지에서 목록가기 / 삭제하기 / 수정하기를 할 수 있도록 링크를 만들어준다.
4. 글 쓰기
4-1. server.js 파일 - get 요청
글쓰기 페이지에서는 get요청시와 post요청시를 구분해주어야한다.
글쓰기 페이지를 열 때 👉 get요청
글쓰기 페이지에서 글을 쓴 뒤 등록을 눌렀을 때 👉 post요청
app.get('/board/write', (req, res) => { res.render('board_write') })
get 요청 시에는 단순히 board_write.html 파일을 랜더링 해주면 된다.
4-2. board_write.html
<h1><a href="/">LOGO</a></h1> <h2>글쓰기</h2> <form method="post" action="/board/write"> <ul> <li> 제목 : <input type="text" name="subject"> </li> <li> 작성자 : <input type="text" name="username"> </li> <li> 작성일 : <input type="text" name="date"> </li> </ul> <input type="submit" value="등록하기"> </form>
작성한 내용을 post 요청으로 서버에 보내기 위해 form태그로 감싸준 뒤 input 박스를 만들어 준다.
input 박스에 입력한 값은 value로 담긴다.
4-3. server.js 파일 - POST 요청
이렇게 작성한 뒤 submit 버튼을 누르면 서버에 작성한 정보가 넘어온다.
req.body = {
subject : 'new제목',
username : 'new작성자',
date : 'new작성일',
}app.post('/board/write', (req, res) => { const content = req.body list.push(content) res.redirect('/board/list') })
list에 req.body로 넘어온 정보를 추가해준다.
그 뒤 게시판리스트 페이지로 redirect해주면 게시판페이지는 추가된 list로 다시 페이지를 다시 랜더링하여 보여준다.
5. 글 삭제
5-1. board_view.html의 글 삭제 버튼
<form method="post" action="/board/delete"> <input type="hidden" name="index" value={{index}}> <input type="submit" value="삭제하기"> </form>
form으로 감싼 삭제버튼을 만들어준다.
hidden으로 보이지 않는 input엘리먼트를 만들어 준다. 해당 엘리먼트는 index값을 담고 있다.
submit을 누르면 post요청으로 index값을 보낸다.
5-2. server.js 파일 - POST 요청
app.post('/board/delete', (req, res) => { const index = req.body.index - 1 list.splice(index, 1) res.redirect('/board/list') })
삭제를 할때는 별도의 html페이지 없이 삭제요청을 처리한 뒤 게시물목록페이지로 리다이렉트 해주는 방식으로 요청을 처리한다.
req.body = {index: (글번호)} 이므로
게시물의 정보가 담긴 list 어레이에서 글번호-1의 인덱스값을 가진 데이터를 splice메소드를 이용하여 삭제해준다.
6. 글 수정
글 수정도 작성한 내용을 서버로 보내 저장하도록 해야하므로 get요청과 post요청 두가지를 모두 처리할 수 있도록 만들어주어야 한다.
6-1. board_view.html의 글 수정 링크
<a href="/board/update?index={{index}}">수정하기</a>
index=(글번호) 쿼리를 가지는 페이지로 이동하도록 a태그를 만든다.
6-2. server.js 파일 - get 요청
app.get('/board/update', (req, res) => { const index = req.query.index res.render('board_update', { list: list, index: index }) })
a태그로 페이지에 접근하면 get 요청으로 처리가 된다.
list 데이터와 query의 인덱스 값을 받아와 html 파일로 넘겨준다.
6-2. board_update.html
<h1><a href="/">LOGO</a></h1> <h2>글보기</h2> <form method="post" action="/board/update"> <ul> <li> 글번호 : {{index}} </li> <li> 제목 : <input type="text" name="subject" value="{{list[index-1].subject}}"></li> <li> 작성자 : <input type="text" name="username" value="{{list[index-1].username}}"></li> <li> 작성일 : <input type="text" name="date" value="{{list[index-1].date}}"></li> </ul> <input type="hidden" name="index" value={{index}}> <input type="submit" value="수정하기"> </form>
board_write.html과 구조가 비슷하다.
차이점은 수정하기 전의 기존 값을 value에 넣어준 상태라는 것이다.
서버에서 전달받은 list데이터와 index 값을 통해 해당 글 번호의 데이터를 찾아 기존값으로 넣어준다.
내용을 수정하게 되면 value가 바뀌게 된다.
❗️submit을 눌러 다시 서버로 데이터를 보내 저장할 때 기존의 index값에 정확히 덮어쓰기를 할 수 있도록 hidden으로 input을 만들어 index값도 함께 post 요청 시에 보내야한다! (이 부분은 삭제처리시와 유사하다.)
6-3. server.js 파일 - post 요청
app.post('/board/update', (req, res) => { const index = req.body.index const item = { subject: req.body.subject, username: req.body.username, date: req.body.date } list[index - 1] = item res.redirect(`/board/view?index=${index}`) })
post 요청시에 req.body로 브라우저에게서 받은 데이터를 이용해
item 객체를 만들어주고
기존의 list 데이터에 덮어쓰기를 해준다.
❗️
브라우저-서버 통신 시의 index는 1부터 시작하는 글번호 🆚 list는 인덱스가 0부터 시작하는 배열
👆이거 헷갈리지 말고 잘 구분해서 코드 짜주기!
그 후 글번호에 해당하는 view 페이지로 리다이렉트 해서 바뀐 내용이 잘 적용되었는지 확인 할 수 있도록 해준다.
'Node.js' 카테고리의 다른 글
5. Hash와 JWT (0) 2022.03.03 4. HTTP 프로토콜, 쿠키와 세션 (0) 2022.02.14 3. Node.js - 로그인 기능 구현 (0) 2022.02.07 1. Node.js 시작해보기 (0) 2022.01.26 0. Node.js 시작 전 설정하기 (0) 2022.01.25