최근에 서비스 홍보를 위한 온보딩 페이지를 개발하면서, 디자이너가 만들어주신 이미지들을 많이 페이지에 추가할 일이 있었다.
이 과정에서 SVG 이미지 화질 깨짐 문제가 있었는데, 해결 과정을 공유하려한다.
React.js, JavaScript, Tailwindcss 환경에서 진행함
문제
SVG 이미지를 사용하던 중, 특히 모바일 크롬 브라우저에서만 뿌옇게 이미지 화질이 떨어지는 문제를 발견했다.
원래 SVG 파일의 장점이 고품질 벡터 그래픽이기에 SVG로 추가한 것인데, PC 브라우저에서는 깨지지 않게 보이고 모바일로 확인했을 때 깨지는 현상이 나타났다.
기존 코드
<img
src="~~~.svg"
className="w-[375px] md:hidden"
alt="~~~"
/>
해결 과정
문제의 해결책을 찾으면서, SVG를 처리하는 방식을 변경하는게 화질 깨짐 현상을 해결할 수 있음을 알게되었다.
<img> 태그 대신에 <object>
수정된 코드
<object
data="~~~.svg"
type="image/svg+xml"
className="w-[375px] md:hidden"
>
<img src="~~~.svg" alt="~~~" className="w-[375px]" />
</object>
변경한 부분은 다음과 같다
- <img> 태그를 <object> 태그로 대체
- src 속성 대신에 data 속성 사용
- type="image/svg+xml" 속성 추가
- 폴백으로 원래의 <img> 태그를 <object> 태그 내부에 포함시키기
폴백(Fallback)이 있다면 다양한 환경에서 일관된 경험을 주는데 도움이 될 수 있다.
SVG 파일이 손상되었다면 폴백 이미지가 대신 표시되고, SVG 파일이 큰 경우 로딩이 오래걸리는데 이 때 폴백 이미지가 먼저 표시된다고 한다.
object 태그는 SVG 를 벡터 그래픽으로 직접 렌더링하여서 원본의 품질을 유지할 수 있기에 해결이 된 것 같다.
img 태그로 SVG 렌더링을 하는 것과 object 태그로 SVG 렌더링을 하는 것에 무슨 차이가 있을까?
img 태그는 래스터화 과정을 거친다.
대부분의 브라우저에서 img 태그로 SVG 를 불러오면, SVG를 일정 해상도의 비트맵 이미지로 변환(래스터화)한다.
이 과정에서 원본 SVG가 손실될 수 있다.
하지만 object 태그는 SVG 를 벡터 형식 그대로 렌더링한다.
따라서 벡터 그래픽이기 때문에 어떤 크기로 확대되어도 선명도가 유지된다.
결론적으로, 고품질의 SVG 렌더링이 필요한 경우 object 태그를 사용하는 것이 적합할 수 있다.
inline 속성을 가지는 object 태그
object 태그를 사용하면서 신경써야할 부분이 있다.
object 태그는 기본적으로 inline 속성을 가진다.
inline 속성을 가지는 요소는 텍스트 기준선에 맞춰 정렬되기 때문에 img 태그를 그대로 대체하려고 하면 레이아웃 문제를 일으킬 수 있다.
따라서 object 태그에 display: block 을 적용하여 img 태그와 유사하게 만들 수 있을 것이다.
결론
이러한 과정으로 SVG 이미지의 화질 문제를 해결할 수 있었다.
같은 문제를 겪는 분들이 있다면 이 방법이 도움이 되길 바란다.