• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

로그인 이후 LOAD_USER_REQUEST에서 넘어가지 않습니다 ㅠㅠ

20.03.29 15:46 작성 조회수 224

0

(처음 http://localhost:3000/ 에 왔을 때)

(로그인 성공)

(그 상태에서 새로고침)

LOAD_USER_REQUEST에서 다음 단계(SUCCESS, FAILURE)로 이어지지를 않네요 ㅠㅠ 

console.log를 찍어보니 'api/user' get 라우터에서 req.user가 undefiend로 나옵니다.

여기저기 살펴보았는데 어느 부분을 고쳐야 하는건지 잘 모르겠네요.. ㅠㅠ 도움 주시면 감사하겠습니다!

덧글로 각각의 코드 어떻게 작성하였는지 남겨보겠습니다!

답변 9

·

답변을 작성해보세요.

1

LOAD_USER에서 다음으로 안 넘어갈때 콘솔창이나 네트워크탭에 에러가 있을 것입니다. 알려주세요.

0

ㅠㅠ 코드 비교하여 어디에서 생긴 오류인지 확인했습니다 제가 passport의 deserialize부분에 코드를 잘못 적었었네요 !!!

0

LOAD_USER_FAILURE에서 띄운 에러도 첨부합니다!

0

확인해보니 LOAD_USER_REQUEST 이후에 네트워크 창에서 user 페이지의 status가 (pending)이라고 뜹니다.

이후 2분동안 아무 동작없이 가만히 있다가 2분이 지난 후에 LOAD_USER_FAILURE를 띄우네요 ㅠㅠ 관련 캡쳐 올려보겠습니다! 

LOAD_USER_REQUEST 이후 네트워크 pending 상태

2분 가량 지난 후 failed를 띄웁니다 

failed 띄운 user/ 클릭했을 때 나온 정보입니다 ㅠㅠ 

LOAD_USER_FAILURE 띄우면서 나온 오류입니다

아는 것이 부족하여 중구난방 캡쳐 올리는 점 양해 부탁드립니다 ㅠㅠ

0

/back/index.js

const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const expressSession = require('express-session');
const dotenv = require('dotenv');
const passport = require('passport');

const passportConfig = require('./passport');
const db = require('./models');
const userAPIRouter = require('./routes/user');
const postAPIRouter = require('./routes/post');
const postsAPIRouter = require('./routes/posts');
dotenv.config();
const app = express();
db.sequelize.sync();
passportConfig();

app.use(morgan('dev')); // app.use는 부가적인 요소들(미들웨어)를 붙여줄 수 있다.
app.use(cors({
origin: true, // 요청 주소랑 같도록
credentials: true // 프론트와 쿠키 주고받을 수 있도록.. front의 axios에서도..
}));
app.use(express.json()); // json 형식의 본문 처리
app.use(express.urlencoded({extended: true})); // form으로 넘어온 데이터 처리

app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(expressSession({
resave: false, // 매번 세션 강제 저장
saveUninitialized: false, // 빈 값도 저장
secret: process.env.COOKIE_SECRET, // 암호화 키
cookie: {
httpOnly: true, // 쿠키를 자바스크립트에서 접근하지 못함
secure: false, // https를 쓸 때 true로
},
name: 'rnbck' // 해킹 방지하기 위해 쿠키 이름 변경
}));
app.use(passport.initialize());
app.use(passport.session()); // express-session보다 아래에 적어야함 (express-session을 내부적으로 사용해서)

// API는 다른 서비스가 내 서비스의 기능을 실행할 수 있게 열어둔 창구
app.use('/api/user', userAPIRouter);
app.use('/api/post', postAPIRouter);
app.use('/api/posts', postsAPIRouter);

app.listen(3065, () => {
console.log('server is running on http://localhost:8080');
})

0

/front/components/AppLayout.js

import React, { useState, useEffect } from 'react';
import {
Menu, Input, Button, Row, Col, Card, Avatar, Form,
} from 'antd';
import propTypes from 'prop-types';
import Link from 'next/link';
import { useSelector, useDispatch } from 'react-redux';
import LoginForm from './LoginForm';
import UserProfile from './UserProfile';
import { LOAD_USER_REQUEST } from '../reducers/user';


const AppLayout = ({ children }) => {
const { isLoggedIn, me } = useSelector((state) => state.user);
const dispatch = useDispatch();
useEffect(() => {
if(!me){
dispatch({
type: LOAD_USER_REQUEST,
});
}
}, [])

return (
<div>
<Menu mode="horizontal">
<Menu.Item key="home"><Link href="/"><a>노드버드</a></Link></Menu.Item>
<Menu.Item key="profile"><Link href="/profile"><a>프로필</a></Link></Menu.Item>
<Menu.Item key="mail">
<Input.Search enterButton style={{ verticalAlign: 'middle' }} />
</Menu.Item>
</Menu>
<Row gutter={8}>
<Col xs={24} md={6}>
{me
? <UserProfile />
: <LoginForm />}


</Col>
<Col xs={24} md={12}>
{children}
</Col>
<Col xs={24} md={6}>세번째</Col>
</Row>

</div>
);
};

AppLayout.propTypes = {
children: propTypes.node,
};

export default AppLayout;

0

/front/reducers/user.js


export const initialState = {
isLoggingOut: false, // 로그아웃 시도중
isLoggingIn: false, // 로그인 시도중
logInErrorReason: '', // 로그인 실패 사유
isSignedUp: false, // 회원가입 성공
isSigningUp: false, // 회원가입 시도중
signUpErrorReason: '', // 회원가입 실패 사유
me: null, // 내 정보
followingList: [], // 팔로잉 리스트
followerList: [], // 팔로워 리스트
userInfo: null, // 남의 정보
};

export const SIGN_UP_REQUEST = 'SIGN_UP_REQUEST';
export const SIGN_UP_SUCCESS = 'SIGN_UP_SUCCESS';
export const SIGN_UP_FAILURE = 'SIGN_UP_FAILURE';

export const LOG_IN_REQUEST = 'LOG_IN_REQUEST';
export const LOG_IN_SUCCESS = 'LOG_IN_SUCCESS';
export const LOG_IN_FAILURE = 'LOG_IN_FAILURE';

export const LOAD_USER_REQUEST = 'LOAD_USER_REQUEST';
export const LOAD_USER_SUCCESS = 'LOAD_USER_SUCCESS';
export const LOAD_USER_FAILURE = 'LOAD_USER_FAILURE';

export const LOG_OUT_REQUEST = 'LOG_OUT_REQUEST';
export const LOG_OUT_SUCCESS = 'LOG_OUT_SUCCESS';
export const LOG_OUT_FAILURE = 'LOG_OUT_FAILURE';

export const LOAD_FOLLOW_REQUEST = 'LOAD_FOLLOW_REQUEST';
export const LOAD_FOLLOW_SUCCESS = 'LOAD_FOLLOW_SUCCESS';
export const LOAD_FOLLOW_FAILURE = 'LOAD_FOLLOW_FAILURE';

export const FOLLOW_USER_REQUEST = 'FOLLOW_USER_REQUEST';
export const FOLLOW_USER_SUCCESS = 'FOLLOW_USER_SUCCESS';
export const FOLLOW_USER_FAILURE = 'FOLLOW_USER_FAILURE';

export const UNFOLLOW_USER_REQUEST = 'UNFOLLOW_USER_REQUEST';
export const UNFOLLOW_USER_SUCCESS = 'UNFOLLOW_USER_SUCCESS';
export const UNFOLLOW_USER_FAILURE = 'UNFOLLOW_USER_FAILURE';

export const REMOVE_FOLLOWER_REQUEST = 'REMOVE_FOLLOWER_REQUEST';
export const REMOVE_FOLLOWER_SUCCESS = 'REMOVE_FOLLOWER_SUCCESS';
export const REMOVE_FOLLOWER_FAILURE = 'REMOVE_FOLLOWER_FAILURE';

export const ADD_POST_TO_ME = 'ADD_POST_TO_ME';

const reducer = (state = initialState, action) => {
switch (action.type) {
case LOG_IN_REQUEST: {
return {
...state,
logInErrorReason: '',
};
}
case LOG_IN_SUCCESS: {
return {
...state,
isLoggingIn: false,
me: action.data,
};
}
case LOG_IN_FAILURE: {
return {
...state,
isLoggingIn: false,
logInErrorReason: action.error,
me: null,
};
}
case LOG_OUT_REQUEST: {
return {
...state,
isLoggingOut: true,
}
}
case LOG_OUT_SUCCESS: {
return {
...state,
isLoggingOut: false,
me: null,
};
}
case SIGN_UP_REQUEST: {
return {
...state,
isSigningUp: true,
isSignedUp: false,
signUpErrorReason: '',
};
}
case SIGN_UP_SUCCESS: {
return {
...state,
isSigningUp: false,
isSignedUp: true,
};
}
case SIGN_UP_FAILURE: {
return {
...state,
isSigningUp: false,
signUpErrorReason: action.error,
};
}
case LOAD_USER_REQUEST: {
return {
...state,
};
}
case LOAD_USER_SUCCESS: {
return {
...state,
me: action.data,
};
}
case LOAD_USER_FAILURE: {
return {
...state,
};
}
default: {
return {
...state,
};
}
}
};

export default reducer;

0

/front/sagas/user.js

import { all, fork, takeLatest, takeEvery, call, put, delay } from 'redux-saga/effects';
import axios from 'axios';
import { LOG_IN_SUCCESS, LOG_IN_FAILURE, LOG_IN_REQUEST, SIGN_UP_SUCCESS, SIGN_UP_FAILURE, SIGN_UP_REQUEST, LOG_OUT_SUCCESS, LOG_OUT_FAILURE, LOG_OUT_REQUEST, LOAD_USER_SUCCESS, LOAD_USER_FAILURE, LOAD_USER_REQUEST } from '../reducers/user';
import { Result } from 'antd';
axios.defaults.baseURL = 'http://localhost:3065/api'

function logInAPI(loginData){
//서버에 요청을 보내는 부분
console.log(loginData);
return axios.post('/user/login', loginData, {
withCredentials: true, // 서로 쿠키를 주고받을 수 있도록 (front)
});
}
function* logIn(action){
try {
console.log('ok1');
const result = yield call(logInAPI, action.data); //함수 동기적 호출 (응답을 받을 때까지 기다림)
yield put({ // put은 dispatch와 동일
type: LOG_IN_SUCCESS,
data: result.data,
});
} catch (e){
console.error(e);
yield put({
type: LOG_IN_FAILURE,
});
}
}
function* watchLogIn(){
yield takeEvery(LOG_IN_REQUEST, logIn);
}



function signUpAPI(signUpData) {
return axios.post('/user', signUpData);
}
function* signUp(action) {
try {
yield call(signUpAPI, action.data); // 함수 동기적 호출 (응답을 받을 때까지 기다림)
// call은 첫번째는 함수, 두번째부터 인자
yield put({ //put은 dispatch와 동일
type: SIGN_UP_SUCCESS,
});
} catch (e){
console.error(e);
yield put({
type: SIGN_UP_FAILURE,
error: e,
});
}
}
function* watchSignUp(){
yield takeEvery(SIGN_UP_REQUEST, signUp);
}



function logOutAPI(){
return axios.post('/user/logout', {}, {
withCredentials: true, // 쿠키를 백으로 보내기 위해
});
}
function* logOut(action){
try {
yield call(logOutAPI);
yield put({
type: LOG_OUT_SUCCESS
});
} catch (e){
console.error(e);
yield put({
type: LOG_OUT_FAILURE,
});
}
}
function* watchLogOut(){
yield takeEvery(LOG_OUT_REQUEST, logOut);
}



function loadUserAPI(){
console.log('loadUserAPI arrived');
return axios.get('/user/', {
withCredentials: true,
});
}
function* loadUser(){
console.log('loadUser arrived')
try {
const result = yield call(loadUserAPI);
console.log(result);
yield put({
type: LOAD_USER_SUCCESS,
data: result.data,
});
} catch (e){
console.error(e);
yield put({
type: LOAD_USER_FAILURE,
});
}
}


function* watchLoadUser(){
yield takeEvery(LOAD_USER_REQUEST, loadUser);
}




export default function* userSaga(){
yield all([
fork(watchSignUp),
fork(watchLogOut),
fork(watchLoadUser),
fork(watchLogIn),
]);
}

0

/back/routes/user.js

const express = require('express');
const bcrypt = require('bcrypt');
const passport = require('passport');
const db = require('../models');
const router = express.Router();

router.get('/', (req, res) => { // /api/user/
if(!req.user){
return res.status(401).send('로그인이 필요합니다.');
}
const user = Object.assign({}, req.user.toJSON());
delete user.password;
return res.json(user);
});
router.post('/', async (req, res, next) => { // POST /api/user 회원가입
try{
const exUser = await db.User.findOne({
where: {
userId: req.body.userId,
},
});
if(exUser){
return res.status(403).send('이미 사용중인 아이디입니다.');
}
const hashedPassword = await bcrypt.hash(req.body.password, 12); // salt는 10~13 사이로
const newUser = await db.User.create({
nickname: req.body.nickname,
userId: req.body.userId,
password: hashedPassword,
});
console.log(newUser);
return res.status(200).json(newUser);
}catch (e) {
console.error(e);
// 에러 처리를 여기서
return next(e);
}
});
router.get('/:id', (req, res) => { // 남의 정보 가져오기 ex) /3

});
router.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
console.log(err, user, info);
if (err) {
console.error(err);
return next(err);
}
if (info) {
return res.status(401).send(info.reason);
}
return req.login(user, async (loginErr) => {

try{
if (loginErr) {
return next(loginErr);
}
const fullUser = await db.User.findOne({
where: {id:user.id},
include: [{
model: db.Post,
as: 'Posts',
attributes: ['id'],
},{
model: db.User,
as: 'Followings',
attributes: ['id'],
},{
model: db.User,
as: 'Followers',
attributes: ['id'],
}],
attributes: ['id', 'nickname', 'userId'],
});
console.log(fullUser);
return res.json(fullUser);
} catch(e) {
next(e);
}
});
})(req, res, next);
})
router.post('/logout', (req, res) => {
req.logout();
req.session.destroy();
res.send('logout 성공');
});
router.get('/:id/follow', (req, res) => {

});
router.post('/:id/follow', (req, res) => {

});
router.delete('/:id/follow', (req, res) => {

});
router.delete('/:id/follower', (req, res) => {

});
router.get('/:id/posts', (req, res) => {

});

module.exports = router;