Next.js + Jest + SVGR 환경 설정
현재 상황
우선 프로젝트의 환경 설정에서 2가지를 도입했다.
- Next.js
- Jest
모꼬지 사이드 프로젝트 진행을 위해 프로젝트 설정 후 이제 막 로그인 페이지를 개발하는 중이었다.
로그인 페이지에는 입력한 비밀번호를 확인하기 위한 비밀번호 표시 버튼이 존재한다. 작은 SVG로 되어있다.
SVG를 적용했을 때부터 문제가 생겼고 이 후 테스트를 했을 때는 구글 여기저기를 찾아보며 고생을 했다.
- Next.js에서 SVG를 Import 할 때 생기는 문제
- Jest를 사용할 때 SVG를 Import하면 테스트가 제대로 이루어지지않는 문제
Next.js에서 SVG 사용하기
https://react-svgr.com/docs/next/
나는 SVG를 사용하기 위해 SVGR이라는 라이브러리를 사용했다.
Img로 넣는 방법도 있었고 svg를 URL로 넣는 방법도 있었지만 특정 상황에 따라 svg의 fill을 사용하여 색상을 변경하고싶었다. 그러면 동일한 형태의 색상만 다른 아이콘을 두 번 호출하지 않아도 되기 때문에 억지로 사용을 해보려 했다.
여러 블로그를 확인하다 찾은 내용이라 공식 문서와 조금 다르다. 어떤 부분이 왜 다른지는 확인을 해봐야겠다.
Install
npm i -D @svgr/webpack
next.config.mjs
compiler 부분은 styled components 사용을 위한 코드다.
/** @type {import('next').NextConfig} */
const nextConfig = {
compiler: {
styledComponents: true,
},
webpack: (config) => {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
});
return config;
},
};
export default nextConfig;
page.tsx
SVG를 그대로 가져와 컴포넌트 형태로 사용하고 색상 등 옵션을 변경할 수 있어 편하다.
import Link from "next/link";
import EyeSVG from "./svgs/eye.svg";
export default function Home() {
return (
<div>
<h1>Home</h1>
<Link href="/login">login</Link>
<EyeSVG fill="#000" />
</div>
);
}
SVGR과 Jest 사용하기
https://react-svgr.com/docs/jest/
친절하게 공식 문서로 작성되어있다. 하지만 Configure 부분에서 잘못 설정하여 디버깅 시간이 길어졌다. 뭐든지 정확하게 알아보고 해야겠다.
__mocks__/svg.js
이 부분은 공식 문서와 다르게 아래와 같이 설정하는 것이 좋은 것 같다.
공식 문서와 동일하게 작성하면 SvgrURL Warning이 나타난다.
export const ReactComponent = "div";
const SvgUrl = () => "svgrurl";
export default SvgUrl;
jest.config.ts
나를 가장 힘들게 한 파일이다.
공식 문서에서는 module.exports로 나와 있는데 그 하위에 있는 moduleNameMapper를 아래 파일의 config에 넣으면 될 거라는 생각으로 작성했었다. 그게 그 위치가 맞는지 확인도 하지 않고 내 감으로 진행한 거다.
https://github.com/vercel/next.js/discussions/58948
여기저기 뒤져보니 위 링크 최하단에 누군가 아주 친절하게 자신의 모든 파일을 작성해 줬다. 덕분에 나는 에러를 해결했고 드디어 Jest를 사용해 볼 수 있었다.
import type { Config } from "jest";
import nextJest from "next/jest.js";
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: "./"
});
// Add any custom config to be passed to Jest
const config: Config = {
coverageProvider: "v8",
testEnvironment: "jsdom"
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
};
const jestConfigWithOverrides = async () => {
const configFn = createJestConfig(config);
const res = await configFn();
res.moduleNameMapper = {
// We cannot depend on the exact key used by Next.js
// so we inject an SVG key higher up on the mapping tree
"\\.svg": "<rootDir>/__mocks__/svg.js",
...res.moduleNameMapper
};
return res;
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default jestConfigWithOverrides;