MySQL을 이용해서 방명록 작성하고 정보 읽어오기

dev_jubby·2022년 8월 5일
1

Node.js

목록 보기
3/8

MySQL을 이용해서 DB에 정보를 저장하고, DB의 값을 읽어와서 view에 table형식으로 보여주기 (CRUD)

먼저, npm(node package manager)를 초기화 한다.

npm init

그 다음 프로젝트에 필요한 dependeny를 설치한다.

npm install express
npm install ejs
npm install body-parser
npm install mysql


📁 폴더구조 & index.js 파일

MVC 패턴에 필요한 폴더를 생성해주고 main index.js 파일을 생성한다. 기본경로를 /visitor 로 설정해주었다.

/* index.js */
const express = require("express");
const app = express();
const port = 8080;
const bodyParser = require("body-parser"); 

app.set("view engine", "ejs");
app.use( express.static( "uploads" ));
app.use(express.urlencoded({extended: true}));
app.use( bodyParser.json() );

const router = require("./routes");
app.use("/visitor", router); 


app.listen(port, () => {
    console.log( "Server Port: ", port);
}) 


💾 DataBase 생성하기

Vistior model을 생성하기 전, MySQL을 이용해서 visitor라는 테이블을 생성했다.

그리고 DML 명령어를 이용하여 데이터를 생성했다.



💡 DB 계정 설정하기

CRUD를 하기 위해 새로운 계정을 생성한다. 기존에 사용하던 root 계정은 최상위 계정이라 외부로부터의 비밀번호 접근을 허용하지 않기 때문이다. 즉, 새로운 사용자를 만들고 그 사용자로 접근을 해야한다.

새로운 계정 생성하기

CREATE USER '사용자이름'@'%' IDENTIFIED BY '비번';

모든 DB, 테이블 관리 권한 부여하기

GRANT ALL PRIVILEGES ON *.* TO '사용자이름'@'%' WITH GRANT OPTION;

권한 부여 내용을 메모리에 반영하기 (권한 적용하기)

FLUSH PRIVILEGES;

기본 인증 암호화 플러그인caching_sha2_password를 사용하게 되어있다. mysql_native_password 방식을 사용하기 위해 변경해준다.

ALTER USER '사용자이름'@'%' IDENTIFIED WITH mysql_native_password BY '비번';


📦 Model 구현하기

Vistior model을 생성하는데, mysql module을 이용한다. mysql.createConnection()을 이용하면 DB와 서버를 연결하는 객체를 만들 수 있으며, 이를 이용해서 여러 쿼리(query)를 실행시킬 수 있다.

/* ./model/Visitor */
const mysql = require("mysql");

const cnn = mysql.createConnection({
    host: 'localhost',
    user: 'user_name',
    password: 'password',
    database: 'database_name'
});

//방명록 전체 정보 조회
exports.get_visitors = (cb) => {
    cnn.query('SELECT * FROM visitor;', (err, rows)=> {
        if ( err ) throw err;
        console.log( rows ); 

        cb(rows);
    });
}

//방명록 등록
exports.insert = ( name, comment, cb ) => {
    var sql = "INSERT INTO visitor (name, comment) VALUES ('" + name + "', '" + comment + "');";
    cnn.query(sql, (err, rows) => {
        if ( err ) throw err;
        console.log( rows ); 

        cb(rows.insertId);
    });
}

//방명록 단일 정보 조회
exports.get_visitor = (id, cb) => {
    // id 컬럼의 값이 id인 데이터를 1개만 검색한다.
    cnn.query(`SELECT * FROM visitor Where id= ${id} limit 1;`, (err, rows) => {
        if ( err ) throw err;
        console.log( rows ); 

        cb(rows);
    });
}

//방명록 정보 수정
exports.update = (data, cb) => {
    var sql = `UPDATE visitor SET name='${data.name}', comment='${data.comment}' WHERE id=${data.id}`;
    cnn.query(sql, (err, rows) => {
        if ( err ) throw err;
        console.log( rows );

        cb(rows);
    })
}

//방명록 정보 삭제
exports.delete = (id, cb) => {
    cnn.query(`DELETE FROM visitor WHERE id=${id}`, (err, rows) => {
        if ( err ) throw err;
        console.log( rows );

        cb(rows);
    })
}

get_visitors()는 SELECT 쿼리를 이용해서 전체 정보를 불러오는 함수이다. 콜백 함수로 해당 데이터를 Controller에 넘겨준다.
insert()는 INSERT ~ INTO 쿼리를 사용해서 데이터를 추가할 때 사용하는 함수이다. 콜백 함수로 insertId만 Controller에 넘겨준다.
get_visitor()는 id로 쿼리를 조회해서 단일 정보만 읽어오는 함수이다.
update()는 id로 정보를 수정하는 함수이다.
delete()는 id로 정보를 삭제하는 함수이다.



🔧 Controller 구현하기

get_visitors()는 model을 통해 DB 정보를 가져와서 view 쪽으로 넘겨준다.
post_comment()는 name과 comment 정보를 model쪽으로 넘겨주어 DB에 저장되도록 한 후, insertId 정보를 돌려 받아 view 쪽으로 넘겨준다.
get_visitor()는 get_visitors() 처럼 단일 정보를 가져와서 view쪽으로 정보를 넘겨준다.
patch_comment()는 Visitor 모델의 update()를 이용해서 정보를 수정한다.
delete_comment()는 Visitor 모델의 delete()를 이용해서 정보를 삭제한다.

/*  ./controller/VisitorController.js */
const Visitor = require("../model/Visitor");

//방명록 전체 정보 조회
exports.get_visitors = (req, res) => {
    Visitor.get_visitors(function( result ) {
        res.render("index", {data: result});
    });
}

//방명록 등록
exports.post_comment = (req, res) => {
    Visitor.insert( req.body.name, req.body.comment, function( result ) {
        res.send( {id: result} );
    });
}

//방명록 단일 정보 조회
exports.get_visitor = (req, res) => {
    Visitor.get_visitor( req.query.id, function(result) {
        res.send({ result: result[0]});
    })    
}

//방명록 정보 수정
exports.patch_comment = (req, res) => {
    Visitor.update( req.body, function(result) {
        res.send( "success Update!" );
    });
}

//방명록 정보 삭제
exports.delete_comment = (req, res) => {
    Visitor.delete( req.body.id, function(result) {
        res.send( "success Delete!" );
    });
}


💻 Route 구현하기

/* .routes/index.js */
const express = require("express");
const visitorRouter = express.Router();
const visitor = require("../controller/VisitorController");

visitorRouter.get("/", visitor.get_visitors);
visitorRouter.post("/write", visitor.post_comment);
visitorRouter.get("/get", visitor.get_visitor);
visitorRouter.patch("/edit", visitor.patch_comment);
visitorRouter.delete("/delete", visitor.delete_comment);

module.exports = visitorRouter; 


🎨 view 구현하기

View는 index.ejs 파일 하나만 생성했다.
BODY

<body>
        <div>
            <form id="form_comment">
                <fieldset>
                    <legend>방명록 등록</legend>
                    <div><input type="hidden" name="id" placeholder="사용자 아이디"></div>
                    <div><input type="text" name="name" placeholder="사용자 이름"></div>
                    <div><input type="text" name="comment" placeholder="방명록"></div>
                    <div id="button-group">
                        <button type="button" onclick="writeComment();">등록</button>
                    </div>
                </fieldset>
            </form>
        </div>
        <br/>
        <table id="visit_list">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>작성자</th>
                    <th>방명록</th>
                    <th>수정</th>
                    <th>삭제</th>
                </tr>   
            </thead>
            <tbody>  
                <%
                for (let i=0; i<data.length; i++ ) {
                %>
                    <tr id="tr_<%=data[i].id%>">
                        <td><%=data[i].id%></td>
                        <td><%=data[i].name%></td>
                        <td><%=data[i].comment%></td>
                        <td><button type="button" onclick="editComment('<%=data[i].id%>');">수정</button></td>
                        <td><button type="button" onclick="deleteComment('<%=data[i].id%>');">삭제</button></td>
                    </tr>
                <%
                    }
                %>
            </tbody>    
        </table>
</body>

Script

<script>
            function writeComment() {
                var form = document.getElementById("form_comment");
                axios({
                    method: 'post',
                    url: 'http://localhost:8080/visitor/write',
                    data: {
                        name: form.name.value,
                        comment: form.comment.value
                    }
                })
                .then((response) => { return response.data; })
                .then((data) => {
                    let html = "<tr id='tr_" + data.id + "'><td>" + data.id + "</td><td>" + form.name.value + "</td><td>" + form.comment.value + "</td>" + 
                        "<td><button type='button' onclick='editComment(" + data.id + ");'>수정</button></td>" +
                        "<td><button type='button' onclick='deleteComment(" + data.id + ");'>삭제</button></td></tr>";
                   
                    $("table").append(html);       
                })
            }

            // 수정버튼 눌렀을 때 input 등록창 update
            function editComment( id ) {
                axios({
                    method: 'get',
                    url: 'http://localhost:8080/visitor/get?id=' + id
                })
                .then((response) => { return response.data })
                .then(( data ) => {

                    var form = document.getElementById("form_comment");
                    form.name.value = data.result.name;
                    form.comment.value = data.result.comment;

                    var html = "<button type='button' onclick='editDo(" + id + ");'>수정</button>"
                    + "<button type='button' onclick='editCancel();'>수정 취소</button>";

                    //등록 button을 수정 button으로 바꾼다
                    document.getElementById("button-group").innerHTML = html;

                });
            }

            // DB 수정 + table 내용 update
            function editDo( id ) {
                var form = document.getElementById("form_comment");
                axios({
                   method: 'patch',
                   url: 'http://localhost:8080/visitor/edit',
                   data: {
                    id: id,
                    name: form.name.value,
                    comment: form.comment.value
                   } 
                })
                .then((response) => { return response.data })
                .then((data) => {
                    var tr = document.getElementById("tr_"+id);
                    var children = tr.children;
                    console.log(children);

                    $(children[1]).text(form.name.value);
                    $(children[2]).text(form.comment.value);
                })
            }

            // 수정취소 -> 등록버튼
            function editCancel() {
                var form = document.getElementById("form_comment");
                form.reset();

                var html = "<button type='button' onclick='writeComment();'>등록</button>";
                document.getElementById("button-group").innerHTML = html;
            }


            // 삭제
            function deleteComment( id ) {
                axios({
                   method: 'delete',
                   url: 'http://localhost:8080/visitor/delete',
                   data: { id: id } 
                })
                .then((response) => { return response.data; })
                .then((data) => { 
                    var tr = document.getElementById("tr_" + id);
                    $(tr).remove();
                    // $("#tr_" + id).remove();
                 });
            }
 </script>

🤍 완성!

사용자 이름과 방명록을 작성하고 등록버튼을 눌렀을 때

table의 수정 버튼을 클릭했을 때

정보를 수정하고 수정 버튼을 눌렀을 때

정보 수정하지 않고 수정취소 버튼을 눌렀을 때

table의 삭제 버튼을 눌렀을 때



profile
신입 개발자 쥬비의 기술 블로그 입니다.

0개의 댓글