처음에 isSuccess/isError로 구현했다가 처음에 동작이 제대로 안되는 것을 보고 on~로 회원가입과, 로그인 동작을 모두 수정해주었다.
const mutation = useMutation(signIn, {
onSuccess: (data) => {
const token = data.token; // toekn 받음
console.log("token", data.token);
// 쿠키 저장, 유효시간 설정
document.cookie = `token=${token}; max-age=600`;
// dispatch(setUser({ id: loginUser.id }));
alert("로그인 되었습니다!");
// navigate("/");
console.log("로그인", token, userId);
},
onError: (error) => {
console.log("onerror", error);
if (error.response.status === 401) {
return alert(error.response.data.message);
}
return alert(error.message);
},
});
로그인 동작 구현 중, 동작을 실행할 때 마다 token인증을 하기 위해서 질문을 해보던 중, intercept로 중간에 작업을 추가해줄 수 있다는 사실을 알았다.
만료 된 채로 요청 -> 401 에러 -> 메시지 출력, token 삭제 후 login page로 이동
aut.js
const instance = axios.create({
baseURL: `${process.env.REACT_APP_AUTAPI_URL}user`,
headers: { "Content-Type": "application/json" },
});
요청을 보내기 전 수행해야 하는 것은 없기 때문에 응답 내보내기 전에 처리만 해준다.
오류가 발생했을 때 error처리를 401일 때 메시지를 출력해주도록 코드를 수정한다.
// 응답 내보내기 전
instance.interceptors.response.use(
function (config) {
return config;
},
function (error) {
const msg = error.response.data.message;
const status = error.response.status;
console.log("응답 보내기 전", error);
console.log(msg);
/**
* 만료 된 채로 요청 -> 401 에러 -> 메시지 출력, token 삭제 후 login page로 이동
*/
if (status === 401) {
if (msg === "토큰이 만료되었습니다. 토큰은 60분간 유지됩니다.") {
document.cookie = "token=; expires=-1;";
alert(`${msg} 다시 로그인 해주세요!`);
return "expire";
} else if (
msg === "위조되었거나 잘못된 형식의 token입니다.(jwt malformed)"
) {
document.cookie = "token=; expires=-1;";
return "falsify";
} else if (msg === "token value가 존재하지 않습니다.") {
return "nonetoken";
} else {
return;
}
}
return error;
}
);
users.js
// 유저 인증 확인
const checkAut = async (token) => {
const response = await aut.get("", {
headers: {
authorization: `Bearer ${token}`,
},
});
return response.data;
};
인증 확인을 렌더링 했을 때 마다 시도해주자.
const token = document.cookie.split("=")[1];
새 컴포넌트를 넣어, 렌더링이 될 때 마다 실행하여 토큰을 인증하려고 한다.
Authorization.jsx
import React, { useEffect } from "react";
import { useMutation } from "react-query";
import { checkAut } from "../api/users";
function Authorization() {
const token = document.cookie.split("=")[1];
console.log("토큰있어?", token);
const mutation = useMutation(checkAut, {
onSuccess: () => {},
onError: (error) => {
console.log("autError", error);
},
});
useEffect(() => {
mutation.mutate(token);
}, []);
return <></>;
}
export default Authorization;
함수 컴포넌트나 커스텀 훅 내에서만 사용해야하는데 그렇지 않았을 때 발생하는 오류이다.
aut.js에서 useNavigate를 사용해서 발생하는 오류였기에 useNavigate를 다른 곳에 사용했다.
로그인 했을 때의 정보를 redux에 담아, { id: "", isLogin: false }
의 상태에 따라 로그인, 로그아웃 버튼이 나타나게 만들었다.
const navigate = useNavigate();
const currentUser = useSelector((item) => item.currentuser);
const [isLogin, setIsLogin] = useState(false);
const dispatch = useDispatch();
const logoutHandler = () => {
document.cookie = "token=; expires=-1;";
dispatch(logoutUser());
setIsLogin(currentUser.isLogin);
alert("로그아웃 되었습니다!");
console.log(currentUser);
};
useEffect(() => {
setIsLogin(currentUser.isLogin);
}, [currentUser]);
.
.
<div>
{!isLogin && (
<Button onClick={() => navigate("/signin")}>LogIn</Button>
)}
{isLogin && <Button onClick={() => logoutHandler()}>Logout</Button>}
</div>
새로고침 등 했을 때 redux 정보가 지워져서 토큰의 존재유무로 판별하였다.
const navigate = useNavigate();
const token = document.cookie.split("=")[1];
const currentUser = useSelector((item) => item.currentuser);
const [isLogin, setIsLogin] = useState(false);
const dispatch = useDispatch();
const logoutHandler = () => {
document.cookie = "token=; expires=-1;";
dispatch(logoutUser());
setIsLogin(currentUser.isLogin);
alert("로그아웃 되었습니다!");
console.log(currentUser);
};
useEffect(() => {
if (token.trim()) {
setIsLogin(true);
} else {
setIsLogin(false);
}
}, [currentUser]);
해당 페이지에 접속했을 때, 각종 error가 아니라 온전한 로그인 상태이고 url을 비교하여 로그인/회원가입 페이지에 들어가지 못하게 막는다.
Authorization.jsx
const preventSign = () => {
if (token) {
alert("로그아웃 해주세요!");
navigate("/");
}
};
useEffect(() => {
const currentUrl = window.location.href.split("/");
const url = currentUrl[currentUrl.length - 1];
console.log("url", url, token);
if (url === "signin" || url === "signup") {
preventSign();
}
mutation.mutate(token);
}, []);
interceptor의 사용법과 로그인, 회원가입에서 쿠키가 어떻게 주고받는지, jwt를 언제 사용하는지 동작과정을 알 수 있었다.