티스토리 오프스크린 이미지 지연 로딩(Lazy loading) 하기2 - 프로미스 비동기 객체 사용

프로미스 비동기 async/await 는 인터넷 익스플로러에서는 지원되지 않습니다.

--------------------------------------------------------------------------

티스토리 서비스는 오프스크린 이미지 지연 로딩이 지원되고 있지 않기 때문에 페이지 로딩이 다른 포털 블로그 서비스에 비해 많이 느립니다.

특히 이미지가 많이 사용된 블로그 페이지는 페이지 로딩이 느릴 뿐만 아니라 검색 지수에서 않좋은 평가를 받기 때문에, 오프스크린 이미지 지연 로딩만 되도 보다 쾌적한 페이지 로딩을 경험할 수 있으며, 검색 지수도 다소 개선되는 모습을 볼 수 있습니다.

근본적으로는 티스토리 서비스에서 이미지 태그에 "srcset" 속성을 지원해야 하고, 낙후된 자바스크립트 라이브러리 구조가 개선되어야 오프스크린 이미지 로딩이 빛을 발할 수 있으며, 어디까지나 임시 방편입니다.

페이지 로딩 속도 및 검색 지수를 약간이나마 개선하는데 도움이 되는 방법으로 생각하고 사용하는 것을 추천합니다.

"lazysizes" 레이지 로딩 라이브러리를 사용하면 조금 더 쉽고 간단하게 구현할 수 있습니다.

"lazysizes" 레이지 로딩 라이브러리를 사용한 구현 방법은 다음 글을 참고하시면 됩니다.

티스토리 오프스크린 이미지 지연 로딩(Lazy loading) 하기1 - lazysizes 라이브러리 사용

프로미스 비동기 함수를 사용하면 바닐라 자바스크립트로 기본 스킨 자바스크립트 파일 안에 오프스크린 이미지 로딩을 구현할 수 있습니다.

스킨에 따라 자바스크립트 파일 명이 다를 수 있으므로 본인이 사용하는 티스토리 스킨의 자바스크립트 파일을 "images" 폴더에서 찾아야 합니다.

먼저 기본 자바스크립트 파일 안에 프로미스 객체를 생성하는 함수를 하나 붙여 넣습니다.

로딩되지 않은 오프스크린 이미지 영역이 화면 안으로 들어오면 이미지를 로딩하는 이벤트를 처리하는 함수입니다.

옵션 값 설정이나 프로미스 리졸브 처리를 잘 모르면 기본 코드 그대로 복붙해도 됩니다.

기본 자바스크립트 파일 맨 끝에 추가하면 됩니다.

/* 이미지가 뷰포트 안이면 비동기로 이미지 로딩 */
function onElementVisible(element, options = {}){
	// 기본 교차 옵저버 옵션 설정
	const intersectionObserverOptions = {
		rootMargin: '0px',
		threshold: 0.3,
		...options,
	};

	//이미지가 처음 화면 도큐먼트 뷰포트 영역 안에 표시되면 리졸브 콜백을 실행하는 프로미스 객체를 리턴
	return new Promise(resolve => {
		//옵저버 객체 생성
		const observer = new IntersectionObserver(async entries => {
			// 뷰포트와 교차한 목록
			const [entry] = entries;

			// 도큐먼트 루트와 교차했는지 체크
			if (entry.isIntersecting) {
				// 프로미스 리졸브 실행
				resolve();
				// 옵저버를 종료해 한번만 실행되도록 함
				observer.disconnect();
			}
		}, intersectionObserverOptions);
		observer.observe(element);
	});
}

6번째 줄의 "threshold" 옵션 값이 중요한데, 기본 설정 값은 0.3 입니다. "threshold" 값은 이미지가 어느정도 보여졌을 때 옵저버가 리졸브를 호출할 지를 정하는 값으모 0 ~ 1 사이의 값입니다. 1이면 이미지 영역이 100% 뷰포트 안에 보여지면 리졸브를 호출해 이미지를 로딩하게 됩니다.

이제 이 함수를 페이지 안의 모든 이미지 태그에 적용되도록 DOM 생성 후 이미지 태그에 옵저버를 부착해야 합니다.

먼저 "src" 속성으로 설정된 이미지 경로를 "1x1.png" 빈 이미지로 대체하고, "src" 속성을 "data-src" 속성으로 모두 변경해 이미지가 페이지 로딩 시점에 함께 로딩되지 않도록 해야 합니다.

스킨에서 사용하는 기본 자바스크립트 파일에 다음 코드를 추가해야 합니다.

const imgs = document.querySelectorAll('img');
if(imgs.length > 0){
	imgs.forEach(function(img){
		if(img.getAttribute('srcset') != null){
			img.setAttribute('data-srcset', img.getAttribute('srcset'));
			img.setAttribute('srcset', '티스토리PNG이미지경로');
		}
		if(img.getAttribute('src') != null){
			img.setAttribute('data-src', img.getAttribute('src'));
			img.setAttribute('src', '티스토리PNG이미지경로');
		}
		img.classList.add('lazyload');
	});
}

그리고 추가한 코드 밑에 다음 코드도 이어서 추가로 붙여 넣어야 합니다.

화면이 스크롤되면서 도큐먼트 뷰포트 안으로 이미지 태그가 처음 들어오면 "src" 속성과 "srcset" 속성을 원복해 이미지를 로딩하는 프로미스 객체를 매핑하는 코드입니다.

//"src"를 처리함 이미지 태그에 프로미스 비동기 함수를 매핑
[...document.querySelectorAll('img.lazyload')].forEach(async image => {
	await onElementVisible(image);
    //이미지 src, srcset 원복
	if(image.getAttribute('src') != null){
		image.setAttribute('src', image.getAttribute('data-src'));
	}
	if(image.getAttribute('srcset') != null){
		image.setAttribute('srcset', image.getAttribute('data-srcset'));
	}
});

앞의 두 코드 블록을 복붙할 위치를 잘 잡아야 합니다.

제이쿼리 기반의 스킨인 경우 기본 자바스크립트 파일의 다음 즉시 실행 함수를 찾아 안쪽 끝에 추가하면 됩니다.

(function($) {
/* 끝 부분에 추가*/
})(jQuery);

바닐라 자바스크립트 코드로 작성한 파일인 경우 다음 이벤트리스너 안쪽 끝에 추가하면 됩니다.

window.addEventListener('DOMContentLoaded', function(event){
/* 끝 부분에 추가*/
}

복붙한 후 두 번째 복붙한 코드 블록 안의 "티스토리PNG이미지경로" 문자열을 실제로 업로드 해 놓은 "png" 이미지 파일 경로로 변경해야 합니다.

앞서 업로드한 "1x1.png" 파일의 경로를 얻어 붙여넣으면 됩니다. 스킨편집기 화면 "파일업로드" 에서 확인할 수 있습니다.

1x1.png 이미지 경로 얻기

적용 후에는 웹브라우저 캐시를 한번 소거해줘야 합니다. 캐시된 이미지가 없어야 레이지로딩이 적용되는 것을 확인할수 있습니다.

웹브라우저 개발자 도구를 열어 "Network(네트워크)" 탭을 선택한 후, 내 블로그 페이지를 열어서 화면을 스크롤 하면 추가로 이미지를 로딩되는지 확인하면 됩니다.

페이지 스크롤에 따라 비동기로 로딩된 이미지들

완성된 소스와 "1x1.png" 이미지는 다음 다운로드 링크에서 다운로드 받을 수 있습니다.

사용하는 티스토리 스킨의 기본 자바스크립트 파일 안의 적당한 위치에 복붙해서 사용할 수 있습니다.

promise_lazyload.zip0.00MB