본문 바로가기
STUDY/Project

회원가입, 로그인 로직 - User, authController, authRoutes

by Y.Choi 2025. 4. 30.
728x90
반응형

 

| User 모델 스키마 정의

데이터 스키마를 정의하고 DB와 연결된 구조를 제공한다.

 

 

backend/models/User.js

const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

const userSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true }
}, { timestamps: true });

userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  this.password = await bcrypt.hash(this.password, 10);
  next();
});

userSchema.methods.matchPassword = async function(enteredPassword) {
  return await bcrypt.compare(enteredPassword, this.password);
};

module.exports = mongoose.model('User', userSchema);

 

/ userSchema : User 스키마를 정의한다.

* unique: true -- 중복 방지를 위한 조건.

* timestamps: true -- createdAt, updatedAt 자동 생성

 

/ userSchema.pre : 미리 저장 전 비밀번호 암호화

사용자가 비밀번호를 입력할 때마다 자동으로 bcrypt로 해시 처리한다.

기존 비밀번호가 변경되지 않았다면 다시 해시하지 않고 넘어간다.

 

/ userSchema.methods.matchPassword : 비밀번호 비교 메서드

로그인 시 입력된 비밀번호(enteredPassword)와 해시된 비밀번호를 비교한다.

 

/ mongoose.model : User라는 이름으로 MongoDB에 user 컬렉션으로 저장된다.

 

 

 

| 회원가입, 로그인 로직을 처리하기 위한 컨트롤러

실제 동작을 처리한다. 요청(req)데이터를 받고 모델을 이용해 DB와 통신한 후 응답(res)을 반환한다.

 

 

backend/controllers/authControllers.js

const User = require('../models/User');
const generateToken = require('../utils/generateToken');

// 회원가입 컨트롤러
exports.registerUser = async (req, res) => {
  const { username, email, password } = req.body;

  try {
  	// 이미 존재하는 사용자 체크
    const userExists = await User.findOne({ email });
    if (userExists) return res.status(400).json({ message: '이미 존재하는 이메일입니다.' });

    const user = await User.create({ username, email, password });

    res.status(201).json({
      _id: user._id,
      username: user.username,
      email: user.email,
      token: generateToken(user._id),
    });
  } catch (error) {
    res.status(500).json({ message: '회원가입 오류', error: error.message });
  }
};

// 로그인 컨트롤러
exports.loginUser = async (req, res) => {
  const { email, password } = req.body;

  try {
    const user = await User.findOne({ email });
    if (!user || !(await user.matchPassword(password))) {
      return res.status(401).json({ message: '이메일 또는 비밀번호가 올바르지 않습니다.' });
    }

    res.json({
      _id: user._id,
      username: user.username,
      email: user.email,
      token: generateToken(user._id),
    });
  } catch (error) {
    res.status(500).json({ message: '로그인 오류', error: error.message });
  }
};

 

DB와 JWT관련 기능을 사용하기 위해 불러와주고

 

/ registerUser : 회원가입 컨트롤러

클라이언트가 보내온 username, email, password를 req.body에서 꺼낸다.

try문에서는 같은 이메일을 가진 유저가 DB에 있는지 체크하고 User.create로 새 유저를 생성한다.

이때 비밀번호는 User모델에서 bcrypt를 통해 해싱된다.

그다음 res.status로 유저 정보를 응답으로 보내고 JWT 토큰도 함께 반환한다.

 

/ loginUser : 로그인 컨트롤러

DB에서 이메일로 유저를 찾고 비밀번호 일치 여부를 matchPassword로 확인한다.

성공하면 토큰을 포함한 유저 정보를 반환하고 실패시 401에러를 반환한다.

 

 

| 라우터 연결

URL과 컨트롤러 함수를 연결한다. 예를들어 POST /api/auth/register 요청이 오면 registerUser 함수를 실행한다.

 

backend/routes/authRoutes.js

const express = require('express');
const { registerUser, loginUser } = require('../controllers/authController');

const router = express.Router();

router.post('/register', registerUser);
router.post('/login', loginUser);

module.exports = router;

 

express.Router()로 라우터 객체를 생성하고 authController.js에서 정의한 registerUser, loginUser함수를 불러온다.

/api/auth/regiser 경로로 POST 요청이 오면 registerUser함수가 실행된다. 

module.exports - router; 외부에서 사용이 가능하게 내보낸다.

 

이렇게 해서 server.js에서 등록한 라우트와 연결된다.

 

 

| JWT Token 모듈 작성

 

빠진것이 있다. 지금까지 순서대로 작성했다면 아마도 터미널에 에러가 떴을 것이다.

 

Error: Cannot find module '../utils/generateToken' ...

어떤 문제인지 대략 눈치 챌 수 있다. 컨트롤러에서 generateToken을 사용하려는데 아직 그 파일을 만들지 않았다.

 

backend/utils/generateToken.js

const jwt = require('jsonwebtoken');

const generateToken = (userId) => {
  return jwt.sign({ id: userId }, process.env.JWT_SECRET, {
    expiresIn: '7d',
  });
};

module.exports = generateToken;

 

 

또한, .env 파일에서 JWT_SECRET이 지정되어 있는지 확인하고 설정해주어야 한다.

 

 

| 테스트

아직 클라이언트 개발을 하지 않았기 때문에 Thunder Client로 요청과 응답을 테스트 한다.

Response에 결과 값이 아래와 같은 형식으로 나온다면 성공이다.

 

Thunder client 사용방법은 여기

 

/ register

 

 

/ login

회원 가입시 입력했던 이메일과 비밀번호를 정확히 입력해야 한다.

 

 

728x90
반응형