node.js
내 로그인 정보 매번 불러오기
Heoky
2022. 1. 18. 23:10
로그인 이후 새로고침을 하게 되면 로그인이 풀리는 문제가 발생한다. 어떻게 해결해야 될까?
1. 프론트에서 페이지가 새로고침이 될때마다(useEffect) 로그인 된 user의 정보를 매번 불러준다.
2. 백엔드 서버(user router)에서는 get을 통해 로그인 된 user의 정보를 매번 불러온다.
- passport 전략에 의해 로그인, req.user의 정보가 있으면 user의 정보를 매번 반환하고
- 없다면 null을 보내면 된다.
1. user 정보를 가져올 router를 만들어준다. (get)
// routes/user.js
const router = require('express').Router();
const { User } = require('../models');
// GET /user
router.get('/', async (req, res, next) => {
try {
if (req.user) {
const user = await User.findOne({
where: {
id: req.user.id,
},
});
res.status(200).json(user);
} else {
res.status(200).json(null);
}
} catch (err) {
console.error(err);
next(err);
}
});
passport의 로그인 전략에 의해 로그인이 성공적으로 이루어졌다면, req.user 안에 user의 정보가 담겨져있다.
get 요청이 왔을 때 model의 User에서 로그인 된 상태의 req.user.id를 찾아 사용자의 정보를 계속 유지하게끔 정보를 전달해준다.
2. 프론트에서(next.js와 redux, redux-saga 사용 기준) 화면이 렌더링 될 때마다 로그인된 user의 정보를 설정한 state에 계속
담아준다.
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { LOAD_MY_INFO_REQUEST } from '../reducers/user';
const Home = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch({
type: LOAD_MY_INFO_REQUEST, // 화면이 렌더링 될 때마다 user의 정보를 요청
});
}, []);
return (
...
)
}
한 페이지의 예를 든 것이고 이렇게 각각의 페이지마다 렌더링 시 user의 정보를 매번 요청해주면 된다.
sagas/user.js
function loadMyInfoAPI() {
return axios.get('/user');
}
function* loadMyInfo(action) {
try {
// api 통신할때는 call
const result = yield call(loadMyInfoAPI, action.data);
// yield delay(1000);
yield put({
type: LOAD_MY_INFO_SUCCESS,
data: result.data,
});
} catch (err) {
yield put({
type: LOAD_MY_INFO_FAILURE,
error: err.response.data,
});
}
}
reducers/user.js
export const initialState = {
loadMyInfoLoading: false,
loadMyInfoDone: false,
loadMyInfoError: null,
me: null,
};
export const LOAD_MY_INFO_REQUEST = 'LOAD_MY_INFO_REQUEST';
export const LOAD_MY_INFO_SUCCESS = 'LOAD_MY_INFO_SUCCESS';
export const LOAD_MY_INFO_FAILURE = 'LOAD_MY_INFO_FAILURE';
const reducer = (state = initialState, action) => {
switch (action.type) {
case LOAD_MY_INFO_REQUEST:
return {
...state,
loadMyInfoLoading: true,
loadMyInfoDone: false,
loadMyInfoError: null,
};
case LOAD_MY_INFO_SUCCESS:
return {
...state,
loadMyInfoLoading: false,
loadMyInfoDone: true,
me: action.data,
};
case LOAD_MY_INFO_FAILURE:
return {
...state,
loadMyInfoLoading: false,
loadMyInfoError: action.error,
};
default:
return state;
}
};
export default reducer;