이어가며
지난 글에서는 컨트롤러를 구현부터 모델로 로그인 기능을 구현하는 부분까지 정리하였다. 이번에는 모델로 회원가입 기능 구현과 최종 결과를 정리해보도록 하겠다.
회원가입 기능 구현
지난 글의 로그인 기능 구현에 이어서 이번에는 회원가입 기능을 구현해보도록 하겠다. 회원가입 시 기존의 데이터에 새로운 데이터를 추가하되, 아이디가 이미 존재하는 경우에는 회원가입이 진행되지 않도록 해야한다.
모든 사용자 데이터 조회
이를 위해 아래와 같이 코드를 작성하여 기존의 모든 데이터를 불러오도록 하였다.
/* ./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 로그인 기능을 구현해보며 글로 정리하여 남길 예정이다.
'Development > Web' 카테고리의 다른 글
API는 무엇인가? REST API는 또 무엇인가? 1분 요약 (0) | 2022.03.17 |
---|---|
Open API 사용 시 발생하는 CORS 이슈, 원인과 해결 방법 정리 (0) | 2022.02.25 |
Express + MVC pattern (2) - Contoller 기능 구현, DB 구축, fetch, Model로 구현한 로그인 처리 (0) | 2022.02.22 |
Express + MVC pattern (1) - 프로젝트 초기 설정, View 기능 개발 (0) | 2022.02.22 |
Node.js의 라이브러리 http와 express로 구현한 서버와 이 둘의 차이점 (0) | 2022.02.22 |