Seung Hun

devtool을 devDependencies가 아닌 dependencies에 설치하는 이유

프론트엔드 개발을 하면서 라이브러리에서 공식적으로 지원하는 devtool을 사용해 본 경험이 많이 있습니다.

라이브러리들의 예시를 확인해 볼까요?

이 라이브러리는 tanstack query입니다. devtool임에도 불구하고 dependencies에 설치 해주는 모습이네요. 다른 라이브러리도 확인해 볼까요?

이 라이브러리는 jotai devtool입니다. 위에 tanstack query와 마찬가지 dependencies에 설치하는 모습이네요.

devDependencies에 설치하고 테스트

이 devtool을 devDependencies에 설치하고 테스트를 해보겠습니다.

우선 react router framework mode를 세팅하겠습니다.

import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; const queryClient = new QueryClient(); export function Layout({ children }: { children: React.ReactNode }) { return ( <QueryClientProvider client={queryClient}> <html lang="en"> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <Meta /> <Links /> </head> <body> {children} <ScrollRestoration /> <Scripts /> </body> <ReactQueryDevtools initialIsOpen={false} /> </html> </QueryClientProvider> ); }

Dev 서버 테스트

간단하게 세팅 후 dev서버를 실행시켜 확인해 보면

아주 잘 실행되는 모습입니다.

Build 테스트

지금까지만 보면 별 문제가 없습니다. 이제 빌드를 해보겠습니다.

빌드도 잘 되네요!

빌드 결과물은 production mode에서 실행이 가능해야하기 때문에 node_modules를 지워주고

pnpm i -P

실행을 시켜보면

이런 에러를 볼 수 있습니다.

원인 분석

사실 원인은 간단합니다. devDependenciespnpm i -P로 설치가 되지 않고

//root.tsx export function Layout({ children }: { children: React.ReactNode }) { return ( <QueryClientProvider client={queryClient}> <html lang="en"> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <Meta /> <Links /> </head> <body> {children} <ScrollRestoration /> <Scripts /> </body> <ReactQueryDevtools initialIsOpen={false} /> </html> </QueryClientProvider> ); }

런타임에서 참조가 있기 때문이죠. 런타임에서 코드를 실행시킬 때 참조가 없기 때문에 에러가 발생합니다.

devDependencies에 설치하고 안전하게 사용하는 방법.

이제 devtool을 devDependencies에 설치하고 안전하게 사용하는 방법에 대해서 알아보겠습니다.

const ReactQueryDevtools = lazy(() => import("@tanstack/react-query-devtools").then((module) => ({ default: module.ReactQueryDevtools, })) ); const queryClient = new QueryClient(); export function Layout({ children }: { children: React.ReactNode }) { return ( <QueryClientProvider client={queryClient}> <html lang="en"> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <Meta /> <Links /> </head> <body> {children} <ScrollRestoration /> <Scripts /> </body> {import.meta.env.DEV && <ReactQueryDevtools initialIsOpen={false} />} </html> </QueryClientProvider> ); }

이런식으로 런타임에 참조를 없애버리면 문제가 발생하지 않습니다.