본문 바로가기

공부/트러블 슈팅

[트러블 슈팅] SVG 컴포넌트 재사용 시 발생한 이미지 중복 문제 해결하기

반응형

발생한 오류 🔥

날씨 API를 요청한 후 아이콘 URL을 가져와 `WeatherIcon`컴포넌트를 사용해 여러 개의 날씨 아이콘을 표시하려고 했습니다. 그러나 배열로 `WeatherIcon`을 렌더링 했을 때, 모든 아이콘이 동일한 이미지만 표시되는 현상이 발생했습니다.

같은 이미지

 

해결 과정 🔎

처음에는 각 아이콘의 URL을 제대로 전달하고 있다고 생각했지만, 여러 개의 `WeatherIcon`컴포넌트를 렌더링할 때 브라우저가 첫 번째 요소의 이미지만을 참조하는 것을 깨닫지 못했습니다.

 

기존 코드

const WeatherIcon = ({ url, className }) => {
  const URL = url
  ? `https://openweathermap.org/img/wn/${url}@2x.png`
  : "data:image/png;base64,iVBORw0KG.....";

  return (
    <svg
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      xmlnsXlink="http://www.w3.org/1999/xlink"
      className={className}
    >

      <rect width="24" height="24" fill="url(#pattern0_18_178)" />
      <defs>
        <pattern
          id="pattern0_18_178"
          patternContentUnits="objectBoundingBox"
          width="1"
          height="1"
        >
          <use xlinkHref="#image0_18_178" transform="scale(0.01)" />
        </pattern>
        <image id="image0_18_178" width="100" height="100" xlinkHref={URL} />
      </defs>
    </svg>
  );
};

 

이렇게 작성했을 때 동일한 `id`가 여러 번 사용되어 브라우저가 첫 번째 값만 참조하는 문제가 있었습니다.

 

해결 방법 ✨

고유한 `id`를 생성해 각 `WeatherIcon`인스턴스에 대한 다른 `id`를 부여하는 방식으로 문제를 해결했습니다.

 

수정 코드

const uniqueId = Math.random().toString(36).substr(2, 9);

  return (
    <svg
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className={className}
    >
      <rect width="24" height="24" fill={`url(#pattern${uniqueId})`} />
      <defs>
        <pattern
          id={`pattern${uniqueId}`}
          patternContentUnits="objectBoundingBox"
          width="1"
          height="1"
        >
          <use xlinkHref={`#image${uniqueId}`} transform="scale(0.01)" />
        </pattern>
        <image id={`image${uniqueId}`} width="100" height="100" xlinkHref={URL} />
      </defs>
    </svg>
  );

 

각 인스턴스에 고유한 `id`를 부여해 브라우저가 각 아이콘을 올바르게 참조하도록 했습니다.

성공!!!

 

어려웠던 점 ❓

이 문제를 해결하는데 몇 시간이 걸렸습니다. 초기에는 API에서 가져온 URI이 잘못된 것이라 생각했지만, 결국 SVG 내부의 `id`충돌이 문제라는 것을 깨닫는데 시간이 많이 걸렸습니다. 

 

특히 SVG와 관련된 문제는 일반적인 DOM요소와 다르게 동작하기 때문에 더 혼란스러웠던 것 같습니다.

 

깨달은 점 ❕

이번 경험을 통해 SVG를 사용할 때 `id`속성이 얼마나 중요한지 깨닫게 되었습니다.

 

동일한 `id`를 가진 요소가 여러 개 존재할 경우, 브라우저가 첫 번째 요소만 참조하는 점을 명확하게 인지하고 앞으로 SVG를 사용할 때 고유한`id`를 부여해 이런 문제를 예방해야겠다고 생각했습니다.

 

또한, 복잡한 UI를 구성할 때, 재사용 가능한 컴포넌트를 설계 하는 것이 얼마나 중요한지를 다시 한번 깨닫게 되었습니다.

반응형