갑자기 node.js를 공부하게 된 이유는
작은 프로젝트를 할 때마다 모든 웹에는 있는 기능(로그인, 회원가입, 찜 등등..) 을 구현을 못하고 화면단만 구현하다보니까 데이터 저장하는게 필요하다는 것을 느끼게 되었다
그래서 깊게는 못하겠지만, 간단하게나마 공부하면서 구현해보려고 한다.
데이터베이스 : mongoDB 를 사용하려고 한다.
Node.js와 express와 mongoDB 를 사용해서 한번 구현해 보도록 하겠다!
Node.js에서 스키마(Schema)는 데이터베이스에서 사용되는 개체(객체) 모델을 정의하는 구조라고 설명한다. 간단하게 생각하면 타입스크립트처럼 타입을 정해준다라고 이해하면 된다.
const mongoose = require('mongoose');
const { Schema, model } = mongoose;
// UserSchema 생성
const userSchema = new Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
},
{
timestamps: true, // createAt,updateAt 자동 생성
}
);
const User = mongoose.model('User', userSchema);
module.exports = User;
new Schema({...}, {...}) : mongoose의 Schema 생성자를 사용하여 사용자 데이터 모델의 스키마를 정의의한다.
(여기서 mongoose는 ? MongoDB와 Node.js를 연결해주는 ODM(Object Data Modeling) 라이브러리)
mongoose.model('User', userSchema): User라는 이름의 MongoDB 컬렉션과 userSchema를 연결하여 모델을 생성한다.
이 모델은 MongoDB에서 사용자 데이터를 저장하고 관리하는 데 사용된다.
module.exports = User; : 생성된 User 모델을 외부로 내보낸다. 이를 통해 다른 파일에서 require를 통해 이 모델을 사용할 수 있다.
이렇게 내가 불러오고 받아올 데이터를 스키마를 사용해서 타입을 지정해주고 User라는 모델을 만들어서 다른 곳에서 사용할 수 있도록 하는 과정이다
요청과 응답 사이의 중간 단계에서 동작하는 함수를 의미한다.
미들웨어는 요청을 처리하는 함수이기도 하며, Express와 같은 웹 프레임워크에서는 주로 HTTP 요청과 응답을 다루는 데 사용한다.
미들웨어의 기본 동작 원리
요청과 응답 사이에서 동작: 미들웨어는 클라이언트로부터 서버에 요청이 들어오고, 서버에서 클라이언트로 응답을 보내기 전에 실행된다.
함수 체인: 미들웨어는 함수의 체인으로 연결될 수 있다.
요청이 처리될 때, 미들웨어 함수들이 순차적으로 실행되며 각 미들웨어는 요청 객체(req), 응답 객체(res), 그리고 다음 미들웨어 함수를 호출하는 next 함수를 받다.
next 함수: 각 미들웨어는 next() 함수를 호출하여 다음 미들웨어로 제어를 넘길 수 있다. 이를 통해 여러 개의 미들웨어가 연속적으로 실행될 수 있다.
--> next() 함수를 호출하지 않으면 다음 미들웨어로 넘어가지 않고 요청-응답 주기가 종료된다.
미들웨어의 종류와 사용 예시
내장 미들웨어: Express와 같은 웹 프레임워크에서 기본적으로 제공되는 미들웨어
express.json() 은 요청의 본문(body)을 JSON 형식으로 파싱하는 미들웨어를 의미한다.
const express = require('express');
const app = express();
// 내장 미들웨어 사용 예시
app.use(express.json()); // 요청의 본문을 JSON 형식으로 파싱
유효성검사(사용자 정의) 미들웨어 :
const { validationResult } = require('express-validator');
const validateError = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const firstError = errors.array()[0];
console.log(firstError);
return res.status(400).json({ error: firstError.msg });
}
next(); // 유효성 검사 에러가 없으면 다음으로 제어 넘기기
};
module.exports = {
validateError,
};
유효성 검사를 할 때 express-validator 패키지에서 validationResult을 가져온다.
이 함수는 Express 애플리케이션에서 요청의 유효성 검사 결과를 검색하는 데 사용된다.
이렇게 정의한 validateError를 가지고

/user 엔드포인트에 POST 요청이 들어올 때 사용된다.
이 미들웨어는 요청 바디의 데이터가 유효한지 검사하고, 유효성 검사 오류가 있을 경우 해당 오류를 클라이언트에게 반환하게 된다.
1 . check('name'), check('email'), check('password') 등을 통해 각 필드의 유효성 검사 규칙을 설정한다.
2 . validateError 미들웨어는 배열로 선언된 미들웨어 리스트에 포함되어 있다. 이는 요청이 처리되기 전에 실행된다.
이 미들웨어는 Express의 check() 함수를 사용하여 각 필드에 대한 검증 규칙을 설정하고, validationResult() 함수를 통해 실제 유효성 검사를 수행한다 라고 이해하면 된다!

여기서 app.use(cors())의 cors() 미들웨어는 Cross-Origin Resource Sharing을 설정하여 다른 도메인에서의 요청을 허용을 시켜준다
(처음에 이걸 추가하지 않아서 계속 작동이 안됬었다..!)
여기서, POST /user 요청을 처리하여 회원가입 기능을 수행하는데,

react로 프론트를 구현을 했을 때, 여기서 useForm을 사용해서 form 태그의 유효성 검사를 진행했는데, 이때 form이 실행됬을 때-> onSubmit이 실행되면서,
axios.post('http://localhost:3000/user'data) Axios를 사용하여 HTTP POST 요청을 서버로 보내게 된다.
axios.post
http://localhost:3000/user이렇게
/user로 HTTP POST 요청을 보내면 -> 유효성 검사 (validateError) -> 데이터 저장 하는 순서로 이루어진다고 간단하게 이해하면 될 것 같다!

이렇게 회원가입에 성공하게 되면,
백엔드 구현한 파일 콘솔에

User saved 와 함께 데이터가 저장되는 것을 확인할 수 있다!
여기서 생각해 봐야할 부분은 비밀번호의 암호화이다.
저장될 때, 저렇게 대놓고 비밀번호를 저장하면 보안상의 문제도 있기 때문에
비밀번호를 암호화 시켜서 저장을 해야한다. 이때 많이 사용되는 라이브러리가 bcrypt이다.
npm install bcrypt 를 통해서 라이브러리를 설치한 다음,

bcrypt 패키지 사용: bcrypt.hash() 함수를 사용하여 비밀번호를 암호화한다.
첫 번째 매개변수로는 암호화할 문자열(여기서는 password)을, 두 번째 매개변수로는 salt 라운드 수를 전달한다. (salt 라운드 수가 클수록 보안성이 더 강화된다)
이렇게 설정하고, 다시 데이터에 저장해보면
이렇게 암호화 된 것을 확인할 수 있다!