뒤로가기의 무한굴레

전해림·2025년 9월 7일
post-thumbnail

안녕하세요. 오늘은 회사에서 프로젝트를 진행하면서 약 5번의 배포와 n번의 QA가 나왔던 뒤로가기 router.back()에 대한 이야기를 써보려고 합니다.

여러분들은 router.back()을 어떻게 쓰고 계신가요?

저는 보통 페이지간 이동이 필요할때는 router.push('url')로 이동하고 뒤로가기가 필요한 순간에 router.back()을 썼는데요 분명 다른 팀원들이 만든 페이지에서는 뒤로가기가 잘 되는데 제 페이지 에서는 3 -> 2 -> 1 구조로 뒤로 가는게 아닌 3 -> 2 -> 3 -> 2 이렇게 뒤로가기의 무한굴레에 빠지기 일쑤였습니다.
그로인해 약 일주일동안 2개의 방식을 적용했었는데요 그 방법을 소개하고 결국 해낸 방법에 대해 써보겠습니다.

문제

먼저 간단하게 router.back()의 구조에 대해 설명해보자면

💡브라우저의 History API (window.history.back())을 호출하는 얇은 래퍼

즉, 사용자가 직전에 방문한 URL이 있으면 해당 페이지로 이동합니다.

이러한 router.back에서 무한굴레의 문제가 발생한 이유는 정말 단순하게 router.push와 router.replace의
차이점을 모르고 썼고, router.back과 router.push를 혼합해서 쓰면서 무한굴레의 문제가 발생했습니다.

  • router.push : 히스토리에 새로운 기록 추가
  • router.replace : 히스토리에 새로운 기록을 추가하지 않고, 현재 기록을 덮어씀

또한 뒤로가기를 할때 router.back 으로 히스토리를 하나씩 지우면서 뒤로가기를 해야하지만,
중간중간 무조건 이동하는 페이지가 있을 때는(수익창출에서 뒤로가기를 하면 프로필이 꼭 나와야함) router.push로 히스토리에 새로운 기록을 추가하면서 뒤로가기를 하고 있었습니다.

그러면 A → B → C → D 로 갔다가 뒤로가기 시
D 이동 히스토리 지우기 → C 이동 히스토리 지우기 → B 이동 히스토리 지우기 → A 이동 히스토리 지우기
히스토리를 하나씩 지우면서 뒤로가기가 되어야 하지만 C에서 router.push(”B”)를 쓰게된다면

D 이동 히스토리 지우기 → C 이동 히스토리 지우고 히스토리 내역 맨 뒤에 B가 추가됨 → B에서 히스토리 지우기 → A 이동 히스토리 지우기 → 다시 B로 이동

그래서 과거 페이지로 돌아가고 싶을 때 router.push를 쓰면 스택의 “뒤쪽”에 과거 페이지가 새로 생겨버려서 뒤로가기가 꼬여버리게 되는데요

첫 번째 해결 시도 : 모바일 브릿지 통신으로 페이지를 모두 앱에서 띄워주기

제목만 들어도 손이 많이가고 복잡한 코드일거 같은데요..
웹뷰를 쓰고있는 서비스 특성 상 모바일과 브릿지통신을 하는 경우가 많아 첫 번째 방법으로 플러터 개발자분께
새창을 여는 브릿지를 만들어달라고 부탁했습니다.

브릿지 통신을 이용해서 openAppScreen으로 새창을 띄우고 closeAppScreen을 사용해서 새창을 닫는 방법으로

브릿지 코드에 대한 설명은 다음 포스팅에서 자세히 다뤄보겠습니다. 

/**
 * 앱 새창 열기
 * @param url 새창으로 띄울 페이지 URL
 */
export const openAppScreen = async (url: string) => {
  const data = url;
  return await flutterBridge(data, 'openAppScreen');
};

openAppScreen의 url로 새창으로 띄울 페이지 url을 넘기면 플러터측에서 새창으로 페이지를 띄워주었습니다.

하지만 요청 시 흰 화면이 보이는 시간이 길고 버벅거리는 문제와 스와이프가 안되는 문제로 인해 못쓰게 되었고,
프로필 이후의 페이지를 앱에게 위임했던것 인데요 모바일에서도 매번 새창을 띄워줘야하기때문에 메모리 문제도 있었습니다.

두 번째 해결 시도 : 프로필에서 넘어가는 모든 페이지에 window.open 새창 띄우기

두번째 방법으로는 window.open을 사용해서 프로필에서 이동하는 모든 페이지에 새 창을 띄우는 방법이었는데요.

 const handleRouterProfile = () => {
    window.open('/프로필 페이지', '_blank');
  };

새창을 여는건 큰 문제가 없었지만 AOS에서 window.close가 안되는 문제가 있었고, AOS에서는

<a href=""/></a>

이렇게 a태그를 활용해 ""로 페이지를 이동시키는 방법밖에 없었습니다.
또한 스와이프 기능이 새 창을 다 꺼버리는 문제가 있어 UX 적으로 좋지 않다는 판단을 하여
두 번째 방법도 쓰지 못하게 되었습니다.
(험난한 뒤로가기 수정 히스토리………)

결론과 마지막 시도

세 번째 시도 : 더이상 물러날 곳이 없다.(튜닝의 끝은 순정)

이제는 더이상 물러설 방법이 없기때문에 router.push와 router.replace에 대해 더 자세히 찾아보니
router.back과 router.push를 혼합해서 쓰면서 히스토리 배열이 꼬이고 있다는 문제를 발견하게 되었고

  • 페이지 이동 시 : router.push
  • 페이지 뒤로가기 시 : router.back
  • 페이지에서 api 통신 후 결과값을 가지고 페이지를 이동 시 : router.replace

router.push와 router.replace를 적절히 써야하는 상황을 잘 알아야 하고 그 안에 구조가 어떻게 흘러가는지
잘 알지 못하면 이러한 문제가 생길 수 있었습니다.

profile
프론트엔드 개발자 전해림입니다

0개의 댓글