본문 바로가기
Web/Front

모노레포에서 ui 패키지를 사용하면서 발생한 이슈 해결 과정

by 김첨지 2023. 8. 15.

 

모노레포인 레포지토리에 새로운 서비스를 추가하고, ui 패키지에서 컴포넌트를 불러오는데 다음과 같은 에러가 발생했다.

Module parse failed: The keyword 'interface' is reserved (4:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

 
구글링 결과 타입스크립트의 interface를 해석하지 못하는 것으로 파악했다. 
 
하지만 다른 서비스에서는 정상 작동하는데, 왜 새 서비스에서는 에러를 뿜는지 이해할 수 없었다.
 
디펜던시도 똑같이 맞춰보았지만 해결되지 않았다.
 
그리고 마지막으로 next.comfig.js 코드를 똑같이 맞춰보기로 했다.
 

 

시도해 본 것들

1. next 다운 그레이드

 
// 기존 next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  swcMinify: true,
  compiler: {
    styledComponents: true,
  },
};

module.exports = nextConfig;

 
// 새 next.config.js

// eslint-disable-next-line @typescript-eslint/no-var-requires
const withTM = require("next-transpile-modules")(["@monorepo/ui", "@monorepo/hooks"]);

/** @type {import('next').NextConfig} */
const nextConfig = {
  swcMinify: true,
  compiler: {
    styledComponents: true,
  },
  experimental: {
    appDir: true,
  },
};

module.exports = withTM(nextConfig);

 

Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error /Users/jha/react-project/chooz-jurumarble/client/.pnp.cjs:19895 Error.captureStackTrace(firstError); ^ Error: Your application tried to access next-transpile-modules, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.

위 에러는 next-transpile-modules 디펜던시를 추가하여 해결하였다.
 

TypeError: config.watchOptions.ignored.filter is not a function or its return value is not iterable at Object.webpack (/Users/jha/react-project/chooz-jurumarble/client/.yarn/cache/next-transpile-modules-npm-10.0.0-35632e5048-3300fc7081.zip/node_modules/next-transpile-modules/src/next-transpile-modules.js:265:42)

위 에러는 구글링해도 잘 나오지 않았다.
 
일단 기존 서비스와 모든 게 같고, next 버전이 달라서 13.4.12 버전에서 13.1.6 버전으로 다운그레이드했다.
 

Error : You tried to import `next/font/local`, did you mean `@next/font/local`? Read more: https://nextjs.org/docs/basic-features/font-optimization
모듈 'next/font/local'에 대한 선언 파일을 찾을 수 없습니다. '/Users/jha/react-project/chooz-jurumarble/client/.yarn/__virtual__/next-virtual-2b50e05bed/0/cache/next-npm-13.1.6-4d04ae3ad7-584977e382.zip/node_modules/next/font/local/index.js'에는 암시적으로 'any' 형식이 포함됩니다. 'next' 패키지가 실제로 이 모듈을 노출하는 경우 'declare module next/font/local';'이(가) 포함된 새 선언(.d.ts) 파일을 추가해 보세요.

 
그러자 이번엔 next를 인식하지 못했다.
 

 

2. ts-loader 추가 

이 방법으로는 안 되겠다 싶어 새로운 방법을 생각했다. 
 
타입스크립트를 인식하지 못하고, 로더가 필요하다고 하였으니 ts-loader를 추가해 보기로 했다.

yarn add ts-loader

 
그리고 next.config.js 설정을 다음과 같이 바꿔주었다.

/** @type {import('next').NextConfig} */
const nextConfig = {
  swcMinify: true,
  compiler: {
    styledComponents: true,
  },
  webpack: (config) => {
    config.module.rules.push({
      test: /\.ts(x?)$/,
      use: [
        {
          loader: "ts-loader",
          options: {
            transpileOnly: true,
          },
        },
      ],
    });
    return config;
  },
};

module.exports = nextConfig;

 
 

TypeError: Cannot read properties of undefined (reading 'ink')

이번엔 ui 패키지에서 사용하던 theme을 인식할 수 없는 에러가 발생했다.
 
새 워크 스페이스에서만 styled-components ^6.0.7 버전을 사용하고 있었는데, 이것을 ^5.3.6로 통일시켰다.
 
^6.0.7을 사용할지, ^5.3.6으로 사용할지 고민이 됐었지만, 메이저 6 버전 이후로 styled를 객체 분해하여 import 해야 하는 부분이 수정 사항이 너무 많아져 일단 5 버전을 사용하기로 결정했다.
 

Module not found: styled-components tried to access react-is (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound.

react-is도 추가해 주었다.
 

TypeError: Cannot read properties of undefined (reading 'ink')

 
그런데 또 같은 에러가 발생했다.
 
이번엔 package.json에 style-loader을 추가해 주었다.

  "dependencies": {
    "@monorepo/hooks": "workspace:*",
    "@monorepo/ui": "workspace:*",
    "next": "^13.4.12",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-is": "^18.2.0",
    "style-loader": "^3.3.2",
    "styled-components": "^5.3.6",
    "styled-reset": "^4.5.1",
    "ts-loader": "^9.4.4"
  },

 
 

Module parse failed: Unexpected token (20:12) File was processed with these loaders: * ../../.yarn/__virtual__/ts-loader-virtual-1830e7a262/0/cache/ts-loader-npm-9.4.4-f7a7993559-8e5e6b839b.zip/node_modules/ts-loader/index.js You may need an additional loader to handle the result of these loaders.

 

같은 에러가 번갈아가면서 뜨고 있다.

 


8.23 진행 사항


새 워크스페이스를 생성하면서 새 워크스페이스에 최신 버전의 의존성들을 추가했었다.

 

그런데 이것이 기존의 의존성들과 충돌을 일으키는 것 같다.

새 워크스페이스를 추가하기 직전 커밋으로 돌아가 피쳐 브랜치를 따고 다시 초기 세팅을 진행했다.

기존 작업 사항을 붙여 넣고, package.json에서 디펜던시 버전을 타 워크 스페이스와 일치시켰다.

그리고 위에서 style-loader과 css-loader을 새 워크스페이스(next 13.4.12 버전)에 넣었는데 오히려 이것이 에러를 발생시켰다. (next/font/local을 인식할 수 없었다.)

듣기로는 styled-loader과 css loader를 넥스트 13부터 지원해 줘서 사용할 필요가 없다고 한다.

(그런데 다른 워크스페이스에서 next 13.1.6 버전을 사용 중인데, 이곳에서는 에러 없이 잘 작동하고 있다.)
 

 

타 워크스페이스의 컴포넌트 사용 시 해당 컴포넌트에 styled components의 theme을 사용하고 있다면, import 하는 워크스페이스에서 해당 theme을 themProvider에 전달해줘야 한다는 사실을 알았다.

 

ui 패키지에서 사용하고 있는 theme를 전달해 주자 다음과 같은 에러가 나타났다.

 

'DefaultTheme' 형식은 'ThemeArgument' 형식에 할당할 수 없습니다.ts(2322)

styled-components의 메이저 버전이 달라지면서 타입이 달라진 것 같다.

 

해당 워크스페이스의 버전을 ^5.3.6으로 일치시켜 해결하였다.

 

 

Unhandled Runtime Error Error: It seems you are interpolating a keyframe declaration (cJoqxJ) into an untagged string. This was supported in styled-components v3, but is not longer supported in v4 as keyframes are now injected on-demand. Please wrap your string in the css\`\` helper which ensures the styles are injected correctly. See https://www.styled-components.com/docs/api#css

 

 

9.12 해결

It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles to not render properly, errors during the rehydration process, a missing theme prop, and makes your application bigger without good reason.

콘솔 창에서인가? 이전에 위와 같은 에러 메시지가 나타났었다. 

 

해석하자면 스타일 컴포넌트가 동시에 여러 개 있다는 뜻인데, 이것이 원인이 되어 theme를 인식하지 못하는 게 분명했다.

 

우측이 ui 패키지이고, 좌측이 그것을 사용하는 서비스다.

서비스에서 ui 패키지를 dependency로 사용하는데, styled-components가 양 측에서 dependency로 들어가 있다.

 

dependency는 빌듯이 포함되는데, 위와 같은 경우 양 측의 styled-components가 포함될 수 있다고 생각했다.

 

이에 따라 ui 패키지의 styled-components를 devDependencise에 추가해 주었다. 

 

결과는 똑같았다.

하지만 이전과는 확실히 다르다.

 

https://localhost:3000 환경은 빌드의 결과물이 아니고, devDependencise의 영향을 받는다.

 

빌드 후 배포 환경에서 보는 서비스는 에러 없이 정상 동작할 것이다.

 

하지만 이와 같은 상황에서 개발을 이어나갈 수는 없다.

 

ui 패키지에 peerDependencies를 추가해 주었다.

 

peerDependencies의 경우, 새로 의존성을 추가하는 것이 아니라 사용하는 곳의 dependency를 따른다.

 

<ThemeProvider theme={{ ...ATheme, ...Btheme }}>

그리고 서비스의 ThemeProvider에 두 theme을 넣어주었다.

 

에러 없이 정상 작동하였다.

 

ui 패키지가 import 되는 곳의 styled-components를 따르기 시작하고, 서비스에서 하나의 styled-components를 가질 수 있게 되었다. 

 

 

마치면서

그동안 얕게 알고 있었던 peerDependency에 대해서 확실히 알게 되었다.

추후 개발할 라이브러리에도 많은 도움이 될 것 같다.

 

 

 

Referecne

 
https://minemanemo.tistory.com/168