ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2. Node.js - 게시판 CRUD 구현
    Node.js 2022. 2. 7. 18:28

    0. 목차

    1. 기본설정

    2. 게시판 목록 페이지

    3. 글보기

    4. 글쓰기

    5. 글 삭제

    6. 글 수정

     

    1. 기본설정

    1-1. 파일 구조

     

    1. node_modules 폴더 : npm으로 다운받은 패키지가 들어있음. (+ package-lock.json, package.json 자동으로 다운 받아짐)
    2. public 폴더 : html파일에 함께 사용되는 정적 파일들이 들어있는 폴더 (css, js)
    3. views 폴더 : 라우팅에 사용되는 html 파일이 들어있는 폴더
    4. server.js : 메인 웹서버 파일
    5. 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 페이지로 리다이렉트 해서 바뀐 내용이 잘 적용되었는지 확인 할 수 있도록 해준다.

     

     

    board_practice.zip
    1.20MB

    '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
Designed by Tistory.