티스토리 뷰
CRA에선 어떻게 이미지를 처리하는가?
10KB미만의 이미지 파일은 data URI의 형태로 변환되어 html에 포함된다. url-loader가 이미지 파일을 만나면 data URI 형태로 변경해주기 때문에 가능한것이다. 이렇게 하면 http 요청수를 줄일 수 있고, bmp, gif, jpg, jpeg, png에만 적용되고 svg는 제외된다. 물론 10KB라는 수치도 변경이 가능하다고 한다.
data URI란 간단히 말하면 작은 크기의 파일을 문서내에 인라인으로 포함하기 위해서 사용된다. 아이콘을 base64로 인코딩하여 data URI형태로 문서에 인라인 하는 방식을 많이 사용한다.
SVG는 왜 제외 됬는가?
이슈 내용을 살펴보면 CRA가 버전 0.8로 업데이트 되면서 url-loader를 사용하여 10KB 미만의 이미지를 data uri형태로 처리하게 변경되었는데, 그것 때문에 원래 잘 쓰고 있던 본인의 svg sprite system이 망가졌다는 이슈이다.
이 사람이 원래 쓰고 있던 svg sprite system은 이렇게 동작한다. 한 폴더에 모여있는 SVG파일들이 빌드 후 10KB미만의 SVG 스프라이트 파일(sprite.svg)로 합쳐진다. 이 스프라이트에서 fragment identifiers를 통해 일부 아이콘만 가져와서 리액트 컴포넌트로 만들어서 사용중이었다고 한다. 이렇게 svg sprite를 이용할 경우 브라우저 캐시를 이용할 수 있어서 큰 장점이 있다.
import React, { PropTypes } from 'react'
import svgSprite from '../img/symbol/sprite.svg'
function Icon({ name }) {
return (
<svg>
<use xlinkHref={`${svgSprite}#${name}`} />
</svg>
)
}
그런데, CRA가 10KB 미만의 svg의 fragment도 url-loader로 처리하여 base64로 인코딩되는 바람에, 아이콘을 제대로 불러오지 못하는 이슈가 발생한것이다. 그래서 SVG 스프라이트의 파일을 10KB 이상으로 잡아서 url-loader를 안거치는 방법 말고 다른 방법이 있는지가 질문 내용이다.
svg fragment란 <svg>...</svg> 부분을 의미한다. 하나의 svg 단위라고 생각하면 된다.
어쨌든, 이런 이슈 때문에 SVG는 url-loader가 처리하지 않게끔 변경되었다고한다. 대신에 아래처럼 svg를 리액트 컴포넌트로 변경해주는 기능을 넣어줬다.
import { ReactComponent as Logo } from './logo.svg';
function App() {
return (
<div>
{/* Logo is an actual React component */}
<Logo />
</div>
);
}
아이콘 관리 방식 : 전통 vs 리액트
전통적인 멀티페이지 애플리케이션에서는 아이콘을 관리할때 PNG 스프라이트 이미지 형태로 관리했다. 이렇게 하면 서버로 가는 요청수를 줄일수도 있고, 브라우저 캐시를 이용해서 한번 받아온 파일을 중복해서 불러오지 않는 장점도 있었다. 이렇게 아이콘을 관리하는 이유는, 멀티페이지 앱에서는 기본적으로 페이지를 이동할때마다 모든 파일들을 새로 받아오기 때문이다.
하지만, 싱글페이지 애플리케이션에서는 아이콘을 굳이 스프라이트 이미지로 관리하지 않아도 될 것 같다. 왜냐면, svg를 리액트 컴포넌트로 만들어서 페이지에 렌더링하면 svg가 그대로 페이지에 포함된다. 그 말은, svg에 의해 html파일이 약간 커지긴 하지만, 스프라이트 이미지를 위한 http 요청을 추가로 하지 않아도 된다는 뜻이다. 또한 PNG로 제어하는것보다 아이콘을 변형하기 훨씬 쉬우며 독립적으로 관리하기도 쉽다. 리액트로 아이콘을 다루기 위해서는 PNG 스프라이트 방식보다 SVG로 독립적으로 관리하는게 더 좋은 것 같다는 의견이다. 실제로 위 이슈에서도 봤듯이, CRA는 url loader를 사용해서 10KB 미만의 이미지 파일을 base64로 인코딩한다. 이것 자체가 크기가 작은 이미지에 대해서는 그냥 페이지에 인라인 시키는게 더 이득이라고 생각했기 때문이 아닐까?
출처
https://create-react-app.dev/docs/adding-images-fonts-and-files/
'React' 카테고리의 다른 글
스토리북에서 Component Story Format (CSF) 란? (0) | 2020.03.25 |
---|---|
Partial Hydration - 리액트에서 웹페이지 성능 최적화 하기 (0) | 2020.03.20 |
리액트의 hydration이란? (4) | 2020.03.20 |
리액트의 동적 Context API 사용해보기 (0) | 2020.03.16 |
왜 리액트는 대세가 되었을까? (0) | 2020.03.15 |
- Total
- Today
- Yesterday
- Polyfill
- storybook
- es6
- useRef
- Next.js
- hydrate
- server side rendering
- design system
- promise
- atomic design
- async
- type alias
- rendering scope
- reducer
- Babel
- react hooks
- typescript
- computed
- webpack
- javascript
- props
- useEffect
- Action
- react
- state
- mobx
- await
- reflow
- reactdom
- return type
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |