node.js

[node.js] passportLocalMongoose 사용 시 몽구스 컬렉션 생성 안됨 해결방법

Let it out 2024. 1. 24. 14:16

node.js에서 mongoose만 사용하면 잘되는데,

passportLocalMongoose를 추가해서 사용하면 컬렉션이 만들어 지지 않을 때 가 있다.

 

Bad Request와 같은 에러 발생

 

 

 

 

왜 안되는지 알아보고 예제를 통해 해결하자.

문제점 은 2개다.

1. 필수 필드 지정 문제

2. 사용자 등록 라우터에서 필드명과 클라이언트 데이터 일치 문제

 

 

1. 필수 필드 지정 문제

- 일반적인 mongoose 스키마 정의

일반적인 mongoose 필수 필드 지정 방법은 required: true 옵션을 사용하여 개발자가 지정한다.

컬렉션 생성 시 필수 필드를 사용하지 않으면 에러가 발생한다.

const mongoose = require("mongoose");

let UserSchema = new mongoose.Schema({
    userId: { 
        type: String,
        required: true //필수 필드 지정
    },
    password: { 
        type: String,
        required: true //필수 필드 지정
    },
    nickName:type: String,
});

let User = mongoose.model("User", UserSchema);
module.exports = User;

 

 

- passportLocalMongoose 과 함께 mongoose 스키마 정의

 

하지만 passportLocalMongoose 사용시 자동으로 usernamepassword 필수 필드로 추가 되어 꼭 작성해 줘야 한다.

또한 일반적인 mongoose 스키마 정의와 다르게 이미 필수 필드로 지정되어 있기 때문에 required:true 옵션을 쓰지 않는다.

따라서 필수 필드인 username과 password를 작성하지 않으면 컬렉션 생성 시 에러가 발생한다.

이게 첫번째 주의 할 점이다.

const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose"); //passportLocalMongoose 사용

let UserSchema = new mongoose.Schema({
    username: String, //필수 필드
    password: String, //필수 필드
    userNickname: String,
});

UserSchema.plugin(passportLocalMongoose);
let User = mongoose.model("User", UserSchema);
module.exports = User;

 

 

 

2. 사용자 등록 라우터에서 필드명과 클라이언트 데이터명 비일치 문제

- 문제점

현재 코드에서는 클라이언트에서 전송한 데이터를 req.body.userId, req.body.userpassword로 받아오고있다.

그런데 mongoose 스키마는 username, userpassword 필수 필드명을 정의하고 있어서  req.body.userId, req.body.userpassword 와 필드명이 일치 하지 않는다.(예제 주석 참조)

물론 일반적인 mongoose 에서는 일치 하지 않아도 되지만  passportLocalMongoose 사용 시에는 문제가 생긴다.

router.post("register", (req, res) => {
    if (
        req.body.userId &&
        req.body.userNickname &&
        req.body.userpassword
    ) {
        let newUser = new User({
            username: req.body.userId, //필수 필드 명이 일치 하지 않아 에러 발생
            userNickname: req.body.userNickname, //얜 일치 하지 않아도 됨
        });

        return createUser(newUser, req.body.userpassword, req, res);
    }
});

 

 

- 해결 방법

클라이언트에서 전송한 데이터의 필드명을 몽구스 스키마에서 정의한 필드명과 일치시켜 줘야한다.

필드명과 데이터명이 다르면 에러 발생.

 

사용자 등록 라우터 예제

router.post("/user/register", (req, res) => {
    if (
        req.body.username &&
        req.body.userNickname &&
        req.body.userpassword
    ) {
        let newUser = new User({
            username: req.body.username, //필드명과 클라이언트에서 전송한 데이터 이름을 일치 시켜준다.
            userNickname: req.body.userNickname,
        });

        return createUser(newUser, req.body.userpassword, req, res);
    }
});

 

 

 

클라이언트 전송 데이터 예제

8번째 줄에 <input>태그 name을 username으로 지정.

13번째 줄에 <input>태그 name을 password로 지정.

<body>
    <div>
        <h2>Sign up</h2>
        <form method="post" action="/register" id="register-form ">
            <div>
                <label for="username-register">아이디</label>
               //mongoose.js의 username 필드와 똑같이 name="username" 지정
                <input id="username-register" type="text" name="username" placeholder="Id">
            </div>

            <div>
                <label for="Password-register">비밀번호</label>
                //mongoose.js의 password 필드와 똑같이 name="password" 지정
                <input id="Password-register" type="password" name="password" placeholder="Id">
            </div>


            <div>
                <label for="Nickname-register">닉네임</label>
                <input id="Nickname-register" type="text" name="nickname" placeholder="Id">
            </div>
 
       
            <button id="register" type="submit" name="register">Sign up</button>
        </form>
       
    </div>
</body>

 

정리 : 라우터에서 필수 필드명과 클라이언트 데이터 이름을 일치 시켜준다.

 

 

 

3. 예제 코드

위에서 설명한 것들을 담은 예제 코드다. 주석을 잘 볼것.

- mongoose.js

username과 password는 필수 필드 이므로 꼭 작성해줘야 한다.

//mongoose.js
 
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");

let UserSchema = new mongoose.Schema({ 
    username: String, //필수 필드
    password: String, //필수 필드
    userNickname: String,
});

UserSchema.plugin(passportLocalMongoose);
let User = mongoose.model("User", UserSchema);
module.exports = User;

 

 

- register.ejs

이 코드는 html이라고 생각하고 봐도 무관하다.

아이디의 name ="username"

비밀번호의 name ="password" 로 지정 해줘서 필수 필드와 이름을 일치 시켜준다.

 
<body>
    <div>
        <h2>Sign up</h2>
        <form method="post" action="/register" id="register-form ">
            <div>
                <label for="username-register">아이디</label>
               //mongoose.js의 username과 name을 똑같이 username으로 지정
                <input id="username-register" type="text" name="username" placeholder="Id">
            </div>

            <div>
                <label for="Password-register">비밀번호</label>
                //mongoose.js의 password와  name을 똑같이 password로 지정
                <input id="Password-register" type="password" name="password" placeholder="Id">
            </div>


            <div>
                <label for="Nickname-register">닉네임</label>
                <input id="Nickname-register" type="text" name="nickname" placeholder="Id">
            </div>
 
       
            <button id="register" type="submit" name="register">Sign up</button>
        </form>
       
    </div>
</body>

 

 

- user.js

컬렉션을 만드는 부분의 일부다.

mongoose.js의 필수 필드인 username과 register.ejs의 input인 username이 똑같은 이름인 것을 볼 수 있다.

//user.js
 
const express = require("express");
const User = require("../models/User");
const passport = require("passport");
const router = express.Router();
 
router.post("/register", (req, res) => {
    if (
        req.body.username &&
        req.body.nickname &&
        req.body.password
    ) {
        let newUser = new User({
            username: req.body.username,  //필수 필드명과 클라이언트 데이터명을 똑같이 지정
            userNickname: req.body.nickname, //필수 필드가 아니므로 일치 하지 않아도 된다.
        });
 
        return createUser(newUser, req.body.password, req, res);
    }
});

 

 

반응형