Javascript

이미지 미리 불러오기(image preload) :: 마이구미

mygumi 2017. 12. 27. 20:12
반응형

이 글은 이미지를 미리 로딩하는 법에 대해 다룬다.

흔히 이미지 프리로딩(Image Preloading) 이라고 불린다.

참고 - https://www.photo-mark.com/notes/image-preloading/


웹 사이트에는 많은 이미지가 존재한다.

특히 갤러리 관련 페이지에는 더욱 많을 것이다.

많은 자원을 통해 웹 페이지는 무거워질 수 밖에 없다.

그에 대한 해결책으로 현재는 이미지의 크기, 질 등을 최소화하는 작업이 존재한다.


다른 방법 중에는 preloading 이 존재한다.

용어 그대로 이미지를 미리 로딩해놓는다는 의미가 된다.

즉, preloading 은 미리 로딩하고 캐시로 가져오게 하는 방식이다.


preloading 을 구현하는 방법은 여러가지가 존재한다.

자바스크립트를 활용한 대표적인 방법은 다음과 같다.

그 외에도 css, ajax 등 많은 방법이 있지만, 어렵지도 중요하지 않기에 다른 방식은 생략하겠다.


function preloading (imageArray) { let n = imageArray.length; for (let i = 0; i < n; i++) { let img = new Image(); img.src = imageArray[i]; } } preloading([ '1.png', '2.png', '3.png' ])


위 방식을 통해 각 이미지들을 가져올 수 있게 된다.



개발자 도구를 통해 확인해볼 수 있듯이 미리 로딩할 이미지들이 로드된 것을 볼 수 있다.

거의 비슷한 시간에 모든 이미지들이 로딩이 시작된 것을 볼 수 있다.

왜냐하면 비동기(async)로 동작하기 때문이다.


우리의 목적은 미리 로딩하는 것이기 때문에 크게 신경쓰지 않을 것이다.

하지만 우선순위가 높은 이미지가 보이지 않을 수도 있다.

이러한 문제를 피하기 위해 preloading 을 적용했는데 무슨 말인지 의아할 수도 있다.


위 개발자 도구의 그림을 다시 보면, 비동기적으로 인해 병렬적으로 처리되는 모습을 볼 수 있다.

병렬과 직렬의 차이를 생각해보면 된다.

병렬은 여러개를 동시에 처리할 수 있다는 장점이 있지만, 그 의미가 직렬보다 훨씬 빠르다는 것은 아니다. (경우에 따라, 오히려 느릴 수도 있다.)

그림을 보다시피, 병렬처리로 인해 비슷하게 완료되지만, 다운로드 시간이 길다는 것을 알 수 있다.

그로 인해, 우선순위와 상관없이 한번에 처리한다면, 우선순위가 높은 이미지의 로딩이 지연될 수 있다.


이러한 경우, 동기식 처리가 필요하다.

동기적으로 인해 순차적으로 처리되는 그림은 다음과 같다.



비록 전체적인 시간은 느린 모습을 보였지만, 각 이미지 다운로드 시간은 확실히 줄어든 모습을 볼 수 있다.

병렬 처리에 대한 문제점을 기준으로 잡았지만, 반대의 상황에서는 당연히 순차적 처리가 문제가 된다.

결국 사용자 경험, 상황, 목적 등에 따라 어떠한 방식으로 preloading 할 것인지 선택해야한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Preloader {
 
  constructor () {}
 
  static series (imageArray) {
    let n = imageArray.length
    for (let i = 0; i < n; i++) {
      let img = new Image()
      img.src = imageArray[i]
    }
  }
 
  static parallel (imageArray, idx) {
    let index = idx || 0
    if (imageArray && imageArray.length > index) {
      let img = new Image()
      img.onload = function () {
        preload(imageArray, index + 1)
      }
      img.src = imageArray[index]
    }
  }
 
  static inject (id) {
    let div = document.createElement("div")
    div.id = id
div.style.position= 'absolute'
    div.style.top = '-9999px'
div.style.left = '-9999px'
    document.body.appendChild(div)
  }
 
}
cs


반응형