백엔드

[EXPRESS - 로그인 기능 구현] MVC 분리하기

김채연채연 2023. 8. 10. 21:59
//모듈
const express = require("express");
const app = express();

const PORT = 3000;

// 라우팅
const home = require("./routes/home");

// 앱 세팅
app.set("views" , "./views");
app.set("view engine", "ejs");

app.use("/", home);
//use 는 미들웨어를 등록해주는 메서도

app.listen(PORT , () => {
  console.log("서버 가동")
})

로그인 구현 기능에 앞서, 기본적인 틀을 만들어 볼겁니다 !

참고로 저도 백엔드를 처음 해보는거라 이것저것 찾아보며 공부하는 중 이라는 점 참고 부탁드립니다 ㅎㅎ

 

먼저, 앞서 작성한 게시글과 같이 express 를 활용하여 서버를 띄워줬는데 로그인을 하려면 기본적인 로그인 창이 필요합니다. 이때 ejs 라는걸 사용했는데 ejs 는 html 과 비슷한(거의 똑같은) 기능을 하는 엔진 이라고 합니다.

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

// 앱 세팅
app.set("views" , "./views");
app.set("view engine", "ejs");

app.get('/' , (req, res) => {
  res.render("home/index")
});

app.get('/login', (req, res) => {
  res.render("home/login")
})

app.listen(3000 , () => {
  console.log("서버 가동")
})

 

우선 app.js 의 전체 코드는 이러한데, express 관련 설명은 이전 게시글에서 다뤘기에 넘어가겠습니다 !

app.set("views" , "./views");

이 부분은 코딩한 내용이 담겨있는 곳의 위치를 지정해준겁니다. /views 디렉토리 안에 html 로 짜두었던 코드가 있습니다.

app.set("view engine", "ejs");

이건 view engine 설정을 ejs 로 하겠다는 뜻인데, view engine 이 뭐냐면 이름처럼 웹 애플리케이션에서 사용자에게 보여주는 동적인 부분을 만들기 위한 템플릿 입니다.

 

이제 이후의 라우팅 기능을 활용하여 각 경로에 맞는 파일을 렌더링 하게 됩니다 !

 

// login.ejs

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="text" placeholder="아이디"><br />
  <input type="text" placeholder="비밀번호"><br />
  <button>로그인</button>
</body>

</html>
index.ejs

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  여기는 루트 입니다.
</body>

</html>

이건 루트와 로그인 코드 입니다. 이렇게 하면 아래 사진처럼 경로에 따라 잘 뜹니당

하지만, app.js 를 보면 코드가 살짝 지저분하기때문에 라우팅분리 라는걸 해보겠습니다 !

 

앞서 views 폴더를 생성한것과 비슷하게

routes 폴더를 생성해주고 app.js 에 적어뒀던 라우팅 관련 코드를 저쪽으로 잘라넣어줬습니다 ! 
하지만, app.js 가 아닌 index.js 이니까 조금 수정해줘야합니다.

"use strict";

const express = require("express");
const router = express.Router();

router.get("/", (req, res) => {
  res.render("home/index");
});

router.get("/login", (req, res) => {
  res.render("home/login");
});

module.exports = router ; // 해당 모듈을 외부로 던져줌

이렇게 ! 

 

여기서 router 말고 app으로 쓰면 안되는지 궁금하실 수 있습니다. 저도 궁금했거든요

먼저, router 는 미들웨어와 라우팅 로직을 하나의 모듈로 구성하여 관리할 수 있도록 도와주는 객체입니다. 여러개의 라우팅 경로를 묶어서 모듈화하고, 해당 모듈을 다른 파일로 분리하여 코드의 가독성, 유지보수성을 높일 수 있습니다.

app 은 express 애플리케이션 그 자체를 의미하며, 서버의 전체적인 설정, 중간에서 사용되는 미들웨어 등을 관리하는데에 사용됩니다! 주로 작은 규모의 애플리케이션에서 사용됩니다.

 

결국은 router 대신 app 을 사용해도 되긴 하지만 코드를 모듈화하고 관리하는 측면에선 router 를 사용하는것이 좋다고 합니다 !

//모듈
const express = require("express");
const app = express();

const PORT = 3000;

// 라우팅
const home = require("./routes/home");

// 앱 세팅
app.set("views" , "./views");
app.set("view engine", "ejs");

app.use("/", home);
//use 는 미들웨어를 등록해주는 메서도

app.listen(PORT , () => {
  console.log("서버 가동")
})

그 후 app.js 에서 라우팅 파일을 연결하지 않았기에 연결해줬습니다.

home 변수에 해당 경로에 있는 모듈을 불러와주고,  app.use 를 이용해 미들웨어를 등록해줍니다. 루트경로로 들어오는 모든 요청을 home 으로 보내주게 됩니다 !

 

다음으로 컨트롤러 분리를 해보겠습니다. 위에 routes/home 의 index.js 에서

router.get("/", (req, res) => {
  res.render("home/index");
});

router.get("/login", (req, res) => {
  res.render("home/login");
});

요부분을 분리해주는거랍니다 !

같은 위치에 home.ctrl.js 파일을 하나 더 생성해주고

const home = (req, res) => {
  res.render("home/index");
}

const login = (req, res) => {
  res.render("home/login");
}

module.exports = {
  home,
  login,
};

이렇게 코딩했습니다. 원래 index.js 에 있었던 컨트롤러 부분을 좀 더 명시적으로 바꿔주기 위해 저렇게 모듈로 만들어줬습니다.

"use strict";

// 라우팅 분리

const express = require("express");
const router = express.Router();

const ctrl = require("./home.ctrl");

router.get("/", ctrl.home);
router.get("/login", ctrl.login);

module.exports = router ; // 해당 모듈을 외부로 던져줌

그 후에 다시 index,js 에서 파일을 불러와주면 아까보다 더 간단하고 명시적인 코드가 완성됩니다 !

갑자기 왔다갔다 복잡해서 한번 스토리텔링 형식으로 정리를 해보겠습니다 !
원래는 가장 처음에 ejs 를 사용하지도 않았을땐 app.js 내에 <h1>홈입니다.<h1> 이런 html 코드가 그대로 들어가있었습니다. 굉장히 좋지 않은 코드죠 ,, ! 그래서 이걸 views 라는 폴더를 만들어서 분리해줬습니다.

index 와 login 두개니까 두개의 ejs 파일을 만들어서 각각 내용을 넣어줘야겠죠 ! 

 

다음으론 라우팅 부분도 분리를 해줍니다. 

routes/home 폴더 내부에 index.js 파일을 생성해서 처음에 app.js 에 있던 라우팅 부분을 옮겨줍니다. 그리고 동일하게 express 를 사용하는데 여기서 app 이 아닌 router 를 활용해 코드를 일부 수정해줍니다.(module.exports 를 사용해 외부로 보내주는 것 잊지말기 !)

다시 app.js 에서 라우팅한 모듈을 불러와주고 루트 경로로 요청이 들어오면 그걸 불러온 모듈쪽으로 모두 넘겨주면 됩니다.

 

이제 마지막으로 컨트롤러를 분리해줍니다.

패턴 자체는 비슷합니다. 새로 routes/home 내부에 파일을 생성해서 각각 변수를 선언해 변수에 들어온 요청을 처리하는 부분을 담아주고 모듈을 밖으로 보내줍니다. 

 

 

[분리를 하면 밖으로 내보내준다 / 모듈을 불러와 사용할땐 변수로 다시 선언해서 사용한다]

 

마지막으로 서버를 켜는 부분도 분리해주겠습니다 ! 

app.listen(PORT, () => {
  console.log("서버 가동");
});

바로 요부분 ~!

그러기 위해선 저 PORT 부분도 함께 가져와야 합니다. 그리고 app 을 app파일에서 가져와 선언해줍니다.

const app = require("../app");
const PORT = 3000;

app.listen(PORT, () => {
  console.log("서버 가동");
});

이렇게 ! app.js 에서도 모듈을 밖으로 보내주는거 잊지 않기 !

이제 실행을 app.js 가 아닌

이렇게 분리해준 파일로 해주면 됩니다 !