문제 상황


<aside> 💡 파일 경로 지정 참고 내용 (참고 링크)

JSX 엘리먼트 속성의 루트 폴더 기준은 public 폴더므로 이미지 파일이 src 폴더에 있다면 파일 최상단에서 이미지 파일을 import한 후 인라인 스타일 url() 함수에 사용할 수 있다. *.png *.webp 같은 이미지 파일은 아래 방법으로 잘 작동한다.

// src/assets/image 폴더에 있는 profile-image.png 파일 import
import ArrowDown from '../assets/image/arrow-down.png'

// 컴포넌트 리턴문
<select style={{ backgroundImage: `url(${ArrowDown})` }} className="bg-no-repeat bg-right pr-4" >...</select>

하지만 위와 동일한 방법으로 *.svg 파일에 적용해보면 이미지가 안나온다

해결 방법


  1. svg 파일을 Data URI에서 사용할 수 있는 문자열로 변환
  2. CSS 파일에 커스텀 클래스를 만들고 url() 함수에 svg 파일 경로 명시 (SSR / SSG에선 안될수도 있음)

방법 1 — Data URI 사용

<aside> 💡 이미지 파일을 base64 URI로 바꿔주는 url-loader 같은 라이브러리도 있음

</aside>

svg 파일을 Data URI에서 사용할 수 있는 문자열로 변환하면 CSS url() 함수에 사용할 수 있다. url() 함수 인자엔 이미지 파일의 상대 / 절대 경로, 웹 리소스 주소 혹은 data URL / blob URL을 추가할 수 있다.

import ArrowDown from '../assets/image/arrow-down.svg'
import { renderToStaticMarkup } from "react-dom/server";

// 컴포넌트 본문
// svg 파일을 Data URI에서 사용할 수 있는 문자열로 변환
const svgString = encodeURIComponent(renderToStaticMarkup(<ArrowDown />));

// 컴포넌트 리턴문
<select style={{ backgroundImage: `url("data:image/svg+xml,${svgString}")` }} >...</select>

Percent Encoding

URI에서 문법적 의미를 갖는 문자를 예약 문자라고 한다. 예를들어 URI에서 & 앰퍼샌드는 AND 의미를 갖는다. 만약 쿼리스트링(?key=value) value 값에 & 같은 예약 문자를 문법적 의미가 아닌 문자 그대로 사용하려면 인코딩(이스케이프)이 필요하다.