Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Tags more
Archives
Today
Total
관리 메뉴

eumjo_o

image 이해 (sprite image, bitmap, base64) 본문

카테고리 없음

image 이해 (sprite image, bitmap, base64)

eumjo_o 2023. 4. 27. 10:47

image 이해 (sprite image, bitmap, base64)

Sprite Image

Sprite Image는 여러 개의 작은 이미지들을 하나의 이미지 파일로 합쳐 놓은 것이다. 이렇게 하면 이미지 파일을 한 번에 한 번만 다운로드하므로, 페이지 로딩 속도가 빨라진다. 또한, CSS background-position 속성을 사용하여 필요한 이미지만 보이게 할 수 있다.

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Images/Implementing_image_sprites_in_CSS

Mapbox 공식 문서

https://docs.mapbox.com/mapbox-gl-js/style-spec/sprite/

https://docs.mapbox.com/help/glossary/sprite/

sprite  is a single image that contains all the icon and pattern images included in a style

위의 이미지 한 개가 sprite 이다. 그리고 그 내부의 개별 이미지들은 위에서 언급했듯, css 스타일링을 통해 정렬이나, 개별 속성을 조작하는 작업이 가능하다. 지도는 렌더해야 하는 데이터들이 많기 때문에, 성능이 매우 중요한데, Sprite 형태로 지도 렌더링 속도가 빨라지니 Sprite는 매우 중요한 요소라는 생각이 들었다.

스프라이트 이미지에서 특정 이미지를 사용하고 싶으면 해당 이미지의 정확한 width, height 정보를 알아야하고, 스프라이트 이미지 내에서의 position 값도 알아야 하는데, 해당 정보들은 JSON 파일로 관리된다.

모든 sprite image는 상응하는 JSON 파일을 가지는데, 이는 각각의 image에 대한 정보이다.

"airport-15": {
  "width": 42,
  "height": 42,
  "x": 76,
  "y": 300,
  "pixelRatio": 2,
  "visible": true
}

즉 sprite image 또는 sprite json 의 형태로 이용 가능하다.

mapbox에서 지도 sprite를 사용하고 싶으면 아래처럼 style 에 sprite를 명시해 주어야 한다.

"sprite": "<https://example.com/sprite>"

위 코드처럼 명시하면, 지도는 아래 두 가지 방법 중 하나로 sprite를 불러오게 된다.

  1. https://example.com/sprite.json and https://example.com/sprite.png,
  2. https://example.com/sprite@2x.json and https://example.com/sprite@2x.png

해당 sprite 리소스는 mapbox에서 다운받아서 사용할 수 있는데, 기존 Sprite 정보를 바탕으로 직접 sprite image / json 데이터를 조작 수도 있다.

image 정보를 조작하는 방법 중 가장 많이 쓰이는 것이 node-canvas 이다.

https://github.com/Automattic/node-canvas 를 사용하여 image를 원하는 방식으로 새로 그려보았다.

구현 방법은 간단하다. 기존 Sprite에 추가하고 싶은 여러 이미지들의 리스트를 순회하면서 node-canvas 를 활용하여 하나씩 그려넣을 수 있다.

그러면 기존에 Sprite Image/ Json에 내가 원하는 이미지들이 새로 추가된 Sprite Image / Json 파일이 생성된다.

node-canvas를 사용해서 image를 새로 그리는 과정은 아래와 같다.

  1. Sprite Image, Json 데이터 로드
  2. 새로 추가하려는 아이콘들의 정보 로드
  3. canvas 생성
  4. canvas에 Sprite그리기
  5. canvas에 새로 그리려는 아이콘들의 영역 확보하기
  6. canvas에 확보해둔 아이콘 영역에 새로운 아이콘들 그려넣기
  7. 새로운 Sprite Image 완성!!!
const canvas = createCanvas(spriteImage.width, spriteImage.height);
const context = canvas.getContext('2d');

context.drawImage(spriteImage, 0, 0, spriteImage.width, spriteImage.height);
context.clearRect(iconInfo.x, iconInfo.y, iconInfo.width, iconInfo.height);
context.drawImage(iconImage, 0, 0, iconImage.width, iconImage.height, iconInfo.x, iconInfo.y, iconInfo.width, iconInfo.height);

// canvas.toBuffer() => 새로운 spriteImage가 됨

canvas를 사용해서 이미지를 그리는 방식은 한번쯤은 경험해 보면 좋다고 생각되는데, 예제 코드가 상당히 많기 때문에 인터넷 상에서 돌아다니는 여러 코드를 참고했다. 추가적인 예시가 될 수 있는 사이트는 다음과 같다.

Sprite Image의 장점과 단점

장점

  • 여러 이미지를 하나의 이미지로 관리하기 때문에, 서버에 요청수를 줄여 로드되는 시간을 단축할 수 있다.
  • hover와 같은 이벤트로 노출되는 이미지들의 경우에는 이미 Sprite로 로드되어 있기 때문에 로딩 시에 delay가 없다는 장점이 있다.
  • Sprite image 파일 하나만을 관리하기 때문에 관리하기 편하다.

단점

  • Sprite 이미지에서 사용하려는 개별 이미지의 경우에는 정확한 위치값을 알아야 한다. (x, y position)
    • 따라서 json 파일 정보가 필수
  • Sprite 이미지에서 사용하려는 이미지를 변경해야 할 때 단일 파일을 변경하는 것보다는 아무래도 리소스가 든다. 위에서 node-canvas를 사용해서 새로운 Sprite를 굽는 과정이 단적인 예이다.

그럼에도 로딩 시간을 위해서는 Sprite로 여러 아이콘들을 관리하는게 용이하다는 결론을 내렸다.

추가적으로 Sprite 이미지가 실시간으로 업데이트 되어야 하는 상황을 가정해보았을 때, 이미지로 서빙하는 시간과 Base64로 구성된 문자열 데이터들을 사용해서 이미지를 노출하는 방법 두 가지를 모두 가정해 보았다.

이를 위해서 이미지 개념을 살짝 정리하고 넘어가겠다.

// 픽셀로 이미지 서빙
<img src="이미지.png" alt="" /> 
// 문자열로 이미지 서빙
<img src="base64 인코딩 문자" alt="" /> 

Bitmap <픽셀로 이미지로 서빙>

https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap

Bitmap은 이미지를 픽셀 단위로 표현하는 방식이다. 이러한 이미지는 파일 크기가 크고, 이미지를 확대하면 픽셀이 뚜렷하게 보인다. 따라서, 이미지를 확대할 필요가 없을 경우에 사용하는 것이 좋다.

  • 웹 상에서 가장 많이 접하는 이미지 포맷으로, JPG, PNG, GIF 모두 비트맵 확장자이다.
  • 아래 그림과 같이 이미지의 각 점들을 픽셀 단위로 나타낸 형태이고, 화면 확대 시 깨짐현상이 존재하는 이미지 포맷이다.https://wooono.tistory.com/358

Base64 <문자열로 이미지 서빙>

Base64는 이미지를 문자열로 인코딩하여 저장하는 방식입니다. 이렇게 하면 이미지를 서버에 업로드하지 않고, HTML 파일 안에 바로 삽입할 수 있다. 하지만, 이미지 파일이 큰 경우에는 HTML 파일이 너무 무거워질 수 있다.

https://developer.mozilla.org/en-US/docs/Glossary/Base64

https://pilot376.tistory.com/3

  • 8비트 이진 데이터를 문자 코드에 영향을 받지 않는 공통 ASCII 문자열로 바꾸는 인코딩 방식을 가리킨다.

data:image/gif;base64,R0lGODlhDwAOAPYBAAAAAP///+Pj5MzS6qy33bfA4sDI5dne8I6e0JGg0Zim1Jqo1aGu2H6SyZOj0HWMxYWYytbY3V98vLG801p9ulN6u2SHw0JvtYiix8vU4TBmsDBmrx9fqyJgrEB1uGCOxRpeqoGjygdXpwlYpw5aqBVhrGOUx6C+3N/p8+/0+dzd3gBVpQNWpgtdphBgqxpmqxpnqyBqsDB1tmqbx3CfzJe62Z+/3a/K46/J4r/V6c/f7t/q9AJaoQhcpAlcpVuSwh9sqC10rF+Xv5G20cXY5cba5wxnnZu7zXKfthhxmS6EloezvVqcqFeeqJq+w1SjqYC0sajNysrh3drp4trn4fD49O/18vb6+Pf5+OXs6Pz9/Pv8+////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAPAA4AAAeYgAEBThYVFxocJCwrL4KCW0gIDxIUGyAiKys6jlMhCg0TKhgdI5kzjksGDA4RKgInLpkwglhHAwQJEBmCOrErOAFUNQcFCx4uN4IpMis/AUwrJh8lKy45gjvMLQFPmZkymwG9mT4oVU2ZMSmCNt5ARYJaUDwrNgE03kHrjgFRRisxvAnhx09KEm9DCBLMoqQHEYUKrVyBGAgAOw==

  • 별도 이미지 파일이 필요 없고, 문자열 자체가 이미지이기 때문에 브라우저에서 이미지와 동일하게 렌더된다.
  • 브라우저가 이미지를 렌더할 때, 네트워크가 좋지 않은 경우 잘 로딩되지 않는 문제도 존대한다.
  • 이미지 파일과 비교시 용량이 증가하는 단점도 존재하며, 소스코드에 위 문자열처럼 긴 길이의 base64 코드로 인코딩되기 때문에 소스의 가독성이 떨어질 수 있다.
  • 더불어 base64 인코딩 이미지를 많이 사용하는 경우 문자 자체를 로딩하는데 오히려 많은 시간이 걸려서 더 느리다는 느낌이 들 수도 있다.

https://www.clien.net/service/board/cm_app/16078399