Home [Next.js] 스마트 뒤로가기 구현: window.history.length의 함정과 해결책
Post
Cancel

[Next.js] 스마트 뒤로가기 구현: window.history.length의 함정과 해결책

🧐 뒤로가기, 왜 그냥 router.back()만 쓰면 안 될까?

개발을 하다 보면 상세 페이지결제 페이지에서 “이전으로” 버튼을 만들어야 할 때가 많습니다. 처음에는 단순하게 router.back() 혹은 history.back()을 사용했죠. 하지만 실전에서는 예상치 못한 상황들이 터져 나왔습니다.

  1. 외부 유입 시 미동작: 광고나 검색을 통해 바로 우리 페이지로 들어온 유저가 버튼을 누르면? 돌아갈 곳이 없어 버튼이 먹통이 됩니다.
  2. 보안/사용성 이슈: 외부 사이트(구글, 네이버 등)로 사용자를 쫓아내버리는 불상사가 발생합니다.
  3. 사용자 이탈: history.length가 1인 상태에서 뒤로가기를 실행하면 사용자는 우리 서비스 밖으로 나가버리게 됩니다.

이런 문제를 방지하기 위해 “우리 서비스 안에서의 이동인지”“돌아갈 기록이 있는지”를 체크하는 로직이 반드시 필요하다는 것을 깨달았습니다.


🛠️ 실무형 스마트 뒤로가기 로직

제가 실무에서 다듬은 코드는 document.referrerwindow.history.length를 조합하여 유저의 유입 경로를 판단합니다.

💻 코드 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * @param {string} fallbackPath - 이전 기록이 없을 때 이동할 대체 경로
 */
const handleSmartBack = (fallbackPath = "/") => {
  // 1. 브라우저 세션 히스토리에 쌓인 페이지가 1개보다 많은지 확인
  const hasHistory = window.history.length > 1;

  // 2. 이전 주소(referrer)가 현재 우리 서비스의 도메인을 포함하고 있는지 확인
  // 즉, 서비스 내부에서 이동해 온 것인지 판단
  const isInternalNavigation = document.referrer.includes(window.location.host);

  if (isInternalNavigation && hasHistory) {
    // 내부 이동 기록이 있다면 안전하게 뒤로가기 수행
    router.back();
  } else {
    // 기록이 없거나 외부 유입이라면 지정된 안전한 경로(메인 등)로 이동
    router.push(fallbackPath);
  }
};

💡 핵심 객체 및 함수 파헤치기

이 로직을 이해하기 위해 꼭 알아야 할 세 가지 핵심 요소입니다.

1. window.history.length

  • 현재 브라우저 탭의 세션 히스토리에 쌓인 페이지 수를 반환합니다.
  • 주의점: 새 탭에서 우리 사이트를 처음 열면 1이 찍힙니다. 즉, 1보다 커야 돌아갈 곳이 있다는 뜻입니다.

2. document.referrer

  • 현재 페이지로 오기 전의 URL 정보를 담고 있습니다.
  • 직접 URL을 입력해서 들어오거나 즐겨찾기로 접속하면 빈 문자열("")이 출력됩니다.
  • window.location.host와 비교하여 “남의 집(외부 사이트)”에서 왔는지 “우리 집(내부)”에서 이동했는지 가려내는 결정적 역할을 합니다.

3. router.back() vs router.push()

  • router.back()은 단순히 히스토리를 한 칸 뒤로 돌립니다.
  • router.push()는 새로운 히스토리를 쌓으며 지정된 경로로 강제 이동시킵니다.

🚀 실전 포인트: 언제, 어떻게 써야 할까?

✅ 언제 써야 하는가?

  • 이벤트 상세 페이지: 유입 경로가 광고(외부)일 수도 있고, 목록(내부)일 수도 있을 때.
  • 폼 작성 취소 버튼: 유저가 작업 중이던 맥락을 유지하며 이전으로 보내줘야 할 때.
  • 404 페이지: 길을 잃은 유저에게 “이전으로 돌아가기” 기능을 제공할 때.

⚠️ 실수하기 쉬운 부분

  • document.referrer보안 정책(Referrer-Policy)에 따라 값이 누락될 수 있습니다. 그래서 반드시 isInternalNavigation 체크와 hasHistory 체크를 병행해야 합니다.
  • 단순히 window.history.length > 1만 체크하면, 구글 검색을 통해 들어온 유저도 history.length가 2 이상일 수 있어 구글로 튕겨버릴 수 있습니다.

🧐 실제 개발 경험 (Troubleshooting)

처음에 history.length만 믿고 배포했다가, 카카오톡 인앱 브라우저에서 유입된 유저들이 “뒤로가기를 누르니까 카카오톡 채팅방으로 나가져요!”라는 CS를 보낸 적이 있었습니다. 이를 해결하기 위해 document.referrer를 추가하여 우리 서비스 도메인 내부에서의 흐름인지를 검증하는 로직을 추가했고, 그 결과 이탈률을 유의미하게 줄일 수 있었습니다.


📊 로직 비교 정리

방식외부 유입 시 동작서비스 이탈 위험권장 상황
Simple back()이전 페이지(검색 엔진 등)로 이동높음없음 (비권장)
History Length 체크히스토리 있으면 무조건 이동보통단순 웹 앱 내부 이동
스마트 백 (Referrer 조합)지정된 안전 경로로 이동매우 낮음상업용 서비스 필수

🏷️ 마치며

사용자 경험(UX)은 아주 사소한 “뒤로가기” 버튼 하나에서도 결정됩니다. window.historyreferrer를 적절히 섞어 쓰는 이 한 줄의 로직이 유저가 우리 서비스에 머무르는 시간을 조금 더 늘려줄 것입니다.

지금 바로 여러분의 프로젝트에 안전한 후진 기어를 장착해 보세요! 🏎️

This post is licensed under CC BY 4.0 by the author.

[React] window.matchMedia로 반응형 사이드바 완벽 구현하기 (resize 이벤트 지옥 탈출)

-