[포스코x코딩온] 웹개발자 풀스택 과정 6주차 회고록 - Mysql과 연동하여 비동기 통신하기(2) - MVC모델

Mysql 사용법을 알고 싶다면 아래 블로그를 참고하세요!!

 

[포스코x코딩온] 웹개발자 풀스택 과정 6주차 회고록 - Mysql과 연동하여 비동기 통신하기(1) - Mysql

🤔 어떤 실습을 할 것인가?? 이번엔 처음으로 DB와 연동하여 비동기 통신을 할 것이다. 백엔드에서 가장 해보고 싶었던 실습이다. CRUD가 어떤 식으로 작동을 하며 좀 더 mvc모델을 적극적으로 배

jin99.tistory.com

 

🤔 어떤 실습을 할 것인가??

이번엔 처음으로 DB와 연동하여 비동기 통신을 할 것이다. 백엔드에서 가장 해보고 싶었던 실습이다. 

CRUD가 어떤 식으로 작동을 하며 좀 더 mvc모델을 적극적으로 배울 수 있는 실습이 될 것이다.

 

-실습내용-

1. 사용자가 회원가입을 한다.

2. 로그인 할 때 정보가 일치하면 바로 프로필 페이지로 이동한다.

3. 프로필 페이지에서 정보를 수정하고 싶으면 수정하고 삭제하고 싶으면 삭제한다.

4. 이 모든 것이 DB와 연동되서 실행된다.

 

이전 블로그에서 mysql을 설치 하고 테이블까지 만들었으니 이젠 직접 코드를 짜보면서 설명하겠다.

내가 해보면서 어려움을 느꼈던 점은 mysql과 연동이 된다는 점과 mvc구조 파악하기, 로그인 정보가 일치하면 바로 프로필 페이지에 로그인 정보가 입력된다는 점이다.

이 3가지를 중점으로 설명하겠다.


1️⃣ index.js 만들기

const express = require("express");
const app = express();
const PORT = 8000;

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

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

//404
app.use("*", (req, res) => {
  res.render("404");
});

app.listen(PORT, () => {
  console.log(`http://localhost:${PORT}`);
});

 

다른건 다 똑같지만 나는 기본 주소설정을 localhost:8000/user로 설정하겠다. 

 

2️⃣ MVC 로직 이해하기

Nodejs에 mysql을 설치했다면 model에 가서 모듈을 불러와야 한다.

이후 내가 만든 DB와 연동을 시켜줘야 한다.

 

const mysql = require("mysql");

//mysql 연결
const conn = mysql.createConnection({
  host: "localhost",
  user: "name",
  password: "1234",
  database: "kdt9",
  port: 3306,
});
conn.connect((err) => {		// 에러시 에러 메시지 출력
  if (err) {
    console.log(err);
    return;
  }
  console.log("connect");	// 성공시 
});

 

이전 블로그에서 만든 DB정보를 입력해준다.

user  - mysql에서 만든 호스트 이름
database - 스키마 이름

 

컨트롤러에서 받은 값을 Model에서 처리해줘야 한다.

 

● Model

 

exports.post_signup = (data, callback) => {
  const query = `INSERT INTO user_practice (userid, pw, name) VALUES ('${data.userid}', '${data.pw}', '${data.name}')`;
  conn.query(query, (err, rows) => {
    console.log("post_signup", rows);
    callback();
  });
};

 

이 코드는 클라이언트가 회원가입을 한 경우 데이터를 DB에 추가하는 상황이다. 

Controller에서 매개변수로 req.body를 보내주고 클라이언트에게 정보가 잘 저장되었다는 정보를 넘겨주기 위해 어떤 함수를 실행했을 것이다. 

그래서 post_signup의 인자로 data와 콜백함수를 갖는다. 

 

아래의 Controller를 확인해 보자

 

● Controller

 

const User = require("../model/User");

exports.post_signup = (req, res) => {
  //model
  User.post_signup(req.body, () => {
    res.send({ result: true });
  });
};

 

먼저 모듈로 내보내진 Model을 불러온다.

 

컨트롤러는 프론트에서 받은 값을 req.body로 받아온다 (POST이기 때문)

이 값을 Model로 보내주고 전달이 성공했을 시 다시 클라이언트에게 result:true라는 객체를 보내준다.

 

 

● View

 

function register() {
            const form = document.forms['form-register'];
            axios({
                method: 'POST',
                url: '/user/signup',
                data: {
                    userid: form.userid.value,
                    pw: form.pw.value,
                    name: form.nickname.value,
                },
            }).then((res) => {
                console.log('res', res);
                if (res.data.result) {
                    alert('회원가입을 축하합니다');
                    window.location.href = '/user/signin';
                }
            });
        }

 

프론트에서는 조건문을 통해 이 객체가 제대로 왔으면 alert창을 띄워주고 로그인 페이지로 이동한다.

 

내가 이해했을 때는 mvc로직이 아래와 같이 실행되는 것 같다.

 

 

3️⃣ query문 작성하는 방법

exports.post_signup = (data, callback) => {
  const query = `INSERT INTO user_practice (userid, pw, name) VALUES ('${data.userid}', '${data.pw}', '${data.name}')`;
  conn.query(query, (err, rows) => {
  	if(err){
    	console.log(err);
        return;
    }
    console.log("post_signup", rows);
    callback();
  });
};

 

쿼리문은 CLI에서 작성한 그대로 써주면 된다. 

여기서 중요한 점은 문자 데이터 값을 쓸 때 꼭 따옴표('')를 써줘야 한다는 점이다. 잊고 쓰는 경우가 많으니 주의하자!

 

조건문을 통해 오류가 발생하면 오류 메시지를 띄우고 아니면 콜백함수를 실행시켜 준다.

여기서 rows는 DB에 저장된 값을 반환한다. 

 

4️⃣ 회원정보 불러오기

로그인 페이지에서 DB에 저장된 id와 pw를 입력하면 프로필 페이지로 넘어간다. 

프로필 페이지에는 id와 pw를 수정하거나 삭제할 수 있다. 그리고 프로필 페이지에는 로그인에서 입력한 id,name,pw를 입력 된 체로 나온다. 

 

내가 하면서 어려움을 느낀점은 프로필 페이지에 바로 회원정보를 띄우는 것이었다.

어떻게 하나 물어보니 정적 폼을 이용해서 바로 값을 전달해주면 된다고 하셨다. 이때 동적 폼의 userid와 정적폼의 userid를 같게해서 DB에서 userid를 찾아서 회원정보를 찾아오는 방법이었다. 

 

숨긴 폼

 

//프론트
const form_profile = document.forms['form-profile'];
form_profile.userid.value = form.userid.value;
form_profile.submit();

 

로그인 폼 아래 숨겨진 폼을 넣어서 로그인 버튼을 클릭하면 위에 폼과 아래 폼의 userid를 같게 한 후 /user/profile 에 보내준다.

 

// Routes
router.post("/profile", controller.post_profile); // 프로필 정보 확인하기

 

주소를 /user/profile로 보냈으니 라우터에서 연결해준다.

 

// Controller
exports.post_profile = (req, res) => {
  User.post_profile(req.body, (result) => {
    if (result.length > 0) {
      res.render("profile", { data: result[0] });
    }
  });
};

 

컨트롤러에서는 프론트에서 받은 userid값을 받아서 모델로 다시 보내준다.

모델에서 쿼리문을 실행했을 때 나온 값을 보내줄 것이다. 이 값은 회원정보가 될 것이다. 근데 왜 result[0]이냐고?? 이건 아래에서 설명을 하겠다. 이 회원정보를 다시 프론트로 넘겨준다.

 

// Model
exports.post_profile = (data, callback) => {
  const query = `SELECT * FROM user_practice WHERE userid='${data.userid}' `;
  conn.query(query, (err, rows) => {
    console.log("post_profile", rows);
    callback(rows);
  });
};

 

모델은 컨트롤러에서 받은 userid값을 가지고 회원정보를 찾는 쿼리문을 작성한다. 쿼리문을 실행하고 성공하면 콜백함수를 실행시켜 준다. 콜백함수의 매개변수인 rows에는 쿼리문의 결과값이 저장된다. 

 

rows의 값

 

위에 컨트롤러에서 페이지를 렌더링하고 객체를 보내줬다. 객체를 보낼 때 왜 result[0]과 같이 보냈냐면 쿼리문을 실행하면 배열 형태로 값이 전달되기 때문이다. 

 

/ 프로필 페이지
<form name="form-profile">
    <input type="hidden" id="id" value="<%= data.id %>" />
    <input type="text" id="userid" value="<%= data.userid %>" readonly /><br />
    <input type="password" id="pw" value="<%= data.pw %>" /><br />
    <input type="text" id="nickname" value="<%= data.name %>" /><br />
    <button type="button" onclick="profileEdit()">수정</button>
    <button type="button" onclick="profileDelete('<%= data.id %>')">삭제</button>
</form>

 

프로필 페이지에서 ejs 방식을 써서 회원정보를 보여준다.