6P by GN⁺ 14일전 | ★ favorite | 댓글 1개
  • 앵커 링크는 단순히 버튼 클릭 → 제목으로 스크롤이라는 구조지만, 실제 구현 시 문제가 발생함
  • 하단에 위치한 제목은 뷰포트 상단으로 정확히 스크롤되지 않음, 이로 인해 UX 저하 발생
  • 이를 해결하기 위해 다양한 접근을 시도하며, 점점 더 정교하고 복잡한 방식으로 발전시킴

단순 해결: 패딩 추가

  • 하단 제목이 스크롤에 잡히도록 여백을 추가하는 방식
  • 델타를 계산해 padding 추가하면 해결 가능
  • 하지만 디자인 팀에서 불필요한 여백을 꺼릴 수 있음

실용적 해결: 트리거 라인 이동

  • 트리거 라인을 뷰포트 하단 쪽으로 이동시켜 하단 제목이 닿도록 조정
  • 문제는 제목이 뷰포트 맨 아래에 위치하게 되어 가독성이 떨어짐

개선안: 가상 트리거 포인트 생성

  • 실제 제목 위치는 그대로 두고, 트리거 발생 위치만 위쪽으로 이동한 가상 위치를 생성
  • 각 제목마다 다른 조정을 적용할 수 있는 유연성 확보
  • 하지만 첫 번째 제목은 너무 위로 이동되어 새로운 문제가 발생함 → 개별 조정이 필요

더 나은 방식: 트리거 위치 비례 이동

  • 모든 트리거를 동일하게 이동하지 않고, 첫 제목은 그대로, 마지막 제목은 최대 이동
  • 중간 제목은 위치에 따라 비례 이동
  • 제목 순서 유지스크롤 도달 가능성 보장이라는 조건을 충족
  • 이 방식은 단순하고 실용적, 대부분의 경우 적절히 작동

고급 접근: 커스텀 매핑 함수로 최적화

  • 트리거 위치를 임의로 25% 위치에 두었기 때문에, 가상 위치가 원래 위치에서 너무 벗어날 수 있음
  • 이를 해결하기 위해 MSE(Mean Squared Error) 를 활용한 최적화 접근을 도입

손실 함수 구성

  • Anchor Penalty: 가상 제목 위치가 원래 위치에서 벗어난 정도
  • Section Penalty: 섹션 간 거리(스크롤 길이)의 변화 정도
  • 두 값을 가중치로 조절해 최적의 트리거 위치를 도출

제약 조건

  • 페이지 범위 내 유지
  • 첫 번째 제목은 위로 이동하지 않음
  • 제목 순서 보존

인사이트: 단순 비례 이동의 한계

  • 매우 긴 페이지(ex. 성경 전체)에서는 전체에 걸쳐 작은 이동을 누적 적용해야 하는 비효율 발생
  • 페이지 길이가 길수록 오류가 커지고, UX에 악영향 가능성 있음

최종 해결: 스무스스텝 기반 가변 매핑 함수

  • 각 제목의 위치를 0~1 사이의 값으로 정규화하고, 이를 기반으로 조정 비율 계산
  • Smoothstep 함수(S(x) = 3x² - 2x³) 를 이용해 부드러운 전이 구현
  • 조정 시작 위치 a를 설정하여 특정 위치까지는 이동하지 않고 이후부터 부드럽게 상승
    • 예: a = 0.4이면 상위 40% 제목은 이동 없음, 하위 60%는 점진적 조정
  • 결과적으로, 상단 제목은 원래 위치 유지, 하단 제목은 최대 조정 적용 → 자연스러운 UX 제공

검증 및 마무리

  • 최종 구현은 설계적 정교함과 실용성의 균형을 갖춘 솔루션
  • 물론, 디자이너 피드백은 “...그냥 잘 작동하면 좋겠음”일 수 있음
  • 하지만 적어도 이 블로그 글은 영원히 기억될 정교한 엔지니어링의 기록으로 남게 됨
Hacker News 의견
  • 백엔드 개발자로서 프론트엔드 작업을 볼 때 가끔 복잡함에 놀라움을 느낌

    • 훌륭한 기사이며 작업도 잘 되어 있지만, 단순한 스크롤에 이렇게 많은 복잡성을 도입해야 하는지 의문이 듦
  • 사이드 내비게이션의 "활성 앵커" 표시의 UX 목적에 대한 질문

    • 독자가 긴 섹션의 중간에 있을 때, 화면에 보이지 않는 헤딩을 대신하여 현재 섹션을 상기시켜 줄 수 있음
    • 이는 스크롤한 헤딩이 아니라 화면에 보이는 섹션에 따라 작동함을 의미함
    • 작은 섹션이 화면의 대부분을 차지하지 못할 경우, 활성 표시가 유용하지 않을 수 있음
  • 앵커 링크의 가장 중요한 UX 기능은 다른 사람에게 보낼 수 있고 북마크로 저장할 수 있어야 함

    • 특정 섹션을 북마크할 수 있는 기능이 페이지 상단부터 시작해 스크롤하거나 앵커 링크를 클릭하는 것보다 훨씬 편리함
    • 이 웹사이트는 #anchor-name URL을 사용하지 않아 이 기능을 제공하지 않음
  • Jira의 앵커/영구 링크에 짜증이 나서 클릭했으나, 비슷하지만 다른 방식임

    • 키보드로 앵커로 이동할 수 없음
    • 저자에게 질문: 왜 HTML <a> 요소 대신 비상호작용 요소에 JS 이벤트 리스너를 사용했는지
  • 메인 페이지 콘텐츠 아래에 패딩을 추가하는 것이 이상적임

    • 콘텐츠의 끝부분이 뷰포트 하단에 고정되는 문제를 해결함
    • 모바일에서는 90vh, 더 큰 화면에서는 50vh의 마진이 적절함
    • 데스크탑에서는 90vh 마진이 어색해 보일 수 있음
  • 현대 브라우저에서는 텍스트 조각을 사용하여 페이지의 특정 부분을 강조할 수 있음

    • Chrome에서는 텍스트를 강조하고 오른쪽 클릭하여 "링크 복사"를 선택하면 됨
    • 앵커 대신 특정 텍스트 부분을 강조하는 데 매일 사용함
  • 여러 "활성" 상태를 허용하는 것도 가능함

    • 콘텐츠가 길면 두 섹션의 헤더가 모두 "활성" 상태가 될 수 있음
    • 짧은 콘텐츠에서는 너무 많은 부분이 강조될 수 있음
  • 다른 댓글을 읽는 것이 재미있음

    • 모바일에서 사이트 디자인이 흥미롭고 문제 해결이 명확히 전달됨
    • 팝업 없이 기술적인 내용을 다루는 블로그를 읽는 것이 신선함
  • Firefox 데스크탑에서 "아름다운 솔루션"이 "중간 섹션"을 강조함

    • 페이지 하단에 도달하지 않았을 때도 결론이 완전히 보임
    • 화면에 보이는 모든 앵커를 강조하는 것이 답임
  • 기사가 깔끔하고 블로그 디자인이 더 흥미로움

    • 오른쪽 정렬 방식은 마음에 들지 않지만, 왼쪽 팝업의 인라인 활성화는 매우 멋짐