간단한 회원가입 기능을 MVC 패턴으로 구현해보기

dev_jubby·2022년 8월 4일
0

Node.js

목록 보기
2/8
post-thumbnail

회원가입을 하면 info.txt 파일에 "//"로 구분하여 정보가 저장되도록 하고, 해당 파일 정보로 로그인이 되도록 하기


먼저, npm(node package manager)를 설치한다.

npm init

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

npm install express
npm install ejs
npm install body-parser


MVC 패턴에 필요한 폴더를 생성해주고 main index.js 파일을 생성한다.

/* 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("/", router); 


app.get("/", function(req,res){
    res.send("Index");
})

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


User model을 생성한다. post_join()은 회원가입 button을 눌러 POST 형식으로 폼 전송이 되었을 때 info.txt 파일에 회원정보를 작성되게 구현하고, post_login()은 info.txt 파일에 저장되어 있는 정보를 읽어와서 로그인이 되도록 한다.

/* ./model/User.js */
const fs = require("fs").promises;


exports.post_join = function( data ){
    // console.log( data );
    const {id, name, email, phoneNumber, password } = data;

    fs.appendFile("./info.txt", `${id}//${name}//${email}//${phoneNumber}//${password}\n`, (err) => {
        if (err) {
            console.log(err);
            res.status(400).send("err!!");
        }
    });
}

exports.post_login = async function( data ){
    var buffer = await fs.readFile("./info.txt");
    return buffer.toString();
}

UserController.js 파일에서 각 경로에 따른 처리를 처리한다. join()은 처음 회원가입 화면으로 rendering되게 했다. post_join()은 User model의 post_join으로 req.body 데이터를 보내서 info.txt 파일을 작성하게 했다. 화면에 name 정보를 띄우기 위해 구조체 형식으로 name 정보를 보냈다. login()은 처음 로그인 화면이며, post_login()은 info.txt 파일에 있던 정보를 model를 통해 불러와 로그인처리 했다.

/* ./controller/UserController.js */
const User = require("../model/User");

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

exports.post_join = (req, res) => {
    User.post_join(req.body);
    res.render( "success_join", {name: req.body.name} );
}


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

exports.post_login = async (req, res) => {
    var data = await User.post_login();
    data = data.slice(0, -1).split("\n");
    // console.log( "data:" , data );

    for (var i=0; i<data.length; i++) {
        var info = data[i].split("//");

        if (info[0] == req.body.id && info[4] == req.body.password) {
            return res.render("success_login", {id: req.body.id, msg: "로그인 되었습니다."})
        }
    }

    return res.render("failed_login", {msg: "로그인 실패하였습니다."})

}

routes 폴더에서 index.js 파일을 생성한다. route 메소드를 사용해서 join(회원가입)과 login(로그인) 경로에 대한 GET 및 POST 메소드에 대해 정의한다.

/*  ./routes/index.js */
const express = require("express");
const userRouter = express.Router();
const user = require("../controller/UserController");

userRouter.get("/join", user.join);
userRouter.post("/join", user.post_join);
userRouter.get("/login", user.login);
userRouter.post("/login", user.post_login); 

module.exports = userRouter; 

view 파일은 아래와 같이 총 5개 파일을 작성했다.




💜 처음 회원가입 view


⚠ 오류

cannot create property '_locals on string '쥬비'

일단 회원가입을 진행하면, "name님 회원가입이 완료되었습니다." 라는 문구를 띄우려고 했는데 갑자기 이런 오류가 발생했다.

ejs.js 파일에서 <%=name%>이라고 받아놓고선, 데이터는 그냥 req.body.name으로 줘서 생긴 오류였다. 그래서 구조체로 {name: req.body.name}으로 데이터를 전달하는 방향으로 코드를 수정했다.


💜 회원가입 성공 view

회원가입이 성공하면 info.txt파일에 정보가 저장된다


💜 로그인 화면


💜 로그인 성공 화면


⚠ 오류

[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

로그인이 성공했을 때, 로그인 성공 view로 이동이 되지만 위와 같은 오류가 발생했다. 이는 서버가 클라이언트에 둘 이상의 응답을 보내려고 할 때 발생하는 오류라고 한다.

/* .controller/UserControler.js */
exports.post_login = async (req, res) => {
    var data = await User.post_login();
    data = data.slice(0, -1).split("\n");
    console.log( "data:" , data );

    for (var i=0; i<data.length; i++) {
        var info = data[i].split("//");

        if (info[0] == req.body.id && info[4] == req.body.password) {
            return res.render("success_login", {id: req.body.id, msg: "로그인 되었습니다."})
        }
    }

    return res.render("failed_login", {msg: "로그인 실패하였습니다."})

}

for문에서 res.render를 이용해서 이미 rendering을 진행했는데, for문이 끝나고 난 후 또 다시 rendering을 시도하기 때문에 서버가 충돌하여 오류 메시지가 표시되었던 것이다. 그래서 코드에 return문을 추가하여 응답이 클라이언트에 전송되면 코드를 종료시킬 수 있도록 수정했다.


💜 로그인 실패 화면

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

0개의 댓글