이슈 발생
Storybook에서 SVG 아이콘을 사용하는 컴포넌트로 스토리를 만들고 있었는데요.
갑자기 위와 같은 오류가 발생했습니다.
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
구글링도 해보고, Github Issue를 여러 개 살펴본 뒤에 file-loader 관련 이슈라는 것을 알게 되었습니다.
Storybook은 Webpack을 사용하고 있고 기본적으로 file-loader가 사용되고 있는데, SVG 파일을 import하는 과정에서 file-loader가 객체 형태로 변환한 것으로 보입니다.
File-loader란?
file-loader는 특정 모듈을 출력(Output) 디렉토리로 복사(Emit)해주는 로더입니다.
Webpack에서 사용하는 로더란?
SVG 파일은 import 아이콘_컴포넌트 from '아이콘.svg'
형태로 컴포넌트에서 사용되고 있는데요.
Webpack이 SVG 파일을 해석(resolve)할 때, file-loader가 이 파일을 객체 형태로 변환한 것입니다.
원하는 동작은 SVG 파일을 리액트 컴포넌트로 변환하는 것입니다.
에러 해결하기 - Webpack module 설정을 변경
Webpack 설정에는 module이라는 항목이 존재합니다.
여기에서 모듈 유형에 따라 어떤 작업을 할 것 인지 (어떤 로더를 사용할 것 인지) 설정해줄 수 있습니다.
@svgr/webpack
은 SVG 파일을 import 할 때, 리액트 컴포넌트로 변환해줍니다.
Storybook에 적용된 Webpack의 모듈 설정을 아래와 같이 변경해주면 됩니다.
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/nextjs';
const config: StorybookConfig = {
stories: ['../components/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-a11y'
],
framework: {
name: '@storybook/nextjs',
options: {},
},
docs: {
autodocs: 'tag',
},
// webpackFinal을 통해 Webpack 설정을 변경
webpackFinal: async (config) => {
if (!config.module || !config.module.rules) {
return config;
}
config.module.rules = [
...config.module.rules.map((rule) => {
if (!rule || rule === '...') {
return rule;
}
if (rule.test && /svg/.test(String(rule.test))) {
return { ...rule, exclude: /\.svg$/i };
}
return rule;
}),
{
test: /\.svg$/,
use: ['@svgr/webpack']
}
]
return config;
}
};
export default config;
module의 rules 배열을 순회하면서 rule.test가 svg를 포함하고 있으면, 해당 rule의 exclude에 /\.svg$/i
를 적용합니다.
즉, file-loader가 svg 모듈을 무시하도록 합니다.
그 후에 svg 모듈을 @svgr/webpack
이 처리하도록 새로운 rule을 넣어줍니다.
이슈 해결 완료
Storybook을 다시 실행시키면 정상적으로 SVG 파일을 컴포넌트 안에 불러올 수 있습니다.
참고
'개발이슈' 카테고리의 다른 글
[Jest] Web Storage 테스트하기 (LocalStorage, SessionStorage) (0) | 2023.08.05 |
---|---|
[Jest] 테스트 작성 시, window.alert 모킹하기 (jest.fn, jest.spyOn) (0) | 2023.08.05 |
[GitLab] The pipeline failed due to the user not being verified 이슈 해결 (0) | 2023.03.09 |
[Next.js] Component selectors can only be used in conjunction 이슈 (0) | 2022.08.07 |
[Next.js] Jest + Cypress 환경에서 Cypress 제공함수의 타이핑 & 자동완성이 안되는 경우 (0) | 2022.04.29 |