본문 바로가기

Development/Web

Express + MVC pattern (3) - 회원가입 기능 구현 및 완료

이어가며

지난 글에서는 컨트롤러를 구현부터 모델로 로그인 기능을 구현하는 부분까지 정리하였다. 이번에는 모델로 회원가입 기능 구현과 최종 결과를 정리해보도록 하겠다.

회원가입 기능 구현

🔗 소스코드 : v1.0.7-model2

지난 글의 로그인 기능 구현에 이어서 이번에는 회원가입 기능을 구현해보도록 하겠다. 회원가입 시 기존의 데이터에 새로운 데이터를 추가하되, 아이디가 이미 존재하는 경우에는 회원가입이 진행되지 않도록 해야한다.

모든 사용자 데이터 조회

이를 위해 아래와 같이 코드를 작성하여 기존의 모든 데이터를 불러오도록 하였다.

/* ./app/src/models/UserStorage.js */

"use strict";

const fileSystem = require('fs').promises;
const filePath = './src/database/users.json';

class UserStorage {
    // ... 생략 ...

    static #getUsers(data, fields) {
        const users = JSON.parse(data);
        if (!fields.length) return users;

        const newUsers = [];
        users.forEach(user => {
            const newUser = {};
            fields.forEach(field => {
                if (user.hasOwnProperty(field)) {
                    newUser[field] = user[field];
                }
            })
            newUsers.push(newUser);
        });
        return newUsers;
    };

    static async getUsers(...fields) {
        return fileSystem.readFile(filePath)
            .then(data => {
                return this.#getUsers(data, fields);
            })
            .catch(console.error);
    };
};

module.exports = UserStorage;

새로운 사용자 정보 저장

이어서 아래와 같이 코드를 작성하여 새롭게 받은 사용자 정보를 기존의 데이터베이스 파일에 덮어씌우도록 구현하였다.

/* ./app/src/models/UserStorage.js */

"use strict";

const fileSystem = require('fs').promises;
const filePath = './src/database/users.json';

class UserStorage {
    // ... 생략 ...

    static async save(client) {
        const users = await this.getUsers();
        if (users.find(user => user.id === client.id)) {
            throw "이미 존재하는 아이디입니다.";
        }
        users.push(client)
        await fileSystem.writeFile(filePath, JSON.stringify(users));
        return { success: true };
    };
};

module.exports = UserStorage;

코드를 보면 알 수 있듯이 아이디가 이미 존재하는 경우 예외 처리를 발생시키도록 하였다. 이렇게 발생한 예외 처리는 User 클래스에서 적절하게 사용하도록 할 것이다.

회원가입 메소드 구현

위에서 언급한대로 User 클래스에서 try ~ catch 문을 통해 새로운 사용자 정보를 저장하는 회원가입 메소드를 아래와 같이 구현하였다.

/* ./app/src/models/Users.js */

"use strict";

const UserStorage = require("./UserStorage");

class User {
    constructor(body) {
        this.body = body;
    };

    // ... 생략 ...

    async signup() {
        const body = this.body;
        try {
            return await UserStorage.save(body);
        } catch (err) {
            return { success: false, message: err };
        }
    };
};

module.exports = User;

코드를 보면 알 수 있듯이 회원가입에 성공하면 그 결과를 UserStorage.save() 결과인 { success: true }를 반환하고, 예외가 발생하면 { success: false, message: 예외 처리 메시지 }를 반환하도록 하였다.

컨트롤러 코드 수정

위의 과정을 통해 반환된 결과를 컨트롤러를 통해 받아올 수 있도록 아래와 같이 코드를 수정하였다.

/* ./app/src/routes/home/index.controller.js */

"use strict";

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

const render = {
    // ... 생략 ...
};

const process = {

    // ... 생략 ...

    signup: async (req, res) => {
        const user = new User(req.body);
        const response = await user.signup();
        return res.json(response);
    }
};

module.exports = { render, process };

여기까지 회원가입 시 서버가 처리할 부분을 구현하였다.

클라이언트 측 응답 처리

이어서 서버의 응답에 따른 로직을 수행하기 위해 클라이언트 측 코드를 아래와 같이 수정하였다.

/* ./app/src/public/js/home/signup.js */

// ... 생략 ...

function signup() {
    const req = {
        id: id.value,
        name: name.value,
        passwd: passwd.value
    };

    fetch("/signup", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(req)
    })
        .then(res => res.json())
        .then(res => {
            const { success, message } = res;
            if (success) return location.href = '/login';
            alert(message);
        })
        .catch(console.error);
};

코드를 보면 알 수 있듯이 회원가입에 성공({ success : true })하는 경우에는 로그인 화면으로 이동하도록 하였고, 회원가입에 실패한 경우에는 메시지를 띄우도록 하였다. 추가적으로 클라이언트 측에서 서버로 회원가입 요청 시 아래와 같은 상황이 있을 수 있다.

  • 아이디를 입력하지 않음
  • 이름을 입려하지 않음
  • 비밀번호를 입력하지 않음
  • 비밀번호와 비밀번호 확인 정보가 일치하지 않음

이와 같은 경우 정규식을 사용하여 처리할 수 있는데, 실습을 위해서 아래와 같이 간단하게 로직을 추가하였다.

/* ./app/src/public/js/home/signup.js */

// ... 생략 ...

function signup() {
    if (id.value === "") return alert('아이디를 입력하세요.');
    if (name.value === "") return alert('이름을 입력하세요.');
    if (passwd.value === "") return alert('비밀번호를 입력하세요.');
    if (passwd.value !== confirmPasswd.value) return alert('비밀번호가 일치하지 않습니다.');

    // ... 생략 ...
};

마치며

여기까지 MVC 패턴을 적용한 express 웹 서버를 구현해보았다. 이 과정을 총 3번 정도 반복해서 구현해보았는데, 추상적인 MVC 패턴의 개념이 어느정도 머릿속에 그려지는 것 같다. 다음에는 세션, JWT 로그인 기능을 구현해보며 글로 정리하여 남길 예정이다.