Files
2nd/10_Wiki/Topics/Coding/Web_History_API_Routing.md
T
2026-05-09 21:08:02 +09:00

3.5 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
web-history-api-routing Browser History API — push / replace / popstate Coding draft B conceptual 2026-05-09 2026-05-09
web
history
routing
browser
vibe-coding
language applicable_to
JavaScript / browser
Web
pushState
replaceState
popstate
back/forward

Browser History API

SPA 라우팅의 기반. pushState / replaceState 로 URL 변경 + 뒤로가기 지원. 라우터 (RR, Next) 가 추상화하지만 알아야 모달 / 검색 필터 / scroll restoration 등 처리 가능.

📖 핵심 개념

  • pushState: 새 history entry. 뒤로가기 가능.
  • replaceState: 현재 entry 교체. 뒤로가기 안 변함.
  • popstate: 사용자 뒤로/앞으로. listener.
  • scroll restoration: 자동 복원.

💻 코드 패턴

URL 변경

// 새 entry
history.pushState({ page: 1 }, '', '/users/1');

// 현재 교체 (검색 필터 typing 시 디폴트)
history.replaceState({ filter: 'name' }, '', '?filter=name');

// 뒤로가기 감지
window.addEventListener('popstate', e => {
  const state = e.state; // pushState 의 첫 인자
  render(state);
});

모달 — URL 동기

function openModal(id: string) {
  history.pushState({ modal: id }, '', `?modal=${id}`);
  setOpenModal(id);
}

// popstate (back) 시 모달 닫기
window.addEventListener('popstate', () => {
  setOpenModal(null);
});

// 모달 닫기 버튼 → 뒤로
function closeModal() {
  history.back(); // popstate 트리거 → 위 핸들러
}

검색 필터 — replaceState (back 무한 폭주 방지)

function setSearch(q: string) {
  const url = new URL(location.href);
  url.searchParams.set('q', q);
  history.replaceState(null, '', url.toString());
  // 매 keystroke push 면 history 폭증 → replace
}

Scroll restoration

// 디폴트: 'auto' — 브라우저가 위치 복원.
// SPA 에서 비동기 데이터 로드 후 위치 안 맞으면 'manual' 후 직접
history.scrollRestoration = 'manual';

window.addEventListener('popstate', () => {
  // 데이터 로드 후
  window.scrollTo(0, savedScrollPositions[location.pathname] ?? 0);
});

라우터 안에서 (React Router)

const navigate = useNavigate();
navigate('/users/1');                    // pushState
navigate('/users/1', { replace: true }); // replaceState
navigate(-1);                            // back

🤔 의사결정 기준

액션 메서드
새 화면 (back 가능) pushState
URL 만 갱신 (필터, 정렬) replaceState
모달 / drawer pushState — back 으로 닫힘 (UX)
인증 후 redirect replaceState — back 으로 안 돌아감
외부 링크 location.href = ... 또는 anchor

안티패턴

  • 검색 typing 매번 pushState: 100번 typing → 100 history. replaceState.
  • state 없이 pushState: popstate 시 state null. 정보 손실. 항상 state object.
  • state 에 큰 객체: 직렬화 비싸고 5MB 한계. ID 만, 본문은 별도 store.
  • popstate 에서 fetch 호출 + race: 빠른 back/forward 시 stale. AbortController.
  • scroll 위치 안 저장: 뒤로 시 top 으로. 직접 saveScrollPosition.
  • history.back() 호출 후 해당 entry 가 없음: 사이트 떠남. canGoBack 체크.

🤖 LLM 활용 힌트

  • "새 화면 = push, URL 만 갱신 = replace" 명확.
  • 모달 = pushState + popstate close.

🔗 관련 문서