front-end/Nextjs

[Next/SVGR] NextJS에서 SVGR 다루기

hojung 2022. 9. 17.
728x90
반응형

1. SVGR이란 

svgr이란 svg 이미지를 react에서 쉽게 다루기 위해서 만들어진 webpack 설정이자 babel 설정이다. SVGR을 이용하면 SVG파일을 react에서 컴포넌트화 하여서 사용할 수 있다. 

 

Svg 파일은 png,jpg, jpeg파일들과 다르게 크기와 상관없이 일정한 화질을 유지하며 무한한 확장 축소가 가능하고 색상과 테두리 선의 두께, 색상과 같은 속성들도 그 때 그 때 변경이 가능하다. 

 

사실 svg 이미지는 xml이라는 마크업 언어로 쓰여진 language의 일종이기 때문에 완벽한 이미지라고 보는 것에는 무리가 있다. 

 

나는 내가 프로젝트를 진행하면서 이 svg이미지를 어떻게 다루었는 지를 기록할 것이다. 

 

우선 나는 NextJS에서 SVGR을 사용하기 위해 @svgr/webpack 을 설치해 주었다. 

webpack 설정을 추가해 주어야하는 이유는 이 웹팩이 코드를 build할 때 svg파일을 자동으로 리액트 컴포넌트화 해주기 때문이다. 

yarn add -D @svgr/webpack

그 후 nextJS의 webpack 설정은 next.config.js파일에서 진행하기 때문에 next.config.js파일을 수정해 주어야한다. 

 

webpack: (config) => {
		config.module.rules.push({
			test: /\.svg$/,
			use: ['@svgr/webpack'],
		});
		return config;
	},

webpack을 조금 공부하다보니 test와 use의 뜻에 알게 되었는데 test에 들어가는 식의 형식은 정규 표현식으로 .svg라는 확장자를 가지고 있다면 use에 들어가는 설정으로 build를 하라는 뜻이었다. 그러니 위의 코드의 의미는 .svg파일은 @svgr/webpack이라는 설정으로 빌드해! 라는 뜻이다. 

 

2. Next에서 SVGR사용하기 

이제 NextJS에서 svg파일을 리액트 컴포넌트화하여 사용해볼 것이다. 우선 기존 svg파일을 import해오려면

img태그 안에 넣거나 따로 <svg />태그를 포함한 리액트 컴포넌트를 정의해준 후 사용했어야 했다. 하지만 이제는 

import NotificationIco from '@/assets/images/Home/notification_on.svg';

다음과 같이 import를 해오면 모듈로써, 리액트 컴포넌트로써 svg이미지를 사용할 수 있게 된다. 

사용할 때도 정의한 이름을 

return (
		<S.HomeHeaderContainer isVisible={isVisible}>
			<span>{isVisible && <OasisLogo />}</span>
			<S.HomeIcons>
				<SearchIco stroke={isVisible ? colors.grey[9] : colors.white} />
				<NotificationIco
					stroke={isVisible ? colors.grey[9] : colors.white}
					fill={hasNotify ? colors.primary.sky : 'transparent'}
				/>
			</S.HomeIcons>
		</S.HomeHeaderContainer>
	);

다음과 같이 <NotificationIco />   로 tsx 문법을 사용하면 import가 된다..! 이렇게 이미지가 사용하기 쉬워지다니 정말 신세계이다. 

 

3. Svg 이미지 control

근데 위의 용례를 살펴보니 <Notification /> 안에 fill 과 stroke라는 attribute가 존재한다. 다음 속성은 무엇을 하려고 들어가 있는 것일까?

 

영어 단어로만 살펴보면 fill은 채우다. stroke는 공학에서 왕복 운동 기관에서 피스톤이 기통 속을 오르내리는 동작 및 그 거리를 의미한다. 그러나 svg파일에서는 테두리 선이라고 이해하면 된다. 

 

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1536_25564)">
<path d="M6.44784 7.96942C6.76219 5.14032 9.15349 3 12 3V3C14.8465 3 17.2378 5.14032 17.5522 7.96942L17.804 10.2356C17.8072 10.2645 17.8088 10.279 17.8104 10.2933C17.9394 11.4169 18.3051 12.5005 18.8836 13.4725C18.8909 13.4849 18.8984 13.4973 18.9133 13.5222L19.4914 14.4856C20.0159 15.3599 20.2782 15.797 20.2216 16.1559C20.1839 16.3946 20.061 16.6117 19.8757 16.7668C19.5971 17 19.0873 17 18.0678 17H5.93223C4.91268 17 4.40291 17 4.12434 16.7668C3.93897 16.6117 3.81609 16.3946 3.77841 16.1559C3.72179 15.797 3.98407 15.3599 4.50862 14.4856L5.08665 13.5222C5.10161 13.4973 5.10909 13.4849 5.11644 13.4725C5.69488 12.5005 6.06064 11.4169 6.18959 10.2933C6.19123 10.279 6.19283 10.2645 6.19604 10.2356L6.44784 7.96942Z" stroke="current" stroke-width="2" fill="transparent"/>
<path d="M8 17C8 17.5253 8.10346 18.0454 8.30448 18.5307C8.5055 19.016 8.80014 19.457 9.17157 19.8284C9.54301 20.1999 9.98396 20.4945 10.4693 20.6955C10.9546 20.8965 11.4747 21 12 21C12.5253 21 13.0454 20.8965 13.5307 20.6955C14.016 20.4945 14.457 20.1999 14.8284 19.8284C15.1999 19.457 15.4945 19.016 15.6955 18.5307C15.8965 18.0454 16 17.5253 16 17" stroke="current" stroke-width="2" stroke-linecap="round" fill="transparent"/>
<circle cx="22" cy="2" r="2" fill="current" stroke="transparent"/>
</g>
<defs>
<clipPath id="clip0_1536_25564">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

svg파일의 code이다. html과 비슷한 태그로 이루어져있지만 xml이라는 마크업 언어의 일종이다. 보다면 태그 들안에 여러 attribute들이 존재하는 것을 확인할 수 있다. 

그 중 눈에 띄는 것은 fill 과 stroke이다.  svg파일은 앞서도 말했듯이 png, jpeg, jpg파일들의 이미지와는 다르게 무한한 확장이 가능하다. (화질이 깨지지 않는다.) 왜냐하면 이는 이미지 그 자체가 아니라 픽셀 값들을 이용한 벡터 이미지이기 떄문에 가능한 것이다. 그렇다면 다른 동작들도 가능하지 않을까? 맞다. 

 

fill 속성을 이용해서 svg 외부에서 이미지의 색상을 변경하는 것이 가능하고 stroke 속성을 이용해서 외부에서 테두리 색상을 변경하는 것 또한 가능하다. 또한 svg파일 내부를 직접 건드린다면 stroke의 두께 위치 viewbox의 크기 등 많은 것을 통제할 수 있지만 나는 svg파일 외부에서 어떻게 svg파일을 다루는 지 기록하겠다. 

 

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1536_25564)">
<path d="M6.44784 7.96942C6.76219 5.14032 9.15349 3 12 3V3C14.8465 3 17.2378 5.14032 17.5522 7.96942L17.804 10.2356C17.8072 10.2645 17.8088 10.279 17.8104 10.2933C17.9394 11.4169 18.3051 12.5005 18.8836 13.4725C18.8909 13.4849 18.8984 13.4973 18.9133 13.5222L19.4914 14.4856C20.0159 15.3599 20.2782 15.797 20.2216 16.1559C20.1839 16.3946 20.061 16.6117 19.8757 16.7668C19.5971 17 19.0873 17 18.0678 17H5.93223C4.91268 17 4.40291 17 4.12434 16.7668C3.93897 16.6117 3.81609 16.3946 3.77841 16.1559C3.72179 15.797 3.98407 15.3599 4.50862 14.4856L5.08665 13.5222C5.10161 13.4973 5.10909 13.4849 5.11644 13.4725C5.69488 12.5005 6.06064 11.4169 6.18959 10.2933C6.19123 10.279 6.19283 10.2645 6.19604 10.2356L6.44784 7.96942Z" stroke="current" stroke-width="2" fill="transparent"/>
<path d="M8 17C8 17.5253 8.10346 18.0454 8.30448 18.5307C8.5055 19.016 8.80014 19.457 9.17157 19.8284C9.54301 20.1999 9.98396 20.4945 10.4693 20.6955C10.9546 20.8965 11.4747 21 12 21C12.5253 21 13.0454 20.8965 13.5307 20.6955C14.016 20.4945 14.457 20.1999 14.8284 19.8284C15.1999 19.457 15.4945 19.016 15.6955 18.5307C15.8965 18.0454 16 17.5253 16 17" stroke="current" stroke-width="2" stroke-linecap="round" fill="transparent"/>
<circle cx="22" cy="2" r="2" fill="current" stroke="transparent"/>
</g>
<defs>
<clipPath id="clip0_1536_25564">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

다시 한 번 svg파일의 코드를 살펴보겠다. 위를 보면 <path />안에 fill은 fill="transparent" 로 고정이 되어 있지만 (투명하다는 뜻이다. ) <circle />안의 fill속성은 current로 되어있다. 이것은 무엇을 의미할까? 이 svg파일을 사용하는 곳에서 지정해준 색상을 사용하겠다는 뜻이다.!

 

실제로 사용하는 곳을 보면 SVGR형태로 svg이미지를 import해온 뒤 fill속성을 지정해주는 것을 확인할 수 있다. 

 

<NotificationIco
					stroke={isVisible ? colors.grey[9] : colors.white}
					fill={hasNotify ? colors.primary.sky : 'transparent'}
				/>

물론 stroke속성도 존재하기에 테두리의 색상 또한 변경이 가능하다. 나는 알림이 있다면 svg파일 내부에 존재하는 <circle /> 부분의 색상만 변경하고 싶었기 때문에 다른  <path />들의 색상을 transparent로 고정한 뒤 사용하는 곳에서 fill prop을 넘겨주었다. 

 

그러면 다음과 같이 hasNotify state에 의해 svg 이미지 색상이 변경된다. 밑은 결과이다. 

 

1. hasNotify = true

 

2. hasNotify = false

이렇게 이미지조차 코드가 되는 세상이 왔다. 하나의 이미지로도 prop을 넘겨 여러가지를 표현하는 것이 가능하다. 

728x90
반응형

댓글