새로운 방법 추가!
해당 방법보다 더 좋은 아이디어로 개발했습니다. 해당 게시글 참고 해주세요!
발단
Hudi님의 블로그를 보다 보니 게시글 목록이 무한 스크롤로 구성되어 있었다. 필자도 구현하고 싶어서 여러 가지 방법을 찾아보았다.
찾아보니 제일 좋은 방법은 IntersectionObserver
를 이용하는 것이라고 한다.
InsersectionObserver
란 상위 요소와의 교차 영역에 대한 변화를 비동기적으로 감지하는 API. element가 화면에 노출되었는지 여부를 간단하게 구독할 수 있음.
문제
그런데 문제는, hugo와 js가 궁합이 그렇게 좋지 않다는 것이다.
블로그 게시글 hugo 템플릿과 js는 공존이 불가능하다.
var num = 1
var test = `
{{ $test := 1 }}{{ $test }}{{ ${num} }}
`
위와 같은 코드는 빌드 시에 아래처럼 에러가 발생한다.
이유가 무엇일까? 우리는 hugo 빌드
와 js 실행
사이의 순서를 알아야 한다.
- hugo 빌드
- hugo 템플릿에 값들이 설정되어 변환됨
- ex.
{{ $test := 1 }}{{ $test }}
라는 템플릿은1
로 변환
- ex.
- 변환된 html이 배포됨
- 사용자가 해당 사이트에 접속할 때 js 실행
즉, hugo 빌드 시점에 템플릿에는 값이 설정되어야 하는데 js가 실행되지 않았으므로 빌드를 완료할 수 없는 것이다.
해결 방법
방법은 전체 html을 만들어 놓고, 필요에 따라 잘라서 집어 넣는 것이다.
<section id="posts" class="article-list">
<!-- 게시글 목록이 보여질 곳 -->
</section>
<!-- IntersectionObserver로 구독할 element -->
<div id="posts-footer"></div>
<script>
// 전체 게시글 대상으로 게시글 목록 html을 생성
// "__pd__"의 경우 게시글과 게시글 사이 구분자
var pageHtml = `
{{ range $index, $element := $filtered }}
{{ partial "article-list/default" . }}
{{ "__pd__" }}
{{ end }}
`
// 구분자로 html을 게시글 html list로 만듦
var pageHtmlList = pageHtml.split('__pd__')
// 현재 보여지는 게시글 갯수
var currCnt = 0
// 몇 개씩 보여질지
var paginate = 10
var intersectionObserver = new IntersectionObserver((entries)=>{
// intersectionRatio가 0 이하이면 아직 노출되지 않은 것
if (entries[0].intersectionRatio <= 0) return;
// 게시글 추가 이후 보여지는 게시글 갯수
let nextCnt = currCnt + paginate
for (let i = currCnt; i < nextCnt && i < pageHtmlList.length; i++){
// 게시글 추가
document.querySelector('#posts').innerHTML += pageHtmlList[i]
}
// 현재 게시글 갯수 업데이트
currCnt = nextCnt
console.log('Loaded new items');
});
// element 구독
intersectionObserver.observe(document.querySelector('#posts-footer'));
</script>
이렇게 하면 정상 구동하는 것을 확인할 수 있다.
위 영상을 보면, 새로고침하고나서 Loaded new items
가 한번 출력되고, 이후 스크롤을 내리면서 <div id="posts-footer"></div>
가 화면에 노출될 때 마다 Loaded new items
가 계속해서 호출되는 것을 볼 수 있다.
후기
쉬울듯 하면서도 생각보다 너무 어려웠다. hugo 템플릿은 브라우저에서 동적으로 작동하지 않는다.
라는 것을 모르는 상태에서 js와 결합하려고 하니 그랬던 것 같다. 그래도 IntersectionObserver
를 알게되고, hugo 템플릿의 작동 방식
을 알게된 좋은 기회였다.
하지만 조금은 아쉬운 방식이다. 저 방식은 한 html에 모든 데이터를 가지고 있고 보여주는 것만 잘라서 보여주는 것이니까, 본질적으로 한번에 모든 데이터를 보여주는 것과 똑같다고 느껴진다. 조금 더 hugo의 정보를 찾아봐서 다른 방식을 찾아봐야 겠다.
오랜만에 하나하나 내가 원하는 것을 만들어가는 재미를 느낀 것 같다. 앞으로도 더 많이 꾸며봐야지.