---
type: note
kind: Explainer
title: location.href 는 암묵적 await 가 아니다 — setter 는 동기, navigation 은 태스크
tags: ['javascript', 'event-loop', 'navigation']
status: release
ctime: 2026-06-23
mtime: 2026-09-10
generated: { by: claude/opus-5, at: 2026-08-21T00:00:00Z }
verified: { by: claude/opus-5, at: 2026-08-21T00:00:00Z }
sources:
  - id: html-spec-navigate
    resource: https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
    title: "HTML Standard — navigate"
---

`location.href`에 값을 넣으면 그 줄에서 바로 페이지가 이동할 것 같다. 마치 **암묵적 `await`**처럼 거기서 멈춘다고 생각하기 쉽다. 그럼 뒤에 오는 코드는 실행되지 않을까.

```js
location.href = 'https://google.com'
console.log('실행됨 1')
location.href = 'https://google2.com'
console.log('실행됨 2')
```

**둘 다 출력된다. 그리고 이동은 `google2.com`으로 간다.**

`await`였다면 첫 줄에서 멈춰 `실행됨 1`도 출력되지 않고 `google.com`으로 갔어야 한다. 두 결과가 모두 어긋나니 가설은 틀렸다.

실제로는 이렇다. setter는 **동기적으로 정상 실행되고 흐름을 끊지 않는다.** 문서를 언로드하고 네트워크 요청을 보내는 실제 작업은 태스크로 넘어가 지금 실행 중인 코드가 끝난 뒤에 시작된다. 그리고 두 번째 navigation이 시작되면 **진행 중이던 첫 번째가 버려진다**[^html-spec-navigate] — 마지막 값이 이기는 건 덮어써서가 아니라 앞의 것이 취소되기 때문이다.

<img
  src="/svg/event_loop_nav_slot.svg"
  alt="location.href setter가 실행되는 시점과 실제 navigation이 처리되는 시점이 분리되는 이벤트 루프 타임라인"
/>

[^html-spec-navigate]: *"Set the ongoing navigation for navigable to navigationId. This will have the effect of **aborting other ongoing navigations** of navigable, since at certain points during navigation changes to the ongoing navigation will cause further work to be abandoned."* — 그리고 문서 언로드·페치는 `in parallel` 로 넘어간다. ([HTML Standard — navigate](https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate))
