내 블로그는 워드프레스 무료 테마인 Pen 테마 를 적용 시킨 사이트다.
Pen 테마에는 게시물 목록 표기 기능을 설정 할 수 있는 기능이 있는데 무한 스크롤 or 페이지 번호로 설정할 수 있다.
그런데 어느 순간부터 무한 스크롤이 동작하지 않기 시작했다. 그래서 테스트 해본 것은 플러그인 전부 삭제, 테마 재설치 등.
포기하고 페이지 번호를 쓰다가 최근 워드프레스 관련 지식이 늘어 한번 테마를 뜯어 JavaScript 파일을 직접 수정해 문제를 해결 하였다.
그래서 나와 같은 문제를 가진 사람들에게 공유하기 위해 이 글을 작성 하게 되었다.
콘텐츠
Pen 테마 뜯어보기
테마를 뜯어보기 위해 내가 선택한 방법은 FTP 로 직접 파일들을 열어 보았다. FTP 로 접속하는 방법을 모르면 워드프레스 FTP 접속 방법: 워드프레스 편집의 기본 에 정리해 두었다.
테마는 FTP 접속 후 www/wp-content/themes 경로 내에 있다. 테마 이름에 따라 폴더들로 분리 되어 있다. 이 안에 pen 폴더에 들어가 보니 기본적인 functions.php, index.php 등의 파일 등이 있다.
그중 여러 테마 폴더를 뒤져보다 무한스크롤 기능이 담긴 것으로 추정되는 파일(pen-infinite-scrolling.js) 을 assets/js 폴더에서 발견 하였다.
그리고 해당 파일을 여러 실제로 동작하는 지 console.log(‘test’); 를 삽입해 실행해보니 실제 내 블로그에서 console.log 가 출력 되었다.
pen-infinite-scrolling.js 분석
파일은 찾았으니 해당 js 를 분석해 보았다. 일단 pen 테마는 기본적으로 JQuery 기반 임을 알았다. 여러 테스트를 하던 도중 infinite-scrolling 이 동작하는 경우가 한두 번 생겼는데 노가다 끝에 문제가 되는 부분을 발견 했다.
문제가 되는 부분은 약 50번 라인의 다음 코드 였다.
$window.on( 'scroll', function() {
if ( pen_infinite_scrolling_js.is_customize_preview ) {
return false;
}
var pages_total = parseInt( pen_infinite_scrolling_js.pages_total );
if ( $window.scrollTop() === $( document ).height() - $window.height()) { // 해당코드
여기서 문제가 발생한 이유는 $window.scrollTop() 때문.
해당 코드는 var $window = $(window); 로 선언 된 변수로 JQuery로 window 객체를 다루는 것이다.
해당 객체에 대한 설명은 중요하지 않고 어쨌든 $window.scrollTop() 이 구문은 나의 브라우저의 스크롤 바 의 수직 위치(높이) 를 가져온다.
그런데 해당 코드가 가져오는 값은 ‘소수 값을 포함’ 하여 가져온다.
그리고 이 값과 비교하는 뒤의 $( document ).height() – $window.height() 는 html 문서 – 나의 브라우저 창 높이 인데 이 값은 ‘정수’ 이다.
우연치 않게 스크롤 높이가 정수가 되고 해당 값과 동일 할 때만 해당 기능이 동작하게 짜여져 있는 것…!
근데 개발자 분이 이 버그가 우연치 않게 계속 발생 안 했을 확률이 매우 적은 버그였다. 그런데 왜 이게 문제가 안되었을까 싶어 찾다 여러 테스트를 하다 결국 원인을 발견 했다.
원인: 크로스 브라우징(Cross Browsing) 이슈
해당 용어는 웹 개발에서 중요한 용어 인데 다양한 브라우저(예: 크롬, 파이어폭스, 사파리, 엣지 등)에서 웹 사이트, 웹 어플리케이션이 일관된 방식으로 잘 작동하도록 만드는 프로세스다.
그래서 한 때 JQuery가 유행 했을 당시 그 이유에 이 크로스 브라우징 지원이 탁월했던 것도 있다.
문제는 위에 언급한 기능이 여러 테스트 결과 크롬(Chrome) 브라우저 에선 동작하는 것을 발견 했고 나는 주로 엣지(Edge)를 사용해 문제가 발생하던 것.
결론적으로 해당 scrollTop 메소드가 엣지 브라우저 에선 소수점을 반환 한다는 것이다.
그런데 이건 내 사이트에서 이용할 땐 그런데 막상 html 파일을 만들어 테스트를 해보았을 땐 정수로 잘 반환 된다.
//테스트 코드
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
var $window = $( window );
$(window).on( 'scroll', function() {
console.log($window.scrollTop());
});
</script>
<body>
<div style="background-color:red; height:3000px;">
</div>
</body>
원인 자체는 찾을 수 없다. 내가 설치한 플러그인이 문제일 수 있고 html 구성에 문제일 수도 있다. 다시 재 설치해도 동일한 이슈가 발견 되어 현상 자체를 고칠 수 없어 다음 방법으로 해결 하였다.
해결 방법
해결 방법은 의외로 간단했는데 $window.scrollTop() 를 Math.ceil($window.scrollTop()) 로 변경 한 것이다.
Math.ceil 는 괄호 안의 값의 소수점을 올림 하는 함수다. 반올림은 round, 버림은 floor.
즉, 정수 값으로만 만들어 주면 되는데 round, floor 를 하니 비교 값 보다 최대 스크롤 값이 작아 if 를 통과하지 못하여 ceil 로 해결 하였다.
그런데 이렇게 JavaScript 파일을 수정하면 문제가 있는데… 바로 테마 업데이트 시 초기화 된다는 점.
이를 위한 해결책은 다음 자식 테마 활용하기 참고.
자식 테마 활용하기
위에 말한 것과 같이 자식 테마를 활용해야 하는 이유는 테마 업데이트 시 변경 내역이 초기화 되기 때문이다. 자식 테마를 만드는 방법은 워드프레스 자식 테마(Child Theme)를 만드는 이유와 방법 에 정리되어 있다.
해당 자식 테마를 만들었으면 두 가지 작업이 필요한데, 먼저 original pen-infinite-scrolling.js 을 복사해 자식 테마 내 폴더에 만들어 준다. 나는 js 폴더 내 custum-pen-infinite-scrolling.js 라 이름을 붙였다.
그리고 자식 테마의 functions.php 를 열어 다음과 같은 코드를 추가해 준다.
<?php
function my_scripts_method() {
//pen 테마 무한스크롤 이슈 해결을 위한 부모 스크롤 js 제거 후 자식 js 파일 바라보게 함
$pen_is_singular = pen_is_singular();
$is_customize_preview = is_customize_preview() ? true : false;
if ( ! $pen_is_singular && pen_option_get( 'list_infinite_scrolling' ) ) {
global $paged, $wp_query;
$page_current = (int) $paged ? $paged : 1;
$page_next = intval( $page_current + 1 );
$pages_total = $wp_query->max_num_pages;
$url_page_next = false;
if ( $page_next <= $pages_total ) {
$url_page_next = next_posts( $pages_total, false );
}
$url_page_next = add_query_arg( 'pen_sticky_exclude', 'true', $url_page_next );
if ( $url_page_next ) { wp_dequeue_script('pen-infinite-scrolling');
wp_enqueue_script('child-inifinite-scroll', get_stylesheet_directory_uri() . '/js/custum-pen-infinite-scrolling.js');
wp_localize_script(
'child-inifinite-scroll',
'pen_infinite_scrolling_js',
array(
'is_customize_preview' => $is_customize_preview,
'allow_stop' => pen_option_get( 'list_infinite_scrolling_allow_stop' ) ? true : false,
'page_current' => (int) $page_current,
'pages_total' => (int) $pages_total,
'url_page_next' => esc_url( $url_page_next ),
'text' => array(
'stop' => esc_html__( 'Stop', 'pen' ),
'no_more_content' => esc_html__( 'Nothing else to show.', 'pen' ),
),
)
);
}
}
}
add_action('wp_enqueue_scripts', 'my_scripts_method', 20);
?>
해당 코드는 원본 pen_infinite_scrolling_js 를 제거하고 child-inifinite-scroll 을 추가해 준다.
이렇게 내 사이트의 무한 스크롤은 다시 살아나게 되었다 👍