3일 전에 쿠키와 싸움을 하고
JWT 토큰을 쿠키에 저장하기로 하였다.
그 과정 도중 JWT토큰 처리하는 다양한 로직들을 볼 수 있었고,
이러한 의견을 백엔드 분에게 전달하였다.
백엔드 분은 고민하셨지만 쿠키로 일단 마무리 지었고,
고민 끝에 다시 JWT 토큰을 스토리지에 저장하기로 하였다.
저번 JWT 토큰을 다룰 때는 Oauth 로그인을 누를 때,
메인으로 넘어가서 메인 주소위에
localhost:3000/AccessToken=sdfsadfvasvsfsdff
이런식으로 전달 되었다.
하지만 Token 자체가 노출이 되고,
사용자가 그것을 보는 것도 좋은 상황이 아니었다.
그래서 이를 개선하기 위해서 쿠키로 전향한 것이었는데,
대중성 있는 방법으로 수정하였다.
무엇이냐면 callback url을 생성하는 것이었다.
서버에게 redirect 보낼 주소를 특정 url을 알려주고,
그 url에 오자마자 스토리지에 저장하고 메인으로 보내주는 로직이다.
callback.tsx라는 파일을 작성하였고,
그 주소로 받아오고 보내주게 로직을 작성하였다.
하지만 여기서 한가지 아쉬운 점이 있었다.
어떤 사이트에서는 로그인을 하면 홈으로 보내주는 곳이 있었고,
어떤 사이트에서는 마지막 화면으로 보내주는 곳이 있었다.
나는 전자의 방법을 사용했는데, 사용자로서 불편함을 주었다.
그래서 나는 후자의 방법을 고민하고 적용하기로 하였다.
먼저 마지막 주소를 사용하기 전에 상태관리 라이브러리에 저장하면 좋을거 같아서
recoil을 사용하고 있으니 atom을 만들었다.
2번째로 현재 주소를 받아오는 방법이 필요했는데.
next/router에서 useRouter에 메서드 중 asPath를 활용하였다.
import { useRouter } from "next/router";
import { useSetRecoilState } from "recoil";
const router = useRouter();
const setLastPath = useSetRecoilState(lastPath);
const OauthHandler = () => {
setLastPath(router.asPath);
window.location.href = `${BACK_URL}/oauth2/authorization/google`;
};
특정 부분은 생략하였고,
위와 같이 작성하였다.
그리고 recoil을 사용할 때, 보통 useRocoilState를 사용하는데,
값을 사용하지 않기 때문에 useSetRecoilState를 import하여 사용하였다.
이를 통해 조금이라도 최적화를 하고자 하였다.
다시 본론으로 돌아가서 DropDown에 Oauth 로그인이 존재하므로,
DropDown에 위와 같이 작성하였고, 버튼을 누르는 순간에
백업이 되고 나서 Oauth 주소로 보내게 설정하였다.
그래서 accessToken이 잘받아왔을 때, 마지막에 접속한 주소로 보낼 수 있게 해주었다.
recoil 사용할 때도 앞에와 마찬가지로 useRecoilValue 메소드를 사용하여서
값만 사용하고자 하였다. (리소스를 아끼고자 하였다)
이제 끝나고 나니 걱정되는 것은 뒤로가기 기능이었다.
마지막 주소로 갔는데 유저가 뒤로가기를 누르면, callback url이 보일텐데,
그런 부분이 아쉬웠다.
그래서 이부분도 개선해주었다.
나의 방법은 뒤로가기 로그를 다른 로그로 대체하는 이벤트를 추가하는 로직을 추가하였다.
const handlePopstate = (event: PopStateEvent) => {
const currentUrl = window.location.href;
if (currentUrl.includes("/callback")) {
// 현재 URL에 "/callback"이 포함되어 있는지 확인합니다.
window.history.replaceState(null, "", "/"); // 홈으로 이동
}
};
window.addEventListener("popstate", handlePopstate);
return () => {
window.removeEventListener("popstate", handlePopstate);
};
해당 handlePopstate라는 함수를 추가하였고, 이를 이벤트를 할당하였다.
callback url일 경우
뒤로가기를 누르면 홈으로 보내주는 로직이었다.
하지만 이는 불편하였다.
뒤로가기를 누르면 보통 로그인을 누르기 전 페이지로 가야지, 갑자기 홈으로 가면
뜬금없다고 생각하였다.
그래서 든 생각은 callback url을 history에 추가하지 않는 것이다.
history API
웹 브라우저의 history API는 브라우저의 히스토리 스택에 접근하는 JavaScript API입니다. 이 API를 사용하면, 뒤로 가기와 앞으로 가기 버튼, 페이지 이동 등의 동작을 제어할 수 있습니다. history 객체에는 pushState(), replaceState(), go(), back(), forward()와 같은 메서드가 포함되어 있습니다.
이러한 history 객체의 메서드를 이용해서, 브라우저 히스토리와 관련된 동작을 자바스크립트 코드에서 제어할 수 있습니다
router.push와 replace는 히스토리를 추가 유무에 따라 차이가 난다.
push는 추가하고 replace는 추가하지 않는다.
좀 더 자세하게 설명하면, replace는 브라우저 히스토리에서 현재 페이지를 삭제하고 새로운 페이지로 대체한다.
이전 페이지로 이동할 때, 브라우저의 뒤로 가기 버튼을 클릭하면 바로 이전 페이지가 아닌 그 이전 페이지로 이동할 수 있다.
예를 들어, A 페이지에서 B 페이지로 이동하고, 다시 B 페이지에서 C 페이지로 이동한다면, 브라우저 히스토리에는 A -> B -> C가 저장됩니다. 이때, B 페이지에서 replace 함수를 사용해 C 페이지로 이동하면 브라우저 히스토리에서 B 페이지가 삭제되고 대신 C 페이지가 추가됩니다. 따라서, 뒤로 가기 버튼을 누르면 A 페이지로 바로 이동할 수 있다.
즉, push와 replace 함수는 브라우저 히스토리를 변경하는데 사용되며, 동작 방식이 다르다.
그래서 로직을 개선하였다.
useEffect(() => {
const accessToken = router.query.access_token as string;
if (accessToken) {
setAccessToken(accessToken as string); //토큰 저장
fetchUserData(accessToken as string)
.then((data) => {
setUser(data);
})
.catch((error) => {
console.error(error);
});
router.push(lastPathState as string); //이전페이지로 이동
} else {
router.push("/"); //토큰이 없으면 메인으로 이동
}
const handlePopstate = (event: PopStateEvent) => {
const currentUrl = window.location.href;
if (currentUrl.includes("/callback")) {
// 현재 URL에 "/callback"이 포함되어 있는지 확인합니다.
window.history.replaceState(null, "", "/"); // 홈으로 이동
}
};
window.addEventListener("popstate", handlePopstate);
return () => {
window.removeEventListener("popstate", handlePopstate);
};
}, [router]);
위에서 push -> replace로
그리고 아래 해당 함수 추가하는 로직을 제거해주었다.
useEffect(() => {
const accessToken = router.query.access_token as string;
if (accessToken) {
//동일 부분 생략
router.replace(lastPathState as string); //이전페이지로 이동
} else {
router.replace("/"); //토큰이 없으면 메인으로 이동
}
}, [router]);
그래서 이제 뒤로가기를 눌러서 callback url로 넘어가는 것을 막을 수 있었다.
나는 3가지를 변경하였다.
history에 대한 이해도가 조금 더 생겼고,
보안적인 이슈에 대해서도 경각심이 더 생겼다.
요즘 기분이 거만해지는 느낌이다.
아직 이룬 것도 없는데, 거만하다는 생각이 드는 것을 보면
우물안의 개구리같고 스스로 더 겸손하고 반성해야겠다
저도 홈으로 보내주는 경로가 많은데 … 사용하다가 로그인 하는 경우를 생각하지 못했네요 ㅠㅠ 저도 바꿔야겠어여 ㅎㅎ