WEB/NodeJS

[Node.js] Node.js CRUD(DB 연결X)

다콩잉 2022. 9. 18. 13:24

Node.js를 이용하여 게시판을 만들어 보았다. 데이터베이스를 연결하지 않고 배열에 객체를 저장하는 방식을 선택했다. 해당 객체에는 글 번호, 글 제목, 내용, 작성자가 들어가 있다. css는 bootstrap과 mvp.style을 사용했는데, mvp 사용에 익숙하지 않아 디자인이 이쁘지 않은 점이 가장 큰 문제다. 다음에는 MySql이나 MongoDB를 연결하고 디자인도 더 이쁘게 만들어야겠다.

 

 

처음 게시판 페이지

 

게시글 작성 페이지

 

작성 후 게시판 페이지

 

게시글 상세 보기 페이지

 

수정 페이지

 

수정한 후 게시판 페이지
게시글 추가 후 게시판 페이지(login 페이지를 아직 구현하지 않아서 작성자는 게시글 id로 표시되도록 함)

 

하이 게시물을 삭제
하이 게시물 삭제 후 게시판(중간 게시글을 삭제하면 게시글 번호가 바뀌게끔 설정)

 

 

 

Node.js 게시판 CRUD

 

server.js

import express from "express";
import morgan from "morgan";    // middleware
import boardRouter from "./routers/boardRouter.js";

const PORT = 4000;
const app = express();

app.set("view engine", "pug");  // html 템플릿 엔진
app.set('views', process.cwd() + "/src/views")
app.use(morgan("dev")); // ex) / 304 4.252 ms - - => path, status code, 응답시간
app.use(express.urlencoded({ extended: true} ));

app.use("/", boardRouter);

const handelListening = () => 
    console.log("서버 시작 " + `http://localhost:${PORT}`);

app.listen(PORT, handelListening);

 

boardRouter.js

import express from "express";
import {
    board, getRegister, postRegister,
    watch, getUpdate, postUpdate, getDelete
} from "../controllers/boardController.js"

const boardRouter = express.Router();

boardRouter.get("/", board);
boardRouter.route("/register").get(getRegister).post(postRegister);
// (\\d+): 정규 표현식, d: digit(숫자)
boardRouter.get("/:id(\\d+)", watch);
boardRouter.route("/:id/update").get(getUpdate).post(postUpdate);
boardRouter.route("/:id/delete").get(getDelete);

export default boardRouter;

 

boardController.js

const user = [];

let tables = [];

export const board = (req, res) => {
    return res.render("board", {pageTitle: "board", tables})
};
export const getRegister = (req, res) => {
    return res.render("register", {pageTitle: "Register"})
};
export const postRegister = (req, res) => {
    const obj = {};
    var id = -1;
    for(var i = 0; i < tables.length; i++){
        id = tables[i].id;
    }
    obj.id = id+1;
    obj.title = req.body.title;
    obj.author = obj.id;
    obj.content = req.body.content;
    tables.push(obj);
    return res.redirect("/");
};
export const watch = (req, res) => {
    const id = req.params.id;
    const table = tables[id];
    return res.render("watch", {pageTitle: "Watch", table})
};
export const getUpdate = (req, res) => {
    const id = req.params.id;
    const table = tables[id];
    return res.render("update", {pageTitle: `Update: ${table.title}`, table})
};
export const postUpdate = (req, res) => {
    const id = req.params.id;
    tables[id].title = req.body.title;
    tables[id].content = req.body.content;
    return res.redirect(`/`);
}
export const getDelete = (req, res) => {
    const id = req.params.id;
    tables.splice(id, 1);
    var change = 0;
    for(var i = 0; i < tables.length; i++){
        tables[i].id = change;
        change++;
    }
    return res.render("board", {pageTitle: "board", tables});
}

 

base.pug

doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(http-equiv="X-UA-Compatible", content="IE=edge")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous")
        link(rel="stylesheet" href="https://unpkg.com/mvp.css")
        style 
            include css/board.css
        title #{pageTitle}
    body 
        header 
            h1=pageTitle
        main 
            block content

 

board.pug

extends base.pug

block content 
    table
        tr 
            td 번호
            td 제목
            td 작성자
        each table in tables   
            tr 
                td=table.id
                td
                    a(href=`/${table.id}`)=table.title
                td=table.author
    div
        button.btn.btn-info
            a(href="/register").link Register

 

watch.pug

extends base.pug

block content 
    div 
        label 제목
        div=table.title
    br
    div 
        label 내용
        div=table.content
    button.btn.btn-info 
        a(href=`${table.id}/update`).link 수정
    button.btn.btn-info 
        a(href=`${table.id}/delete`).link 삭제
    button.btn.btn-info 
        a(href="/").link 목록

 

register.pug

extends base.pug

block content 
    form(method="post")
        label(for="") 제목
            input(name="title", required)
        label(for="") 내용
            textarea(name="content", cols="30", rows="10", required)
        input(type="submit", value="Next", style="color:white").btn.btn-info

 

update.pug

extends base.pug

block content
    form(method="post")
        label(for="") 제목 
        input(name="title", placeholder="Title", value=table.title, required)
        label(for="") 내용 
        textarea(name="content", cols="30", rows="10", placeholder="Content", required)=table.content
        input(value="Save", type="submit", style="color:white").btn.btn-info

 

board.css

.link{
    text-decoration: none;
    color: white;
}
@media (hover: hover) {
	a:hover { color: white; text-decoration: none; }
}
table{
    margin-left:auto; 
    margin-right:auto;
}

CRUD.zip
8.37MB

728x90