Image Sprite

woolee의 기록보관소·2023년 1월 8일
0

FE개념정리

목록 보기
30/35

이미지 스프라이트

이미지 스프라이트(Image Sprite)는 여러 개의 이미지를 하나의 이미지로 합쳐서 관리하는 방식이다.

웹 페이지에서 이미지가 사용될 경우, 해당 이미지를 다운로드 받기 위해 웹 브라우저는 서버에 이미지를 요청한다. 사용되는 이미지가 많으면 많을 수록 그 수만큼 웹 브라우저가 서버에 요청을 해야 되므로 웹 페이지 로딩 시간이 오래 걸리게 된다.

그러므로 필요한 이미지들을 하나의 이미지에 합쳐놓고, 그 하나의 이미지만 다운로드 받아서 css 혹은 js 조작을 통해 이미지를 관리하면 웹 브라우저가 서버에 이미지를 요청하는 횟수를 줄일 수 있다.

이미지 스프라이트 기법을 사용하면, 웹페이지에 필요한 여러 이미지를 한번에 관리할 수도 있고 애니메이션을 만들 수도 있다.

예를 들어 위와 같은 이미지 1장을 두고
background-position의 값을 @keyframes로 저장해둔다.

@keyframes sprite-icon {
  0.00% { background-position: 0 0; }
  1.67% { background-position: -100px 0; }
  3.33% { background-position: -200px 0; }
  5.00% { background-position: -300px 0; }
  
  ...
  
  93.33% { background-position: -200px -900px; }
  95.00% { background-position: -300px -900px; }
  96.67% { background-position: -400px -900px; }
  98.33% { background-position: -500px -900px; }
}

그리고 나서,
원하는 아이콘에 애니메이션을 적용해준다.

.icon {
  /* animation: */
  animation: sprite-icon 3s steps(1) infinite;
}

모든 값을 css로 저장해두면 쉽지만 대신 유연하지 않다.
자바스크립트로 대응하면 유연하다.

let x = 0
let y = 0
let frames = ''
for (let i = 0; i < 60; i += 1) {
  frames += `${(100 / 60 * i).toFixed(2)}% { background-position: ${x}${x === 0 ? '' : 'px'} ${y}${y === 0 ? '' : 'px'}; }\n`
  if (x <= -500) {
    x = 0
    y -= 100
    continue
  }
  x -= 100
}

0(100/60*0) ~ 100(100/60*60)% 사이의 값을 반복한다.

이미지 스프라이트와 프론트엔드 최적화

image sprite를 사용하지 않고 개별 이미지를 사용하면 css 코드는 간결하다.
대신 이미지를 여러 번 요청해야 한다. 그러므로 이미지 전부를 다운로드하는 시간이 훨씬 길다.

http/1.x

http/1.x 에서는 클라이언트와 서버 간 tcp 연결당 최대 하나의 요청만 가능하다.
후속 요청을 하려면 tcp 연결을 재사용하기 위해 기다려야 하므로 페이지 로딩이 지연될 수밖에 없다. 이 때문에 브라우저에서는 서버와 여러 개의 병렬 tcp 연결을 진행하지만 그럼에도 제한적(보통 2~8개의 병렬 연결)이다.

개별 이미지들을 하나씩 요청하면 로드 시간도 길어지고 네트워크도 과부화된다.

물론 그렇다고 모든 개별 이미지들을 한번에 로드하는 것 또한 문제가 된다.

http/1.x에서의 한번에 너무 많은 직렬화 요청(many serialized requests in HTTP/1.x) 또한 로드 시간을 증가시키기 때문이다.

http/2

http/2를 사용하면 브라우저와 서버 간 모든 요청이 단일 tcp 연결에서 다중화된다. 즉, 동일한 tcp 연결에서 수십 개의 이미지를 병렬로 로드하는 게 가능해질 수 있다.

그럼 http/2에서 이미지 스프라이트를 통한 최적화는 무의미해지는가?

이에 대한 benchmarks 결과는 다음과 같다고 한다.

http/2가 http/1.x에 비해 로드 시간을 확실히 감소시키지만, http/2만으로 최적화를 달성하기에는 부족하다.
즉 sprite set을 통한 front-end 최적화는 http/2에서도 여전히 유효하다. (sprite set은 여전히 individual sprites보다 로드 시간이 빠르다)

로드 시간도 최적화되지만 동시에 html 마크업이 간결해지고 스크린 리더의 탐색 속도도 향상된다.

  • 개별 이미지를 img 요소의 src 속성에 작성하는 게 아니라 css background 속성을 사용하므로

물론 sprite set이 개발 복잡도를 높이는 건 분명한 단점이 된다.

  • 이미지 1장에 여러 이미지를 합쳐놓기에 그 1장이 손상되면 거기에 포함된 모든 이미지가 영향을 받는다.
  • 이미지가 1장 추가되면 sprite set을 새로 만들어야 하며, 각각 포지션이 정해져 있으므로 이전에 만든 포지션 코드들을 전부 변경해줘야 하는 등 문제가 생긴다.

참고

HTTP/2 arrives but sprite sets ain’t no dead
CSS 이미지 스프라이트

profile
https://medium.com/@wooleejaan

0개의 댓글