로컬 URL 프래그먼트로 이동해도 브라우저 히스토리가 수정되지 않음

페이지 내 섹션으로의 링크를 포함할 때, 해당 링크를 클릭해도 브라우저 히스토리가 수정되지 않습니다. 뒤로 가기를 누르면 페이지 위치로 돌아가는 대신 페이지를 벗어나게 됩니다.

수정: 이 Discourse에서는 ID가 있는 요소를 생성할 수 없으므로 여기서 데모를 보여줄 수 없습니다. 여기서는 제가 하고 싶은 작업을 소스로 나타내었지만, 이는 단순히 문제를 설명하기 위한 것이며 문제의 핵심에는 영향을 미치지 않습니다:

<div id="link-target"></div>

*이 섹션은 위에서 링크로 연결되어 있습니다. 볼 만한 내용은 없습니다.*

이건 어느 정도 예상되는 상황입니다. 같은 토픽 안의 다른 게시글 링크를 클릭해도 히스토리 스택에 추가되지 않으며, 프래그먼트가 없는 완전한 링크이므로 토픽 내 이동은 히스토리에 푸시되지 않습니다.

이러한 동작은 매우 예상 밖입니다 :slight_smile:

여기 JavaScript가 없는 샘플 페이지가 있습니다. Chromium에서 해당 링크를 클릭하면 페이지 하단으로 이동합니다. 뒤로 버튼을 누르면 클릭하기 전 위치로 돌아옵니다. 이는 히스토리를 소비하지 않는 다른 모든 웹사이트에서 볼 수 있는 예상된 동작입니다.

<a href="#target">link</a>

<div style="height:2000px"></div>

<div id="target">Hello</div>

Discourse가 JavaScript를 통해 URL 단편(fragments)을 처리하고 해당 위치로 스크롤하므로, 히스토리가 명시적으로 push되어야 한다고 추측합니다.

@codinghorror은 이 문제에 대해 여기에서 강하고도 최종적인 의견을 표명했습니다. 표준 웹 브라우저 동작에 대한 변경 사항에 대해 이렇게 강한 의견이 나온다는 것은 놀랍습니다. 공평하게 말하자면, 저는 아직 Discourse를 고강도 토픽 탐색에 사용하지 않아서 그의 주장이 자명하다는 점을 충분히 이해하지 못하고 있습니다.

저는 Discourse를 문서화 목적으로 부분적으로 사용하고 있는데, 이 동작은 매우 방해가 심해서 링크를 클릭했다가 페이지에서 제 위치를 잃을까 봐 클릭조차 두려울 정도입니다.

이 동작이 문제되는 사례를 하나 보여드리겠습니다:

https://meta.discourse.org/tos

목차(TOC) 링크 중 하나를 클릭한 뒤 브라우저 히스토리를 통해 원래 위치로 돌아가고 싶은 유혹이 생길 수 있습니다. 하지만 그럴 수 없습니다.

그렇다면 애초에 왜 목차를 제공하는 것일까요?

표준 브라우저 탐색을 지원하려는 사이트들을 위해, 어떤 제안이 있을까요?

이 동작의 원인이라고 의심되는 요소로 스크롤하는 동작을 monkeypatching하는 방법을 조사하고 있습니다. 다만 코드를 처음 접하는 상태라 전혀 아는 것이 없습니다. :slight_smile: 결국 해결은 하겠지만, 방향을 잡아줄 수 있는 팁이 있다면 정말 감사하겠습니다!

앵커를 사용할 맥락에 따라, 이 목차 플러그인이 유용할 수 있습니다(제 생각에는 이용약관 및 FAQ 페이지에 잘 맞을 것 같습니다). 예시는 여기 있습니다.

당신이 지적해 주지 않았다면 이 부분이 나를 불편하게 하고 있다는 사실조차 몰랐을 거예요. Discourse에서 링크를 클릭한 뒤 원래 있던 페이지로 돌아가려 하면, 의도치 않게 이전 페이지로 이동하는 경우가 많았거든요. 정말 짜증나는 일이었어요. 저는 거의 모든 Discourse 관련 활동을 iOS 앱으로 하니까, 그 앱의 문제와 제 실수가 겹친 결과라고만 여겼습니다.

이 TOC 컴포넌트는 정말 잘 만들어졌으며, 모든 문서 페이지에서 사용하고 있습니다. 이 부분에 기울인 노고에 진심으로 감사드립니다!

하지만 내비게이션 문제는 여전히 남아 있습니다. TOC의 링크를 클릭해도 브라우저 히스토리가 수정되지 않아, 뒤로 가기를 누르면 페이지에서 벗어나게 됩니다.

확실히 그런 것 같습니다. @Johani 님이 이 문제를 수정해 주시면 좋겠지만, 매우 복잡할 것 같은 느낌입니다. 아마 목차 링크를 클릭할 때 pushstate를 호출하면 될 것 같습니다.

테마 컴포넌트를 통해 워크어라운드(링크 내비게이션에 대한 Discourse의 관점에서 사이트를 커스터마이즈하는 적절하다고 할 수 있는 방법)를 구현했습니다. 이는 DiscoTOC에서 사용되는 패턴을 따르며, 포스트에 마커를 추가하여 동작을 트리거합니다. 해당 코드는 여기에서 확인하실 수 있습니다.

DiscoTOC가 URL 조각(fragment)과 브라우저 히스토리를 사용하도록 수정하는 것은 좋은 아이디어라고 생각합니다. 이는 내비게이션 방식을 변경해야 하므로 사소한 변경이 아닙니다. DiscoTOC는 링크의 href 대신 데이터 속성(data attributes)을 통해 타겟을 전달합니다. 또한 브라우저 URL(window.location)에 새로운 페이지 위치를 반영하려는 시도는 없습니다.

위에서 제가 사용한 패턴이 DiscoTOC에도 적용될 수 있다고 생각하지만, 현재 DiscoTOC의 접근 방식을 고려할 때 그 컴포넌트에 더 광범위한 영향을 미칠 것입니다.

pushstate는 조심해야 합니다… 아마 원하시는 것은 replacestate일 겁니다.

이 경우 pushState를 사용하는 것이 맞을 것 같습니다. 목표는 이전 위치로 돌아가는 것을 가능하게 하는 것이며, 이벤트가 방지되므로 이를 위해 히스토리에 push가 필요합니다.

이것이 예전에는 각 (이 예시에 맞게 조정하면) 이용약관 항목 하단에 작은 “맨 위로” 링크가 있었던 이유입니다… :thinking: