인프런 커뮤니티 질문&답변
로그인 시도중 backend 에서 에러가 발생하면서 로그인이 되지 않습니다. 작성한 코드는 강사님이 작성하신 코드와 차이가 없는것 같습니다.
해결된 질문
작성
·
499
0

login(option)

login(Post)

아래는 backend - log 입니다.
Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'test@test.com';
Executing (default): INSERT INTO `Users` (`id`,`email`,`nickname`,`password`,`createdAt`,`updatedAt`) VALUES (DEFAULT,?,?,?,?,?);
Executing (default): SELECT `id`, `email`, `nickname`, `password`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'test@test.com';
(node:11018) UnhandledPromiseRejectionWarning: Error: Include unexpected. Element has to be either a Model, an Association or an object.
at Function._conformInclude (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:383:11)
at /Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:319:59
at Array.map (<anonymous>)
at Function._conformIncludes (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:319:39)
at Function._baseMerge (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:786:10)
at Function._defaultsOptions (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:823:17)
at Function._injectScope (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:3224:10)
at Function.findAll (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:1694:10)
at Function.findOne (/Users/imac/Desktop/nodebird study/back/node_modules/sequelize/lib/model.js:1905:23)
at /Users/imac/Desktop/nodebird study/back/routes/user.js:25:56
(node:11018) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:11018) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
에러 메세지를 읽은 결과...
원인이 두가지로 생각되는데요
1. routes/user.js 에 route /login 부분의 요소가 연관 모델이 아니다.
2. routes/user.js 에 route /login 함수를 try catch 로 묶어 줘라.
제가 이해한것이 맞는지 모르겠네요..
routes/user.js
const express = require('express');
const bcrypt = require('bcrypt');
const passport = require('passport');
const { User, Post } = require('../models');
const router = express.Router();
// 로그인 login
// 미들웨어 확장
router.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => { // 서버 에러, 성공, 클라이언트 에러
if (err) {
console.error(err);
return next(err);
}
if (info) {
return res.status(401).send(info.reasone); // 401: 허가되지 않음 , 403: 금지
}
return req.login(user, async (loginErr) => { // passport login error 시
if (loginErr) {
console.error(loginErr);
return next(loginErr);
}
const fullUserWithoutPassword = await User.findOne({
where: { id: user.id },
// attributes: ['id', 'nickname','email'],
attributes: {
exclude: ['password']
},
include: [{
model: Post,
attributes: ['id'],
}, {
medel: User,
as: 'Followings',
attributes: ['id'],
}, {
model: User,
as: 'Followers',
attributes: ['id'],
}]
})
// res.setHeader('Cookie', 'cxlhy')
return res.status(200).json(fullUserWithoutPassword);
});
})(req, res, next);
});
// 로그아웃 logout
router.post('/logout', (req, res) => {
req.logout();
req.session.destroy(); // session 에 저장된 쿠키와 id 를 지운다.
res.send('ok'); // 로그아웃 성공
});
// 회원가입 signup
router.post('/', async (req,res, next) => { // POST /user
try {
const exUser = await User.findOne({
where: {
email: req.body.email,
}
});
if (exUser) {
return res.status(403).send('이미 사용 중인 아이디입니다.'); // 응답
}
const hashedPassword = await bcrypt.hash(req.body.password, 12); // 10 ~ 13 - 해쉬화 한다.
await User.create({
email: req.body.email,
nickname: req.body.nickname,
password: hashedPassword,
});
// res.json();
// res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// res.setHeader('Access-Control-Allow-Origin', '*');
res.status(200).send('ok'); // res.status(200).send('ok'); 응답
} catch(error) {
console.error(error);
next(error); // status 500
}
});
// router.delete('/', (req,res) => { // DELETE /user
// res.json({id: 1 });
// });
module.exports = router;
app.js
const express = require('express');
const cors = require('cors');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const dotenv = require('dotenv');
const postAPIRouter = require('./routes/post');
const userAPIRouter = require('./routes/user');
const db = require('./models');
const passportConfig = require('./passport');
dotenv.config();
const app = express();
db.sequelize.sync()
.then(() => {
console.log('db 연결 성공');
})
.catch(console.error);
passportConfig();
app.use(cors({
// origin: 'https://nodebird.com', // https://nodebird.com 에서 온 요청만 허용하겠다.
origin: '*', // 모든 요청 허용
// credentials: false, //
}));
app.use(express.json()); // front server 에서 json 형식으로 데이터를 보냈을때 req.body 안에 data를 넣어준다.
app.use(express.urlencoded({ extended: true})); // from submit 했을때 urlencoded 방식으로 변환해준다.
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
saveUninitialized: false,
resave: false,
secret: process.env.COOKIE_SECRET,
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/post', postAPIRouter);
app.use('/user', userAPIRouter);
app.listen(3065, () => {
console.log('서버 실행 중')
});
models/user.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', { // Mysql에는 users 테이블 생성
// id가 기본적으로 들어있다.
email: {
type: DataTypes.STRING(30), // INTEGER: 정수, FLOAT: 소수(실수) BOOLEAN, FLOAT
allowNull: false, // 필수
unique: true, // 고유한 값
},
nickname: {
type: DataTypes.STRING(30),
allowNull: false, // 필수
},
password: {
type: DataTypes.STRING(100),
allowNull: false, // 필수
},
}, {
charset: 'utf8',
collate: 'utf8_general_ci' // 한글 저장
});
User.associate = (db) => {
db.User.hasMany(db.Post);
db.User.hasMany(db.Comment);
// Liked user 가 좋아요를 누른 post 를 가져온다..
db.User.belongsToMany(db.Post, { through: 'Like', as: 'Liked' });
db.User.belongsToMany(db.User, { through: 'Follow', as: 'Followers', foreignKey: 'FollowingId'});
db.User.belongsToMany(db.User, { through: 'Follow', as: 'Followings', foreignKey: 'FollowerId'});
};
return User;
models/post.js
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define('Post', { // Mysql에는 posts 테이블 생성
// id가 기본적으로 들어있다.
content: {
type: DataTypes.TEXT,
allowNull: false,
},
// RetweetId
}, {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci' // 이모티콘 저장
});
Post.associate = (db) => {
db.Post.belongsTo(db.User);
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag'} );
db.Post.hasMany(db.Comment);
db.Post.hasMany(db.Image);
// user post 테이블간에 like 테이블이 생기고.. as 에 따라서 post.getLikers 처럼 게시글 좋아요.. 누른 user 를 가져온다.
// Likers 좋아요를 누른 user 를 가져온다.
db.Post.belongsToMany(db.User, { through: 'Like', as: 'Likers' });
db.Post.belongsTo(db.Post, { as: 'Retweet' })
};
return Post;
}
models/comment.js
module.exports = (sequelize, DataTypes) => {
const Comment = sequelize.define('Comment', { // Mysql에는 comments 테이블 생성
// id가 기본적으로 들어있다.
content: {
type: DataTypes.TEXT,
allowNull: false,
},
// UserId: 1
// PostId: 1
}, {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci' // 한글 저장
});
Comment.associate = (db) => {
db.Comment.belongsTo(db.User);
db.Comment.belongsTo(db.Post);
};
return Comment;
}
sagas/user.js
import { all, put, fork, takeLatest, delay, call } from 'redux-saga/effects';
import axios from 'axios';
import {
LOG_IN_REQUEST,
LOG_IN_SUCCESS,
LOG_IN_FAILURE,
LOG_OUT_REQUEST,
LOG_OUT_SUCCESS,
LOG_OUT_FAILURE,
SIGN_UP_REQUEST,
SIGN_UP_SUCCESS,
SIGN_UP_FAILURE,
FOLLOW_REQUEST,
FOLLOW_SUCCESS,
FOLLOW_FAILURE,
UNFOLLOW_REQUEST,
UNFOLLOW_SUCCESS,
UNFOLLOW_FAILURE,
} from '../reducers/user';
function followAPI(data) {
return axios.post('/api/follow', data);
}
function* follow(action) {
try {
// yield put({
// type: 'FOLLOW_REQUEST',
// });
// const result = yield call(followAPI, action.data);
// ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시
yield delay(1000);
// throw new Error('') // 아래 catch 로 넘어간다.
yield put({
type: FOLLOW_SUCCESS,
data: action.data,
});
} catch (err) {
yield put({ // put => dispatch 다.
type: FOLLOW_FAILURE,
data: err.response.data,
});
}
}
function unfollowAPI(data) {
return axios.post('/api/unfollow', data);
}
function* unfollow(action) {
try {
// yield put({
// type: 'UNFOLLOW_REQUEST',
// });
// const result = yield call(unfollowAPI, action.data);
// ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시
yield delay(1000);
// throw new Error('') // 아래 catch 로 넘어간다.
yield put({
type: UNFOLLOW_SUCCESS,
data: action.data,
});
} catch (err) {
yield put({ // put => dispatch 다.
type: UNFOLLOW_FAILURE,
data: err.response.data,
});
}
}
function signUpAPI(data) {
return axios.post( '/user', data); // localhostUrl ( http://localhost:3065 ) + /user
}
function* signUp(action) {
try {
// yield put({
// type: 'LOG_IN_REQUEST',
// });
const result = yield call(signUpAPI, action.data);
// ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시
// yield delay(1000);
// throw new Error('') // 아래 catch 로 넘어간다.
console.log(result);
yield put({
type: SIGN_UP_SUCCESS,
// data: result.data,
});
} catch (err) {
console.error(err);
yield put({ // put => dispatch 다.
type: SIGN_UP_FAILURE,
data: err.response.data,
});
}
}
function logOutAPI() {
return axios.post('/api/logout');
}
function* logOut() {
try {
// yield put({
// type: 'LOG_OUT_REQUEST',
// });
// const result = yield call(logOutAPI);
yield delay(1000);
yield put({
type: LOG_OUT_SUCCESS,
});
} catch (err) {
yield put({ // put => dispatch 다.
type: LOG_OUT_FAILURE,
error: err.response.data,
});
}
}
function logInAPI(data) {
return axios.post('/user/login', data);
}
function* logIn(action) {
try {
console.log('saga logIn');
// yield put({
// type: 'LOG_IN_REQUEST',
// });
const result = yield call(logInAPI, action.data);
console.log(result);
// ex> const result = yield call(logInAPI, action.data, a, b, c); a, b, c 인자를 추가시
// yield delay(1000);
yield put({
type: LOG_IN_SUCCESS,
data: result.data,
});
} catch (err) {
console.error(err);
yield put({ // put => dispatch 다.
type: LOG_IN_FAILURE,
error: err.response.data,
});
}
}
function* watchFollow() {
yield takeLatest(FOLLOW_REQUEST, follow); // take =>logIn 액션이 실행될때까지 기다리겠다.
}
function* watchUnFollow() {
yield takeLatest(UNFOLLOW_REQUEST, unfollow); // take =>logIn 액션이 실행될때까지 기다리겠다.
}
function* watchLogIn() {
yield takeLatest(LOG_IN_REQUEST, logIn); // take =>logIn 액션이 실행될때까지 기다리겠다.
}
function* watchLogOut() {
yield takeLatest(LOG_OUT_REQUEST, logOut);
}
function* watchSignUp() {
yield takeLatest(SIGN_UP_REQUEST, signUp); // take =>logIn 액션이 실행될때까지 기다리겠다.
}
export default function* userSaga() {
yield all([
fork(watchFollow),
fork(watchUnFollow),
fork(watchLogIn),
fork(watchLogOut),
fork(watchSignUp),
]);
}
sagas/index.js
// all fork call put delay debounce throttle takeLatest tabkeEvery takeLeding taekMaybe
import { all, fork } from 'redux-saga/effects';
import axios from 'axios';
import postSaga from './post';
import userSaga from './user';
import { localhostUrl } from '../config/config';
axios.defaults.baseURL = localhostUrl;
export default function* rootSaga() {
yield all([ // all 은 배열을 받아서 배열안에 있는 명령들을 한번에 실행 시켜준다.
fork(postSaga),
fork(userSaga),
]);
};
front/config/config.js
export const domainUrl = 'http://api.nodebird.com';
export const localhostUrl = 'http://localhost:3065';
답변 2
1
제로초(조현영)
지식공유자
const fullUserWithoutPassword 여기서 medel 오타입니다.
이게 아니라면 models/index.js에 오타가 있는 것으로 판단됩니다.
0




