개발

사용자 인터랙션을 기반으로 실행되는 자바 스크립트 헬퍼 함수


모든 DOM 구현, 스크립트 처리를 그냥 의식의 흐름대로 처리를하면 초기 페이지 로드까지 꽤나 시간이 걸리는게 현실이다.
특히나 요즘처럼 서버 사이드 랜더링(SSR) 방식으로 처리를하면 DOM 크기도 상대적으로 커지기도하고, 사용자의 기능을 보조하기위한 스크립트를 채용하면 로딩시간은 더 지연되는게 현실이다.

예전보다 컴퓨팅 파워가 워낙 좋아졌고, 클라이언트단에서의 브라우저 지원도 좋아져서 요즘 웹사이트를 개발/퍼블리싱하는데 이런 사항을 고려할일은 적긴하다만 이런 '웹 최적화'는 항상 연구자들의 고민이기도하다.


사용자 인터랙션을 기반으로 실행되는 자바 스크립트 헬퍼 함수구글 페이지스피드 결과, 모두 초록색 합격점을 받기란 실질적으로 너무 힘들다

특히나 요즘들어서 구글의 사이트 평가에 여러가지 웹지표를 사용하기 시작하고 웹사이트 속도 체크와 평가 기준이 더욱 확실히 되고있는 상황에서 그냥 막무가내로 사이트를 만들었다가는 '느린 사이트'로 낙인찍혀 웹 수집은 쉽게 물건너가는게 현실이다.

대부분 블로그등의 개인 웹사이트는 플랫폼을 이용해서 만들게되고, 이런 플랫폼 코드는 위에서 서술한것을 어느정도 기본적으로 제공, 보장하기 때문에 사용자단에서 고려할일은 없다.
하지만 나처럼 개인 서버에 개인 사이트를 운영하는 사람은 그런 과정을 전부 스스로 구현해야하는 상황인것이다.

특히나 나는 여기서 DOM의 1차적인 로드 완료 후 스크립트 처리에서 최적화 하는방법에 대해 예전부터 부단히 고민을 해왔다.
다름이 아니라 '애드센스'의 처리때문이다.

애드센스는 스크립트 형식으로 구글의 애드센스 스크립트가 알아서 내 사이트의 지정된 위치나 자동으로 특정한 위치에 광고를 가져와 삽입하는 방식을 취하고있다.
이런 스크립트 처리는 당연히 웹사이트의 속도를 느리게하는 주범이다.

하지만 이런 스크립트 처리는 쉽게 우리가 뜯어볼수도 없고 조작하는것도 힘들다.
우리선에서 할 수 있는건 그저 해당 스크립트의 실행 타이밍을 조정할 수 있는 정도이다.

그런 의미에서 이전에 올렸던 포스팅, 사용자 인터랙션 핸들러 방식을 이용하면 그나마 사용자의 조작을 기준으로 스크립트의 실행 지연을 유도할 수 있고, 초기 페이지 로드와는 별개로 처리할 수 있어 웹사이트의 로딩속도를 혁신적으로 줄일 수 있다.


여기에서 나는 이런 인터랙션 핸들러 방식의 재사용을 하고싶었고 기존의 코드를 약간 손봐서 아래와 같이 재구성 해보았다.

function onUserInteraction(callback, timeout = 5000) {
    if (typeof callback !== 'function') return;

    let triggered = false;
    const events = ['scroll', 'mousemove', 'touchstart', 'keydown'];

    const doTrigger = () => {
        if (triggered) return;
        triggered = true;
        callback();
        events.forEach(e => window.removeEventListener(e, handleInteraction));
    };

    const handleInteraction = (event) => {
        if (event.type === 'scroll' && window.scrollY === 0) return;
        doTrigger();
    };

    events.forEach(e => {
        window.addEventListener(e, handleInteraction, { passive: true });
    });

    setTimeout(doTrigger, timeout);
}Copy

인터랙션 핸들러를 다른데에서 재사용하기위해서 위와같이 구현해두고 아래와 같이 필요한 위치에서 핸들러를 호출해 간단하게 사용할 수 있다.

onUserInteraction(() => {
    initAd();
});

onUserInteraction(() => console.log('A triggered'));
onUserInteraction(() => console.log('B triggered'));Copy

위 헬퍼함수는 1회만 실행되도록 제약이 걸려져 있으나 핸들러 내부의 변수로인해 각각의 호출에따라 독립적인 1회 실행을 보장한다.
즉 위에처럼 반복적으로 여러번 헬퍼함수를 호출해도 문제없다.


이런 방식으로 처리하면 최초 페이지로드와 사용자가보는 최종 페이지의 차별적인 전략을 통해 페이지 평가지표와 사용자 경험 두가지를 모두 잡을 수 있다.

본문 이미지최초 페이지 로드시 화면
본문 이미지사용자 인터렉션 이후 최종 화면

위의 예시처럼 두 화면은 같은 페이지를 보여준다.
하지만 좌측의 경우가 웹 크롤러나 수집기가 보는 최초의 페이지이고, 우측의 경우가 실제 사용자가 보는 화면이다.

나는 상대적으로 사용자에게는 시각적으로 중요한 댓글입력란, 컬렉션 카드, 카테고리 카드같은건 인터렉션 기반 지연로딩을 적용했다.
실제로 이렇게 해당페이지의 핵심 컨텐츠는 남겨두고 보조 컨텐츠는 지연로딩 하는게 의외로 웹사이트 최적화에 매우 도움이 된다.

뭐 꼼수라면 꼼수이긴하지만 말이다.
끝!


#JavaScript
0 개의 댓글
×