본문 바로가기
WIKI 기술 지식 베이스

React 18로 마이그레이션

원문 보기 위키 갱신

React 18로 마이그레이션 (Migrating to React 18)

info

출처: 문서

본문

info

이 가이드에는 이제 폐기된 React 16에 대한 지원을 제거하는 단계가 포함되도록 업데이트되었습니다.

Backstage 핵심 라이브러리와 플러그인은 v17부터 v18까지 모든 React 버전과 호환됩니다. 즉 프로젝트를 원하는 속도로 마이그레이션할 수 있습니다. 다만 진화하는 생태계를 따라가기 위해서도, React 18이 특히 테스트에서 성능 개선을 가져오기 때문에도, 가능한 한 빨리 마이그레이션할 것을 권장합니다.

마이그레이션 (Migration)

시작하기 전에, 대규모 프로젝트의 경우 점진적 마이그레이션으로 분해하기 어렵기 때문에 까다로운 마이그레이션이 될 수 있다는 점을 알려드립니다. 실제로 이 마이그레이션의 어려운 부분은 테스트용 @testing-library/react 패키지의 새 버전으로 전환하는 것입니다. React 주요 버전 간에 겹치는 지원이 없기 때문입니다. 자세한 내용은 나중에 다룹니다.

React 18로 업그레이드 (Upgrading to React 18)

Backstage 인스턴스 (Backstage Instance)

Backstage 인스턴스를 React 18로 마이그레이션하려면 다음 단계를 따르세요.

  • 루트 package.json의 resolutions 섹션을 수정해 @types/react와 @types/react-dom의 최신 버전을 참조하세요.

package.json

"resolutions": {    "@types/react": "^17",    "@types/react-dom": "^17",    "@types/react": "^18",    "@types/react-dom": "^18",  },
  • packages/app/package.json의 react 및 react-dom 의존성을 업데이트하세요.

packages/app/package.json

"dependencies": {    ...    "react": "^17.0.2",    "react-dom": "^17.0.2",    "react": "^18.0.2",    "react-dom": "^18.0.2",    ...  },
  • 렌더링에 react-dom/client API를 사용하도록 packages/app/src/index.tsx를 조정하세요.

packages/app/src/index.tsx

import '@backstage/cli/asset-types';import ReactDOM from 'react-dom';import ReactDOM from 'react-dom/client';import App from './App';ReactDOM.render(<App />, document.getElementById('root'));ReactDOM.createRoot(document.getElementById('root')!).render(<App />);

Backstage 프런트엔드 플러그인 (Backstage Frontend Plugin)

  • 플러그인의 package.json에서 react, react-dom, @types/react에 대한 devDependencies와 peerDependencies를 업데이트하세요.

plugins//package.json

"devDependencies": {    ...    "@types/react": "^16.13.1 || ^17.0.0",    "react": "^16.13.1 || ^17.0.0",    "react-dom": "^16.13.1 || ^17.0.0",    "@types/react": "^17.0.0 || ^18.0.0",    "react": "^17.0.0 || ^18.0.0",    "react-dom": "^17.0.0 || ^18.0.0",    ...  },

plugins//package.json

"peerDependencies": {    ...    "@types/react": "^16.13.1 || ^17.0.0",    "react": "^16.13.1 || ^17.0.0",    "react-dom": "^16.13.1 || ^17.0.0",    "@types/react": "^17.0.0 || ^18.0.0",    "react": "^17.0.0 || ^18.0.0",    "react-dom": "^17.0.0 || ^18.0.0",    ...  },

이 업데이트를 완료하면 애플리케이션과 플러그인이 이전처럼 작동해야 하며, 이제 React 18을 활용합니다.

note

package.json 파일을 수정한 후에는 잠금 파일을 업데이트해야 합니다.

TypeScript 오류 (TypeScript Errors)

React 18로 업그레이드할 때 상당히 많은 TypeScript 타입 오류가 보일 가능성이 높습니다. 파괴적 변경 요약은 이를 도입한 Pull Request에서 확인할 수 있습니다. 마이그레이션을 돕기 위한 codemod도 제공됩니다.

손상 정도를 평가하려면 yarn tsc:full을 실행하세요.

좋은 소식은 이러한 오류를 React 17에 머무른 채로도 수정할 수 있다는 것입니다. 수정할 오류가 많다면 한 번에 원하는 만큼 적거나 많게 처리하고, 1단계의 버전 업그레이드 없이 이를 메인 브랜치에 병합할 수 있습니다. 이를 통해 프로젝트의 타입을 아직 완전히 React 18로 전환하지 않고도 점진적으로 마이그레이션할 수 있습니다. 모든 타입 파손이 해결되면 테스트 마이그레이션의 다음 단계로 진행할 수 있습니다.

테스트 마이그레이션 (Migrating Tests)

이 시점에서 앱이 작동하고 타입 오류가 없기를 바라지만, 테스트를 실행하면 많은 테스트가 실패하는 것을 볼 수 있습니다. 현재 버전의 @testing-library/react 패키지가 React 18을 지원하지 않기 때문입니다. 불행히도 우리가 옮겨 갈 새 버전은 React 17을 지원하지 않으므로, 한 번에 모두 해야 합니다.

info

한 번에 전체 프로젝트를 마이그레이션하는 것이 불가능하다면, 나중에 마이그레이션할 개별 플러그인에 react 및 react-dom v17용 devDependencies를 추가해 볼 수 있습니다. 이것은 우리가 실제로 시도해 본 것은 아니므로, 시도한다면 커뮤니티 Discord에서 알려주시고 어떻게 되었는지 알려주세요.

의존성 업그레이드 (Dependency Upgrades)

테스트가 다시 작동하도록 하려면 @testing-library/react를 최소 v13으로 업데이트해야 하지만, 추가 파괴적 변경의 영향이 낮으므로 최소한 모두 v14로 올리는 것이 합리적입니다. v13의 변경 사항에 대한 자세한 내용은 릴리스 노트를 참조하세요.

@testing-library/react를 올리는 것 외에도 @testing-library/react-hooks 패키지를 제거해야 합니다. 이제 @testing-library/react 자체에 포함되기 때문입니다. 이 변경에 대한 자세한 내용은 @testing-library/react-hooks README.md에서 확인할 수 있습니다.

package.json 파일을 업데이트할 때 다음 찾기-바꾸기 RegEx 패턴이 도움이 될 수 있습니다.

찾기: "@testing-library/react": ".*"

바꾸기: "@testing-library/react": "^14.0.0"

찾기: "@testing-library/react-hooks": ".*",?

바꾸기: <nothing>

테스트 업데이트 (Test Updates)

새 버전의 의존성을 설치하고 나면 이것은 꽤 기계적인 테스트 업데이트 과정이 됩니다. 선호하는 방법을 사용하세요. 모든 테스트를 한 번 실행해 파손을 찾은 다음 한 파일씩 집중하는 것이 꽤 매끄러웠습니다.

Backstage 프로젝트의 테스트를 업데이트할 때 다음 패턴이 유용하다는 것을 알았습니다.

  • 기존 act(...) 호출 중 많은 것을 제거할 수 있습니다. waitFor, .findBy*, @testing-library/user-event 같은 대부분의 테스트 유틸리티에 내장되어 있습니다.
  • 요소가 나타날 때까지 기다리려면 .findBy*를 사용하세요.
  • 다른 예상 상태 변경이나 여러 요소를 기다리려면 waitFor(...)를 사용하세요.
  • 사용자 상호작용에는 @testing-library/user-event를 사용하세요.
  • renderHook API는 여러 가지 면에서 변경되었습니다.
    • 더 이상 waitForValueToChange나 waitForNextUpdate를 반환하지 않습니다. 대신 waitFor를 사용하고 싶을 것입니다.
    • 이제 오류를 결과의 일부로 반환하는 대신 던집니다.
    • 더 이상 initialProps를 wrapper에 전달하지 않습니다. 이에 대한 해결 방법이 문서에 제공되어 있습니다.
    • 구성 요소가 mock 함수를 호출할 때까지 기다렸다가 렌더 상태가 업데이트되었는지 기대하는 것은 더 이상 신뢰할 수 없습니다.
    • 렌더링된 구성 요소는 종종 사용자 입력에 즉시 업데이트되지 않습니다. 예상 상태에 도달할 때까지 waitFor 또는 다른 유틸리티를 사용해야 하는 것이 더 일반적입니다.

Backstage 프로젝트 자체를 React 18로 마이그레이션한 이 PR의 테스트 변경 사항도 참조할 수 있습니다.

행운을 빕니다! 질문이 있다면 커뮤니티 Discord에 참여하세요. 이 문서가 개선될 수 있다고 생각하면 이슈를 열거나 풀 리퀘스트를 제출하는 것을 환영합니다.

더 알아보기 (Learn more)