문제상황
회사 프로젝트를 진행하며 한 페이지에서 하나의 svg icon을 여러 번 호출하는 경우가 많이 있었다.
평소에는 잘 보이던 이미지가 해상도마다 다른 컴포넌트를 보여주기 위해 media query를 이용해서 display: none 설정을 해주는 부분에서 svg가 정상적으로 표출되지 않는 문제가 발생하였다.
See the Pen Untitled by 유지영 (@hagfyiyi-the-sans) on CodePen.
예시로 작성한 코드처럼 동일한 svg 파일로 fisrt, second, third를 만들어주고 first에만 해상도에 따라 display: none 을 설정해주었는데 second, third의 svg 파일도 깨지는 것을 확인할 수 있다. 실제 프로젝트에서는 svg 파일이 아예 표출되지 않았었다.
해결 방법 탐색
테스트로 작성한 예시에서는 스타일이 간단하였지만 실제로 적용된 프로젝트된 스타일이 많았어서 영향을 주는 스타일 속성이 있는지를 먼저 확인했다.
1. svg에 영향을 주는 스타일이 있는지 확인하기
- width, height가 확보되지 않아 이미지가 정상 표출되지 않는 것인지
- z-index의 영향을 받는 요소가 있는지
- svg 태그의 fill, background-color 등이 설정되어 있는지
- ...
이 외의 영향 받을 만한 스타일을 찾아보았지만 마땅히 영향을 받는 요소가 없었다.
2. svg 태그 호환이 불안정한지 확인하기
프로젝트에서는 일러스트 아이콘을 사용하고 있었기 때문에 일반적인 아이콘와 달리 image 태그, use xorm, xlink:href 속성 등이 사용되고 있었다.
여기서 xlink:href의 경우 deprecated 되어서 react 자체에서 xlinkHref 로 호환되어 사용할 수 있었다. 현재 설정도 xlinkHref로 되어 있었는데 여기에서 경로를 제대로 인식하지 못하는 것인가 의심하여 전체 공통으로 호환되는 href 속성으로 변경해보았으나 문제는 동일하게 발생하였다.
3. 모바일, 태블릿, 데스크탑을 별도 컴포넌트로 관리하면서 발생한 문제인지 확인하기
프로젝트에서는 데스크탑, 태블릿, 모바일에서 표출할 컴포넌트를 각각 생성하여 media query와 display: none으로 관리하고 있었다. 현재 발생한 문제의 맹점은 해상도 별로 표출되는 컴포넌트가 달라질 때 svg가 특정 컴포넌트에서만 정상 표출된다는 점이다.(동일한 공통 컴포넌트로 관리하고 있음에도 불구하고!)
그래서 테스트를 위해 기존에 해상도 별로 걸려있던 display: none 을 제거하였더니 모든 svg 이미지가 정상 표출되었다!
→ display: none 이 svg 파일에 영향을 주고 있다는 사실을 발견!
하지만 각각 다른 컴포넌트로 호출하고 있었는데 어떻게 영향을 받을 수 있는지 의문이었다. 그래서 svg, display: none 을 키워드로 구글링을 하였더니 유사한 문제를 겪은 글들을 발견할 수 있었다.
SVG 내부 ID를 유니크하게 관리하자
문제는 svg 파일 내부에 있었다. svg 파일 내부에는 스타일 설정 등을 위해 id 속성이 설정된 경우가 있는데 이 값은 svg를 피그마 등에서 가져온 경우 고정 문자열 값을 가지고 있다.
그런데 한 페이지에서 동일한 svg 파일을 여러 번 호출하면서 해당하는 svg 들이 모두 동일한 고정 값 id를 가지고 있어서 자바스크립트에서 id로 해당 요소를 조작할 때 해당하는 컴포넌트 내부의 svg 뿐만 아니라 페이지 안에 있는 모든 svg 파일이 선택되게 된 것이다.
따라서 svg 파일 내부에 있는 id를 유니크하게 관리할 수 있도록 방법을 변경하여 해결하였다.
const IconDefault = () => {
const patternId = useId();
const svgId = useId();
return (
<svg
width="20"
height="14"
...
>
<rect width="20" height="14" fill={`url(#${patternId})`} />
<defs>
<pattern
id={patternId}
>
<use
xlinkHref={`#${svgId}`}
/>
</pattern>
<image
id={svgId}
width="640"
height="480"
...
/>
</defs>
</svg>
);
예시 코드에서도 svg 내부에서 사용하는 id를 호출할 때마다 고유한 값으로 호출되도록 설정하였을 때 아래처럼 정상적인 이미지가 표출되는 것을 확인할 수 있다.
배운 점
id를 중복되지 않게 고유하게 관리해야한다는 것은 당연한 사실이었는데 미처 svg 내부 id 값을 관리하는 건 생각도 못했던 것 같다. 항상 피그마에서 바로 가져와서 사용하다보니 내부에서 어떤 속성이 사용되고 어떻게 영향을 줄 수 있을지 고려하지 못했다.
이번 기회를 통해 동일한 상황이 발생하면 더 빠르게 해결 할 수 있을 것 같다!
참고 자료
https://stackoverflow.com/questions/49531434/hidding-svg-affects-other-svg-styles-in-the-same-page
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/id
'개발 공부 > JavaScript' 카테고리의 다른 글
[자바스크립트 딥 다이브] 타입변환과 단축평가 (0) | 2022.12.02 |
---|---|
single vertical bar ('|') (0) | 2022.10.10 |
JavaScript 이론 정리 #4 [구조 분해 할당, 나머지 매개 변수, 전개구문] (2) | 2022.08.27 |
JavaScript 이론 정리 #3 [배열 메소드] (0) | 2022.08.17 |
JavaScript 이론 정리 #2 [number 메소드, Math 메소드, string 메소드] (0) | 2022.08.16 |