부트캠프/[POSCO x Codingon] 웹개발자 풀스택 과정 12기

[POSCO x Codingon] MVC-MySQL, Sequelize | 웹개발자 풀스택 과정 12기 8주차 회고 1

hyunh404 2024. 4. 17. 08:58
728x90

 

 

8주차 회고

 

 

8주차에는 지난주에 이어서 MVC모델과 MySQL에 대해서 배웠으며 서로 연결하는 방법을 연습해볼 수 있었다. 또한 DB작업을 쉽게할 수 있도록 도와주는 Sequelize 라이브러리도 사용해봤다.

 

 


 

 

1. MVC - MySQL

 

지난 주에 이어서 MVC와 MySQL을 연습하고 MySQL의 데이터 베이스와 연결하는 연습을 해볼 수 있었다.

 

MVC 구조로 폴더와 파일을 생성하고 MySQL과 연결해 방명록을 만드는 실습을 진행했다.

 

 

먼저 MVC 구조를 만들어주었다.

controller, model, routes, static, views 폴더를 생성하고 app.js로 실행파일을 생성했다.

MVC

 

 

views 폴더에는 실제 화면에 보여야할 구조를 구현했다.

방명록을 남긴 사람, 방명록 내용이 보이도록 했으며, 새로운 방명록 등록도 가능하도록 화면을 만들었다.

 

새로운 방명록을 등록하는 코드

<h1>방문자 목록</h1>
    <form name="visitor-form">
        <fieldset>
            <legend>방명록 등록</legend>
            <input type="text" id="name" placeholder="사용자 이름">
            <input type="text" id="comment" placeholder="방명록 내용">
            <div id="button-group">
                <button type="button" onclick="createVisitor()">등록</button>
            </div>
        </fieldset>
    </form>

 

 

 

MySQL의 데이터베이스에 저장된 방명록이 화면에 보여지는 영역

=> ejs 문법을 활용해 방명록이 추가, 삭제될 때 자동으로 화면에 나타나도록 for문을 작성했다.

또한 저장된 데이터를 받아와서 화면에 보여지도록 코드를 작성했다.

<table border="1">
        <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="editVisitor('<%= data[i].id %>')">수정</button></td>
                    <td><button type="button" onclick="deleteVisitor(this,'<%= data[i].id %>')">삭제</button></td>
                </tr>
            <% } %>
        </tbody>
    </table>

 

 

 

이제 데이터를 업데이트하고 받아오기 위해 MySQL을 연결해보겠다.

데이터를 연결하는 것은 model폴더에서 진행했다.

 

설치한 mysql2모듈을 활용해서 연결해보도록 하겠다.

 

모듈을 사용하기위해 변수로 선언해주고 연결 생성을 위한 createConnection 명령어를 통해 MySQL 계정에 파일을 연결해주었다.

const mysql = require('mysql2');

const conn = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '1234',
    database: 'kdt'
})

 

 

 

데이터베이스를 연결했으니 화면에 데이터가 뜰 수 있도록 불어와야한다.

먼저 저장된 모든 데이터를 불러와 화면에 보이기 위해 select * from visitor 쿼리문을 사용했다.

또한 다른 파일에서도 이 함수를 사용할 수 있도록 exports까지 해주겠다.

exports.allVisitorsList = (cb)=>{
    conn.query('select * from visitor', (err,rows)=>{
        console.log('select *');
        cb(rows)
    })
}

 

 

 

다음으로 방명록을 추가, 삭제, 수정할 수 있는 세부 기능들도 구현해주겠다.

insert into, update, delete 쿼리문을 활용했으며 ?를 활용해 value가 들어갈 자리를 지정해주었다.

//폼에서 받은 데이터 추가하기
exports.postVisitor = (data, cb)=>{
    const sql = 'insert into visitor (name,comment) values (?,?)'
    const values = [data.name, data.comment]
    conn.query(sql, values, (err,rows)=>{
        cb(rows.insertId)
    })
}

// 폼에서 1명의 방문자 보기
exports.getShowAvisitor = (id, cb)=>{
     const sql = 'SELECT * FROM kdt.visitor where id=?';
     conn.query(sql, id, (err, rows) => {
        if (err) throw err;
        cb(rows[0]);
    })
}

// 수정버튼 후 바뀐내용으로 변경
exports.patchContent = (data, cb)=>{
    const sql ="UPDATE visitor SET name =? , comment =? WHERE id = ?";
    const values=[data.name, data.comment, data.id]
    conn.query(sql, values, (err, rows)=>{
       cb(rows)
    })
}

//삭제버튼 후 데이터 삭제
exports.deletedb = (id, cb)=>{
    const sql ="delete from visitor WHERE id = ?";
    conn.query(sql, id, (err, rows)=>{
       cb(rows)
    })
}

 

 

 

model 폴더에서 데이터 연결을 진행해준 후 controller 폴더에서 데이터를 받고 보내고 렌더링하는 동작들을 구현해주어야한다.

가장 먼저 연결한 데이터를 받아오기 위해 model폴더를 사용하겠다고 선언해줬다.

 

모든 방문자 목록이 보여지는 visitor.ejs 파일을 렌더링 해주고, 방문자를 추가, 수정, 삭제하는 데이터를 받아서 ejs파일로 데이터를 객체형태로 보낸다.

exports.allVisitorsList = (req,res)=>{
    Visitor.allVisitorsList(result=>{
        res.render('visitor', {data:result})
    })
}

exports.addVisitor = (req,res)=>{
    const {name,comment} = req.body;
    Visitor.postVisitor(req.body, (result)=>{
        res.send({id:result, name, comment})
    })
}

exports.getShowAvisitor=(req,res)=>{
    Visitor.getShowAvisitor(req.params.id, (result) =>{
      res.send(result)
    })
}
 
exports.patchVisitor =(req,res)=>{
    Visitor.patchContent(req.body, (result)=>{
     res.send(result)
    })
 }
 
exports.deleteVisitor=(req,res)=>{
    Visitor.deletedb(req.body.id, (result)=>{
      res.send('삭제성공')
    })
}

 

 

 

다음으로 controller와 경로를 연결하기 위한 작업은 routes 폴더에서 수행하게된다.

따라서 브라우저에서 특정한 경로가 들어오면 controller에 있는 동작이 수행될 수 있도록 연결 다리를 만드는 것이다.

라우터를 만든 후에는 반드시 실행파일인 app.js에서 활용할 수 있도록 모듈을 exports 해주어야 한다.

=> 잊으면 안된다..!!! 빠트리고 안적게 되면 경로 오류가 생긴다...🔥

const express = require('express');
const router = express.Router();
const controller = require('../controller/Cvisitor');
 
router.get('/', controller.main)
router.get('/visitors', controller.allVisitorsList)
router.post('/addvisitor', controller.addVisitor)
router.get('/visitormodify/:id', controller.getShowAvisitor)
router.patch('/visitoreditDo', controller.patchVisitor)
router.delete('/visitordelete', controller.deleteVisitor)

module.exports = router;

 

 

 

마지막으로 ejs파일에 있는 버튼들이 작동하도록 하는 스크립트 코드를 작성해줘야한다.

지금까지 동작과 기능은 정의해주었지만 버튼에 동작을 연결해주지 않았기 때문이다.

 

먼저, 동작을 정의해주어야할 요소들을 불러와준다.

const tbody = document.querySelector('tbody');
const btnGroup = document.querySelector('#button-group');

 

 

 

다음으로 등록 버튼에 대한 동작을 정의했다.

폼이 채워지지 않았다면 경고창이 뜨는 유효성 검사를 먼저 실행했고, axios를 활용해 데이터들이 화면에 보일 수 있도록 코드를 작성했다.

마지막엔 작성한 폼 또한 초기화 시켜 다시 작성할 수 있도록 했다.

function createVisitor(){
    const form = document.forms['visitor-form'];
    if (form.name.value.length === 0 || form.comment.value.length === 0) {
        alert('이름 또는 방명록 기입해주세요!');
        return;
    }
    if (form.name.value.length > 10) {
        alert('이름은 10글자 미만입니다!');
        return;
    }

    axios({
        method: 'post',
        url: '/addvisitor',
        data: {
            name: form.name.value,
            comment: form.comment.value
        }
    }).then(res=>{
        const data = res.data;
        const html = `
            <tr id="tr_${data.id}">
                <td>${data.id}</td>
                <td>${data.name}</td>
                <td>${data.comment}</td>
                <td><button type="button" onclick="editVisitor(${data.id})">수정</button></td>
                <td><button type="button" onclick="deleteVisitor(this, ${data.id})">삭제</button></td>
            </tr>
        `;
 
        tbody.insertAdjacentHTML('beforeend', html)
        form.reset();
    })
}

 

 

다음으로 한명의 방명록을 수정하려 할 때 수정 버튼을 누르면 등록 버튼이 변경, 취소 버튼으로 바뀌도록 해주는 코드를 작성했다.

수정 버튼을 누르면 데이터를 변경할 수 있도록 해당 데이터가 폼에 표시되게끔 하는 동작도 정의했다.

이 또한 axios를 활용했다.

function editVisitor(id){
    alert(`찾는 1명의 id=${id}`);

    axios({
        method: 'get',
        url: `/visitormodify/${id}`
    }).then(res=>{
        const {name, comment} = res.data;
        const form = document.forms['visitor-form'];
        form.name.value = name;
        form.comment.value = comment;
    })

    const html = `
        <button type='button' onclick='editDo(${id})'>변경</button>
        <button type='button' onclick='editCancel()'>취소</button>
    `

    btnGroup.innerHTML = html;
}

 

 

위와 비슷하게 변경버튼이나 취소버튼을 누르면 원상태, 즉, 등록버튼으로 되돌아가도록 하는 동작을 만들어주었다.

function editDo(id){
    const form = document.forms['visitor-form'];
    axios({
        method:'patch',
        url:'/visitoreditDo',
        data:{
            id:id,
            name : form.name.value,
            comment: form.comment.value
        }
    }).then(res=>{
        const children = document.querySelector(`#tr_${id}`).children;
        children[1].textContent = form.name.value;
        children[2].textContent = form.comment.value;
        editCancel();
    })
}

function editCancel(){
    const form = document.forms['visitor-form'];
    form.reset();
 
    const html = `<button type='button' onclick='createVisitor()'>등록</button>`;
    btnGroup.innerHTML = html;
}

function deleteVisitor(obj, id){
    if (!confirm('정말 삭제하시겠습니까?')) return;
    axios({
        method:'delete',
        url:'/visitordelete',
        data:{ id:id}
    }).then(res => {
        obj.closest(`#tr_${id}`).remove()
    })
}

 

 

 

따라서 만들어진 결과물은 다음과 같다.

방명록 만들기 실습

 

 

 

728x90

 

 


 

 

2. Sequelize

 

: 자바스크립트 구문을 알아서 sql로 변환해주며, DB 작업을 쉽게 할 수 있도록 도와주는 ORM 라이브러리 중 하나이다.

: sequelize는 지역 설치해줬기 때문에 경로를 주어야만 sequelize를 찾을 수 있다.

=>  .\node_modules\.bin\sequelize 

sequelize 명령어 예시

 

 

sequelize를 설치하고 config폴더에서 데이터 베이스를 연결해준다.

다른 폴더 구조는 MVC와 비슷하다.

 

위에서 만든 방명록을 이번엔 sequelize를 이용해서 만들어보는 실습을 진행했다.

 

 

먼저, 모델 폴더부터 정의했다.

sequelize 모델을 정의하고 user와 visitor모델도 정의했다. mysql에서 정의한 테이블을 sequelize에서도 정의해줘야한다.

const Sequelize = require('sequelize');
const config = require('../config/config.json')["development"];
const db={}

const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
)
 
db.sequelize = sequelize;
db.Sequelize = Sequelize;

db.Visitor = require('./Visitor')(sequelize,Sequelize);
db.User = require('./User')(sequelize,Sequelize);

module.exports = db;

 

// User 모델 정의

const User = (Sequelize, DataTypes)=>{
    const model = Sequelize.define(
        'user', {
            id:{
                type: DataTypes.INTEGER,
                allowNull: false,
                primaryKey: true,
                autoIncrement: true
            },
            userid:{
                type: DataTypes.STRING(20),
                allowNull: false,
            },
            name:{
                type: DataTypes.STRING(10),
                allowNull: false,
            },
            pw:{
                type: DataTypes.STRING(20),
                allowNull: false,
            }
        }, {
            tableName: 'user2',
            timestamps: false
        }
    );
    return model;
}

module.exports = User;

 

// visitor 모델 정의

const Visitor = (Sequelize, DataTypes)=>{
    const model = Sequelize.define(
        'visitor', {
            id:{
                type: DataTypes.INTEGER,
                allowNull: false,
                primaryKey: true,
                autoIncrement: true
            },
            name:{
                type: DataTypes.STRING(10),
                allowNull: false
            },
            comment:{
                type: DataTypes.TEXT('medium')
            }
        }, {
            tableName: 'visitor2',
            freezeTableName: true,
            timestamps: false
        }
    );
    return model;
}

module.exports = Visitor;

 

 

다음으로 위에서 만들었던 것과 비슷하게 controller 폴더의 파일과 routes, views 파일들을 만들어 주면 된다.

이때 다른점은 sequelize 쿼리문을 활용해 코드를 작성한다는 점이다.

 

 

그런의미에서 sequelize 쿼리를 간단히 정리하고 넘어가겠다.

sequelize 쿼리는 sql쿼리와 비교하면서 보면 좋을 것 같다. 의미 파악을 쉽게할 수 있다.

 

  • findAll() = select * from
  • findOne() = select 1 from
  • create() = insert into
  • update() = update from
  • destroy() = delete from

 


 

 

MVC-MySQL을 연결해 방명목을 추가하고 삭제 및 변경 취소까지 가능한 데이터베이스 페이지를 만들어 볼 수 있었고, MVC 구조는 이제 어느정도 이해가 되었으나 데이터베이스를 연결해서 스크립트 코드를 작성하는 부분은 복습이 필요할 것 같다.

버튼에 대한 스크립트 코드와 데이터베이스에 기능하는 스크립트 코드 등 작성해야할 것이 많이 있기 때문에 스크립트 코드를 제대로 이해하고 작성하는 연습을 해봐야겠다.

뿐만아니라 sequelize를 이용한 코드 작성 방법도 구조를 잘 파악해야할 것 같다.
점점 내용이 많아지면서 이해 속도가 느려지긴 했지만 계속해서 하다보면 코드에 익숙해지고 혼자서도 원하는 기능을 만들 수 있지 않을까 기대해 본다.

화이팅화이팅💪💪💪
728x90