이미지 스프라이트(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 마크업이 간결해지고 스크린 리더의 탐색 속도도 향상된다.
물론 sprite set이 개발 복잡도를 높이는 건 분명한 단점이 된다.