javascript로 한 이미지의 url을 다른 것으로 바꿔치기

휴대폰을 위한 웹페이지를 만드는데, 배경에 사용될 그림의 크기가 1920 x 11400이고, 파일의 크기가 4MB나 된다.
이 비대한 배경이미지때문에 넓은 부분이 하얗게 남아있고, 레이아웃중인 어정쩡한 상태의 화면이 장시간동안 나타나며, 그 시간동안 사용자의 조작에 응답하지 못한다.

해결방법은 배경이미지의 크기를 아주 작게 만들어서, 큰 배경이미지가 주는 부담을 제거하는 것이다.

그래서, 처음에는 50x297 크기의 배경이미지를 사용하고, 나중에 더 높은 해상도의 배경이미지로 교체하는 방법으로 이 문제를 해결했다.

이 방법을 적용하고나니 처음에는 생각하지 않았던 좋은 점이 생겼는데, 화면이 작은 휴대폰에는 너무 큰 이미지를 사용하지 않아도 된다는 것이다. 화면 크기가 480 x 800인 휴대폰에 1920 x 11400 크기의 이미지가 무슨 소용인가? 더군다나 사용자가 zoom도 하지 못하게 차단시킨 상태인데.



바꿔치기하는 방법은 다음과 같다.


1. img 태그를 둔다. 처음에는 width=50px인 이미지를 표시한다. 웹페이지가 열리면서 이 작은 이미지가 재빠르게 로드되고, 이미지는 확대되어 화면 가득 표시된다. 굉장히 저화질의 화면을 얻게 된다.

  <img id="bg" src="poo-50.jpg" />

poo-50.jpg는 너비가 50픽셀이고,
poo-150.jpg는 너비가 150픽셀이고,
poo-1920.jpg는 너비가 1920픽셀이다.




2. 이 이미지의 로딩이 완료되면 load이벤트가 발생하는데, 이때 해상도가 더 높은 이미지로 교체한다. 그런데 이미지가 캐쉬되어있으면 load이벤트가 없다고 한다. 그래서, 이미 로딩이 완료되었는지를 확인하여 로딩완료된 경우라면 load() 이벤트 핸들러를 호출해준다.

  $(document).ready( function(){
    $('#bg').on('load', higher_resolution).
         each( function() {
           if( this.complete ) $(this).load();
         });
    ...
  });




3. higher_resolution() 이라는 함수는 다음과 같다.

  var res = 50;

  function higher_resolution() {

    switch( res ) {

      case   50:
        res=150;
        setTimeout('$("#bg").attr("src", "poo-150.jpg")', 500);
        break;

      case  150:
        res=1920;
        setTimeout('$("#bg").attr("src", "poo-1920.jpg")', 500);
        break;

      case 1920:
        break;
    }
  }




4. poo-50.jpg가 로드되어 화면에 나타난 후 500ms를 기다렸다가 poo-150.jpg를 로딩하기 시작한다. 이 500ms라는 시간동안 브라우저는 레이아웃 등의 작업을 하게 된다. poo-150.jpg가 로드되어 화면에 나타나면 500ms후에 poo-1920.jpg를 로딩하기 시작한다.




5. 아래와 같이 조건문을 하나 삽입하면, 휴대폰 화면 크기보다 큰 이미지를 불필요하게 로딩하는 경우를 피할 수 있다.

  var res = 50;
  function higher_resolution() {
    switch( res ) {
      case   50:
        if($(window).width() > res)
          res=150,
          setTimeout('$("#bg").attr("src", "poo-150.jpg")', 500);
        break;
      case  150:
        if($(window).width() > res)
          res=1920,
          setTimeout('$("#bg").attr("src", "poo-1920.jpg")', 500);
        break;
      case 1920:
        break;
    }
  }





6. 위의 예들은 최저해상도의 이미지에서 조금씩 높은 해상도의 이미지로 점진적으로 바꿔치기하고 있다.
최저해상도 이미지에서 최적의 해상도 이미지로 단 1회 바꿔치기를 하려면 다음과 같이 한다. 뿌옇게 답답한 화면이 좀 오래 지속되는 반면에 트래픽을 더 많이 감소시킬 수 있다.

  function higher_resolution() {
    var ww = $(window).width();
    var rs = [50, 150, 800, 1300, 1920];
    if( ww > res ) {
      for( var i=0; i<rs.length; i++ ) {
        if( ww <= rs[i] ) break;
      }
      if( rs.length == i ) {
        res = 999999999;
        src = "poo-" + rs[ rs.length-1 ] + ".jpg";
      }
      else {
        res = rs[i];
        src = "poo-" + rs[i] + ".jpg";
      }
      setTimeout('$("#bg").attr("src", "' + src + '")', 1000);
    }
  }





7. 화면 폭의 변화는 휴대폰이 회전되었을때도 일어난다. 그래서 다음과 같은 코드도 필요하다.

  $(document).ready( function(){
    ...
    $(window).on('orientationchange resize', function(){
      higher_resolution();
    });
    ...
  )};