사용자가 웹사이트에 로그인하여 서비스를 이용하려면 인증이 필수적.
HTTP의 Stateless 특성으로 인한 인증 시스템이 필요한 이유를 정리.
그 사용자를 기억하지 않음.
클라이언트: "안녕하세요, 저는 user123입니다."
서버: 첫 사용자의 요청을 처리하지만, 이후의 요청에서 "누구시죠?"라고 묻는 것과 같음
서버는 이전 요청의 사용자를 기억하지 않는 특성
서버는 각 요청마다 사용자가 누구인지 확인할 별도의 방법이 필요
인증(Authentication)이 필요한 이유:
보안 유지 : 사용자가 누구인지 확인해 특정 서비스나 데이터에 대한 접근을 제어연속된 세션 유지 : 사용자가 여러 요청을 할 때마다 서버가 사용자 식별 필요test123@test.com이 로그인을 시도
Email이 DB에 일치하는 데이터가 있는지를 확인const user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send('Auth failed, email not found');
bcrypt에 의해 암호화된 비밀번호와 입력받은 비밀번호를 비교const isMatch = await user.comparePassword(req.body.password);
if (!isMatch) return res.status(400).send('Wrong password');
userSchema.methods.comparePassword = async function (plainPassword) {
let user = this;
const match = await bcrypt.compare(plainPassword, user.password);
return match;
};
const jwt = require('jsonwebtoken');
const payload = {userId: user._id.toHexString()};
const accessToken = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });

useEffect(() => {
if (isAuth) {
dispatch(authUser());
}
}, [isAuth, pathname]);
- 사용자가 로그인한 상태가 되었을 때, authUser 액션이 실행
- 사용자가 다른 페이지로 이동할 때도 이 훅이 실행
let auth = async (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (token === null) return res.sendStatus(401);
try {
const decode = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findOne({ _id: decode.userId });
if (!user) return res.status(400).send('존재하지 않는 정보입니다.');
req.user = user;
next();
} catch (error) {
next(error);
}
};
const payload = {userId: user._id.toHexString()};
const accessToken = jwt.sign(payload, process.env.JWT_SECRET});
const decode = jwt.verify(token, process.env.JWT_SECRET);
/users/auth 엔드포인트로 인증이 유효한지를 확인 요청을 보내게 된다. export const authUser = createAsyncThunk('user/authUser', async (_, thunkAPI) => {
try {
const response = await axiosInstance.get(`/users/auth`);
return response.data;
} catch (error) {
console.log('authUser error : ', error);
return thunkAPI.rejectWithValue(error.response.data || error.message);
}
});
auth 요청 시, 사용자에게 전달하기 위한 token값을 localStorage로 부터 저장 axiosInstance.interceptors.request.use(
async function (config) {
config.headers.Authorization = 'Bearer ' + localStorage.getItem('accessToken');
return config;
},
function (error) {
return Promise.reject(error);
},
);

