실습 - MVC의 실습

YoonSuk Choi·2024년 12월 4일

6주차_MVC 실습

목록 보기
1/4

MVC 패턴을 활용한 동적 폼 로그인 실습

핵심 내용

  • 동적폼 로그인 실습 문제를 MVC 패턴으로 변경해보기
  • 기존 'app.js'에서 변수로 'id'와 'pw'를 선언했던 부분 'model/User.js'로 이동 후 'exports'
  • 기존에 하나의 파일에서 관리되던 코드 구조를 역할별로 분리하여 유지보수성과 재사용성을 높이는 것이 목표이다.

MVC의 사용

  • Model (User.js)

    • 사용자 데이터를 관리하는 부분입니다. 사용자 정보(realId, realPw)를 담고 있으며, 이를 외부에서 접근할 수 있도록 exports.userInfo() 메서드로 제공하였습니다.
  • View (index.ejs)

    • 사용자 인터페이스를 담당하는 부분입니다. 로그인 폼을 제공하며, 유효성 검증 및 Axios를 사용하여 데이터를 Controller로 전송합니다.
  • Controller (Cuser.js)

    • Model과 View를 연결하는 역할을 합니다. View에서 전달받은 요청 데이터를 Model과 비교하여 결과를 반환하는 로직을 포함하고 있습니다.

간략한 폴더 구조

project-MVC
├── controller/
│   ├── Cuser.js
├── model/
│   ├── User.js
├── routes/
│   ├── user.js
├── views/
│   ├── index.ejs
└── app.js

app.js 실행 결과

  1. 홈 화면

    • 경로에 접속하면 로그인 폼이 표시
  2. 로그인 기능

    • 사용자가 아이디와 비밀번호를 입력한 후 "로그인" 버튼을 클릭하면, 입력된 데이터가 /login 경로로 POST 요청됩니다.
    • Controller(Cuser.js)는 Model(User.js)의 사용자 정보를 이용하여 입력값과 비교합니다.
    • 로그인 성공 시 {"isSuccess": true, "userId": "apple"} 형식의 JSON 데이터를 반환하고, 실패 시 {"isSuccess": false} 데이터를 반환합니다.
  3. 결과 표시

    • 로그인 성공 or 실패 메시지가 표시됩니다.

사용한 주요 기능

  1. Express를 이용한 서버 구성

    • app.js에서 Express를 사용하여 미들웨어와 라우팅을 설정하고, 서버를 실행합니다.
  2. EJS 템플릿 엔진

    • set("view engine", "ejs")를 통해 EJS를 템플릿 엔진으로 설정하였습니다.
    • index.ejs를 이용하여 로그인 폼을 작성하였습니다.
  3. Axios

    • View에서 데이터를 Controller로 전송하기 위해 Axios를 사용하였습니다.
    • 비동기 요청을 통해 사용자 입력값을 /login 경로로 POST 요청합니다.
  4. MVC 구조화

    • Model: User.js에서 사용자 정보를 관리.
    • View: index.ejs에서 UI 렌더링 및 사용자 인터랙션 관리.
    • Controller: Cuser.js에서 로직 처리 및 응답 제어.
  5. 데이터 검증 및 응답

    • Controller에서 사용자 입력값과 Model 데이터를 비교하여 결과를 반환.
    • 성공 시 사용자 ID와 성공 메시지 반환, 실패 시 실패 메시지 반환.

사용한 코드

app.js

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

// 미들웨어 설정
app.set("view engine", "ejs");
app.set("views", "./views");

app.use(express.urlencoded({ extended: false }));
app.use(express.json());

// 라우터 연결
const userRouter = require("./routes/user");
app.use("/", userRouter);

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

index.ejs

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>MVC 실습</title>
  </head>
  <body>
    <h3>동적폼 로그인 실습문제를 MVC 패턴으로 변경해보기</h3>
    <form name="login">
      <label for="userId">
        <span>아이디</span>
        <input type="text" name="userId" id="userId" required />
      </label>
      <br />
      <label for="userPw">
        <span>비밀번호</span>
        <input type="password" name="userPw" id="userPw" required />
      </label>

      <br />
      <button type="button" onclick="clickLogin()">로그인</button>
    </form>
    <div class="login-result"></div>
  </body>

  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    function clickLogin() {
      const form = document.forms["login"];
      const loginResult = document.querySelector(".login-result");
      const data = {
        userId: form.userId.value,
        userPw: form.userPw.value,
      };

      console.log(data);
      // 유효성 검증
      console.log(form.userId.checkValidity());
      console.log(form.userPw.checkValidity());
      if (!form.userId.checkValidity() || !form.userPw.checkValidity()) {
        loginResult.innerText = "아이디와 비밀번호는 필수입니다.";
        return;
      }

      axios({
        url: "/login",
        method: "post",
        data: data,
      }).then((res) => {
        console.log(res.data);
        // {isSuccess: false}
        // {isSuccess: true, userId: 'banana'}
        if (res.data.isSuccess) {
          loginResult.textContent = `${res.data.userId}님 로그인 성공~!😊`;
          loginResult.classList.add("success");
          loginResult.classList.remove("error");
        } else {
          loginResult.textContent = "아이디 또는 패스워드 오류입니다🥺";
          loginResult.classList.add("error");
          loginResult.classList.remove("success");
        }
      });
    }
  </script>
</html>

user.js

const express = require("express");
const router = express.Router();
const controller = require("../controller/Cuser");

// GET /
router.get("/", controller.main);

// POST /login
router.post("/login", controller.login);

module.exports = router;

User.js

exports.userInfo = () => {
  return {
    realId: "apple",
    realPw: "12345",
  };
};

Cuser.js

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

exports.main = (req, res) => {
  res.render("index");
};

exports.login = (req, res) => {
  console.log(req.body);
  const { realId, realPw } = User.userInfo();

  if (realId === req.body.userId && realPw === req.body.userPw) {
    res.send({ isSuccess: true, userId: req.body.userId });
  } else {
    res.send({ isSuccess: false });
  }
};

profile
Name : 최윤석(YoonSuk Choi)

0개의 댓글