react에서 페이지 이동할려고 했을 때 이를 검색한 적이 있다. 각각마다 차이점이 존재하여 이에 대해서 서술해보고자 글을 적게 되었다.
개념
자바스크립트에서 페이지 이동
- location.href : 새로운 페이지로 이동
- location.replace : 새로운 페이지로 이동
react에서 페이지 이동
- navigate : 새로운 페이지로 이동
차이점
1. 이전 페이지 이동
1) location.href와 location.replace
location.href는 객체의 속성이며, loaction.replace()는 메서드(함수)로 작동된다.
href는 페이지를 이동하는 것이기 때문에 뒤로가기 버튼을 누른 경우 이전 페이지로 이동이 가능하지만, replace는 이동한 페이지를 현재 페이지로 덮어 씌우기 때문에 이전 페이지로 이동이 불가능하다.
href는 일반적인 페이지 이동시 이용을 하면 되고, replace의 경우는 보안상의 이유로 덮어씌운다.
2) navigate
navigate("../success", { replace: true});
그리고 navigate도 replace 옵션을 써서 이전 페이지 이동이 불가능하다. 하지만 navigate의 replace옵션의 기본값은 false로 되어 있어, 이전 페이지가 원래는 이동이 가능하다. 저렇게 쓸려면 true로 바꿔 주어야 한다.
2. 주소창에 표시
href와 replace의 경우 라우터가 /user/login으로 되어있을 경우에 /로 이동한다고 했을 때, /user/로 이동하게 된다. react의 navigate를 사용했을 경우에 /로 이동하게 된다.
오류 발생
내가 지금 프론트로 react를 사용하고 있다. 자바스크립트 코드도 사용이 가능하기에 window.location.replace를 사용하여 로그인 후 이전 페이지인 로그인 화면을 이동할 수 없게 할려고 하였다. 그런데 이를 사용하니 replace버튼을 찾을 수 없다는 오류가 나왔다. 그래서 window를 없애고 하니 location.replace을 인식하지 못했다. navigate를 이용하여 replace를 사용해 이전 페이지 이동을 막고자 하였다. 그런데 사용은 되는데 이동을 막을 수가 없었다. 어떠한 오류도 나지 않고 이동이 되니 답답했다.
오류 발생의 이유
페이지에 진입할 때마다 특정 자바스크립트가 실행되어야 하는데, 처음 해당 페이지에 진입할 때는 정상적으로 자바스크립트가 실행되지만 뒤로가기를 통해 재진입했을 때에는 자바스크립트가 실행되지 않는 문제가 발견되었다.
여기서 bfcache라는 개념을 중점으로 설명하고 있다.
bfcache
: 이는 Back/Forward cache를 말한다. 앞과 뒤의 캐시를 의미한다.
bfcache는 데스크톱과 모바일에서 수년 동안 Firefox와 Safari 모두에서 지원되었습니다. 버전 86부터 Chrome은 소수의 사용자를 위해 Android에서 사이트 간 탐색을 위해 bfcache를 활성화했습니다. 후속 릴리스에서는 추가 지원이 천천히 롤아웃되었습니다. 버전 96부터 bfcache는 데스크톱 및 모바일의 모든 Chrome 사용자가 사용할 수 있습니다.
onLoad 이벤트에 주요 자바스크립트 코드를 걸어놓은 경우, bfacache를 타게 되면 페이지 진입시 해당 자바스크립트 코드가 항상 재실행되는 것을 보장하기 어렵다. 새로운 페이지에서 진행한 작업이 뒤로가기로 왔을 때 재진입한 페이지에도 영향을 주는 경우, 자바스크립트로 이 부분을 최신화해야 한다.
해결
BFCache에서 복원되는 경우를 확인 할 수 있는 API가 있다. pageshow, pagehide 이벤트를 이용하여 bfcache 여부를 확인 할 수 있다.
pageshow 이벤트
pageshow 이벤트는 페이지가 로드되거나, bfcache에서 페이지가 복원될 때 호출된다. 그리고 Callback에 전달되는 event 객체는 persisted 속성을 가지고 있는데 이 속성은 bfcache에서 페이지가 복원되었을 때 true이다.
뒤로가기 등이 재진입한 상태임을 알 수 있기에 정밀한 컨트롤이 가능해진다.
window.onpageshow = function (event) {
if (event.persisted) {
console.log('BFCahe로부터 복원됨');
}
else {
console.log('새로 열린 페이지');
}
};
pagehide 이벤트
pagehide 이벤트는 pageshow 이벤트와 반대이다. pagehide 이벤트는 페이지가 unload 되거나, bfcache 로 페이지가 캐시되기 직전 호출된다. 이 때 주의해야 할 점은 event.persisted 가 true라고 해도 bfcache가 되지 않을 수도 있다는 점이다. 다른 외부요인으로 인해 bfcache가 되지 않을 수도 있다.
window.addEventListener('pagehide', (event) => {
if (event.persisted === true) {
// bfcache로 이 페이지가 *아마도* 캐시 될 것이다.
} else {
// 이 페이지는 정상적으로 unload 된다.
}
});
→ 아직 코드에 대입해보지 않았지만, 이가 되는지 한번 주입해보고 되면 추가해야겠다.
적용
react에 적용할려고 하니, html태그에 적용할 수 없었다. 그래서 useEffect에 코드를 써서 적용하였다.
useEffect(() => {
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
window.history.forward()
}
});
}, []);
pageshow이벤트는 페이지가 로드됐을 경우 쓸 수 있는 이벤트이기에 코드 상위에 쓰도록 한다. 그리고 event가 허락이 됐을 경우의 조건문을 쓰고 window.history.forward()를 쓴다. 그러면 다음 페이지로 넘어가서 이전페이지로 갈 수 없게 된다.
또한, 한가지 오류가 생겼는데 이는 로그인하고 로그인이 되었으면 로그아웃이라고 버튼이 업데이트되어야 하는데 업데이트가 되지 않았다. 그래서 자바스크립트 코드를 사용하여 replace:true코드 밑에 reload를 시켜주어 로그아웃버튼이 바로 뜨게 하였다.
navigate('/', { replace : true})
window.location.reload();