brunch

You can make anything
by writing

C.S.Lewis

by 찐님 Oct 05. 2023

프론트 TIL - TOC를 만들어보자

TOC라는 개념을 이번 사이드 프로젝트를 하며 알게되었다. 

Table of Contents의 약자로 직역하면 목차이다. 


포스팅 옆에 보면 목차가 있고, 

그 목차를 클릭하면 그 컨텐츠로 스크롤이 이동하는 기능을 자주 보았을 것이다.


그 기능을 구현하는 것이 이번 스프린트에서 내가 할 일이었다. 





기본 로직


전제 : 포스팅을 발행하면 DB에 HTML태그가 string으로 저장되며, 각 태그들은 유니크한 id값을 가짐 

순서 : 

     1. DB에 저장된 string형태의  html 태그들 중 h1~h3 태그만 선택한다.

    2. 가져온 h태그들이 목차가 된다.

    3. 목차를 클릭하면 해당 내용이 있는 곳으로 스크롤 이동

    4. 스크롤을 하다가 h태그를 만나면 해당 목차 강조








STEP 1.



string HTML -> DOM변환



DOMParser() 객체를 생성 후 parseFromString 메서드 사용

DOM String (DOM의 문자열형태)을 인자로 받아 DOM 객체를 반환한다.



h1~h3 태그 선택


querySelecterAll 메소드를 사용하여 h1~h3까지 태그를 모두 선택

querySelecterAll 의 반환값은 NodeList로 배열과 유사하지만 배열은 아니다.

 ➡️ 따라서, 배열 메소드 사용불가 (ex. map, filter 등) 


 TOC배열 생성


선택한 h태그들을 순회하며 본문, 태그명, id값을 추출하여 객체 배열을 생성

text는 각 목차의 제목을, tag는 목차의 들여쓰기 기준을, 그리고 id는 스크롤의 위치를 나타낸다.





※STEP 2. 



TOC 목차 클릭 시 스크롤 이동 이벤트 

useScrollPosition.ts


useScrollPostition이라는 커스텀 Hooks를 만들었다. 

useEffect 를 사용해 페이지가 렌더링되면 스크롤 이벤트를 등록하고, 페이지를 벗어나면 제거한다.

scrollToEl은 TOC의 제목을 클릭하면 해당 태그가 있는 곳으로 스크롤을 이동하는 이벤트이다.


하지만, 태그에 랜덤 id값을 추가하기 이전 코드라서 로직이 이상하다. 지금은 id로 바로 구분이 가능하지만 이전 코드에서 그나마 태그들의 순서를 구별할 수 있는 값이 제목(textcontents)뿐이라 직접 순회하며 비교했었다. 




※STEP 3. 



스크롤할 때 TOC 제목 강조 이벤트

포스팅을 읽으면서 스크롤을 내릴 때 옆에 있는 TOC의 제목이 강조되는 것을 본 적이 있을 것이다.


이렇게 동작하는 이벤트 함수를 직접 만들 것이다.




요약하자면, 현재 스크롤의 위치와 h1~h3의 Y축 위치값을 비교하는 것이다. 

현 스크롤 위치보다 큰 최초의 태그를 활성화 시켜 유저가 보고 있는 영역이라고 가정하는 것이다. 


복잡해보이지만 결국 activeItemId 가 리턴하는 것은 스크롤 위치보다 큰 첫번째 태그의 아이디값이다. 




그리고 적용은 위와 같이 특정 조건을 만족할 때 class값을 삽입하는 형태로 했다. 






참고

https://www.ha0.work/detail/64cb416b3ddb51328e615e2e

작가의 이전글 현타
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari