인프런 커뮤니티 질문&답변

잼코님의 프로필 이미지

작성한 질문수

따라하며 배우는 노드, 리액트 시리즈 - 기본 강의

노드 리액트 기초 강의 #14 로그아웃 기능

Route.get() requires a callback function but got a [object Object]

20.10.18 17:34 작성

·

2.5K

0

인자를 객체로 넘겼다고 에러가 뜨는데, auth를 구현하는 app.get에서 자꾸 문제가 있다고 합니다. 오타는 도저히 못찾겠는데,, 문제가 무엇일까요

const express = require('express')
const app = express()
const port = 5000
const bodyParser = require('body-parser');
const { User } = require("./models/User");
const config = require('./config/key');
const cookieParser = require('cookie-parser');
const auth = require('./middleware/auth');

// application / x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended : true}));
// application / json
app.use(bodyParser.json());
app.use(cookieParser());

const mongoose = require('mongoose');



//mongoDB 연결
mongoose.connect(config.mongoURI,{
useNewUrlParser: true, useUnifiedTopolongy: true, useCreateIndex: true, useFindAndModify: false
}).then(() => console.log('MongoDB connected !'))
.catch(err => console.log('MongoDB Error !'));



//Hello world 출력
app.get('/', (req, res) => {
res.send('Hello World!')
});



//register 라우트
app.post('/api/users/register', (req, res) => {
// 회원가입 할 때 필요한 정보들을 client으로부터 받아오면
// 그것들을 database에 넣어준다.

const user = new User(req.body)

user.save((err, userInfo) => {
if(err) return res.json({ success : false, err })
return res.status(200).json({
success: true
});
});


});



// login 라우트
app.post('/api/users/login', (req, res) => {

// console.log('ping')
//요청된 이메일을 데이터베이스에서 있는지 찾는다.
User.findOne({ email: req.body.email }, (err, user) => {

// console.log('user', user)
if (!user) {
return res.json({
loginSuccess: false,
message: "제공된 이메일에 해당하는 유저가 없습니다."
})
}

//요청된 이메일이 데이터 베이스에 있다면 비밀번호가 맞는 비밀번호 인지 확인.
user.comparePassword(req.body.password, (err, isMatch) => {
// console.log('err',err)

// console.log('isMatch',isMatch)

if (!isMatch)
return res.json({ loginSuccess: false, message: "비밀번호가 틀렸습니다." })

//비밀번호 까지 맞다면 토큰을 생성하기.
user.generateToken((err, user) => {
if (err) return res.status(400).send(err);

// 토큰을 저장한다. 어디에 ? 쿠키 , 로컳스토리지
res.cookie("x_auth", user.token)
.status(200)
.json({ loginSuccess: true, userId: user._id })
})
})
})
})


// auth 라우트 (미들웨어로 사용될 것입니다.)
app.get('/api/users/auth', auth, (req, res) => {
//여기 까지 미들웨어를 통과해 왔다는 얘기는 Authentication 이 True 라는 말.
res.status(200).json({
_id: req.user._id,
isAdmin: req.user.role === 0 ? false : true,
isAuth: true,
email: req.user.email,
name: req.user.name,
lastname: req.user.lastname,
role: req.user.role,
image: req.user.image
})
})


app.get('/api/users/logout', auth, (req, res) => {
// console.log('req.user', req.user)
User.findOneAndUpdate({ _id: req.user._id },
{ token: "" }
, (err, user) => {
if (err) return res.json({ success: false, err });
return res.status(200).send({
success: true
})
})
})


// 포트를 통해 index.js 를 실행합니다.
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});

위는 index.js 

const { User } = require('../models/User');

let auth = (req, res, next) => {
//인증 처리를 하는곳
//클라이언트 쿠키에서 토큰을 가져온다.

let token = req.cookies.x_auth;
// 토큰을 복호화 한후 유저를 찾는다.
User.findByToken(token, (err, user) => {
if (err) throw err;
if (!user) return res.json({ isAuth: false, error: true })


// console.log('userh', user)

req.token = token;
req.user = user;
next();
})
}


module.exports = { auth };

 auth.js

// 모듈 (User에서는 데이터 베이스를 위한 몽구스, 유저의 비밀번호 암호화를 위한 비크립트, 유저의 개개인 토큰을 얻기 위한 제이슨웹토큰을 가져온다.)
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');

// 비밀번호 암호화를 위한 salt 값 설정. salt 값은 암호화된 비밀번호를 해킹하기 어렵게 만들 수 있음.
const saltRounds = 10;

// 유저의 정보들을 객체화, 이른 바 유저 스키마를 생성한다. ( 몽구스의 메소드 )
// 각 유저들의 이름, 이메일, 비밀번호 등 개인정보를 담기 위한 객체임.
const userSchema = mongoose.Schema({
name : {
type: String,
maxlength: 50
},

email : {
type: String,
trim: true,
unique: 1
},

password : {
type: String,
minlength: 5
},

lastname : {
type: String,
maxlength: 50,
},

role : {
type: Number,
default: 0
},

token: {
type: String,

},
tokenExp: {
type: Number
},

image : String

})


// 유저 스키마 이전에 실행될 것임.
userSchema.pre('save', function (next) {
var user = this;
if (user.isModified('password')) {
//비밀번호를 암호화 시킨다.
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) return next(err)

bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err)
user.password = hash
next()
})
})
} else {
next()
}
})

// comparePassword 라는 이름의 유저 스키마 메소드를 생성합니다. ( 당연히 비밀번호 비교를 위한 메소드이겠지요? )
userSchema.methods.comparePassword = function (plainPassword, cb) {

//plainPassword 1234567 암호회된 비밀번호 $2b$10$l492vQ0M4s9YUBfwYkkaZOgWHExahjWC
bcrypt.compare(plainPassword, this.password, function (err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
})
}

userSchema.methods.generateToken = function (cb) {
var user = this;
// console.log('user._id', user._id)

// jsonwebtoken을 이용해서 token을 생성하기
var token = jwt.sign(user._id.toHexString(), 'secretToken')
// user._id + 'secretToken' = token
// ->
// 'secretToken' -> user._id

user.token = token
user.save(function (err, user) {
if (err) return cb(err)
cb(null, user)
})
}

userSchema.statics.findByToken = function(token, cb) {
var user = this;

// 토큰을 decode 한다.
jwt.verify(token, 'secretToken', function(err, decoded) {
// 유저 아이디를 통해서 유저를 찾은 다음에
// 클라이언트에서 가져온 token과 DB에서 가져온 토큰이 일치하는지 확인합니다.

user.findOne({ "_id" : decoded, "token" : token }, function(err, user) {
if(err) return cb(err);
cb(null, user);
})

})
}


// 유저스키마 => User 라는 이름으로 모델화.
const User = mongoose.model('User', userSchema);
// 방금 모델화한 User 밖에서도 사용가능하도록 exports.
module.exports = { User };


user.js 입니다.

문제가 무엇일까요, ㅠ

답변 3

14

최율겸님의 프로필 이미지

2020. 11. 06. 14:33

해결하셨겠지만 뒤에분들 보시라고 달아놉니다.

const auth = require('./middleware/auth');

여기서 auth를 {auth}로 해주시면 됩니다.

왜냐하면 module.exports = {auth} 이기 때문입니다.

에러메시지는 router.get에서는 콜백함수를 받아와야 하는데 객체를 받아와서 에러가 뜬다고 알려주는겁니다.

auth만 하게되면 auth라는 콜백함수를 품고있는 객체가 되는것이고 {auth}는 객체안의 콜백함수라는 뜻입니다

김현재님의 프로필 이미지

2021. 05. 12. 12:32

덕분에 해결하였습니다 감사합니다😇

밈도님의 프로필 이미지

2021. 06. 03. 22:49

저도 덕분에 해결하였습니다!ㅠㅠ 감사합니다!

김동현님의 프로필 이미지

2022. 03. 23. 17:09

감사합니다 머리아팠는데 해결했네요

은정님의 프로필 이미지

2022. 09. 07. 13:45

감사합니다.

chosc0417님의 프로필 이미지

2024. 01. 14. 19:56

덕분에 {auth}와 auth의 차이를 알게 되었습니다! 감사합니다!

1

John Ahn님의 프로필 이미지
John Ahn
지식공유자

2020. 10. 18. 20:41

안녕하세요 Hoonsboy님 ! 
아마 세세한 부분에서 오타가 난 경우 인것같은데요...
이러한 경우에는 제가 만들어 놓은 원본 소스를 복사 붙여넣기 하는 방법이 
가장 에러 해결에 좋을것같습니다 ㅠㅠ 
https://github.com/jaewonhimnae/boiler-plate-ko
여기 소스를 이용해서 복사 붙여넣기를 해주세요 ~ ! 

0

오아시스님의 프로필 이미지

2020. 12. 20. 22:11

율겸님 감사합니다~

잼코님의 프로필 이미지

작성한 질문수

질문하기