Docs
Fast Refresh

Fast Refresh

Fast Refresh는 Next.js에 통합된 React 기능으로, 파일을 저장할 때 브라우저 페이지를 라이브 리로드하면서 클라이언트 측 상태를 유지합니다. Next.js 9.4 이상 버전에서는 기본적으로 활성화되어 있으며, Fast Refresh가 활성화된 경우 대부분의 수정 사항은 1초 이내에 표시됩니다.

작동 방식

  • React 컴포넌트만 내보내는 파일을 편집하는 경우, Fast Refresh는 해당 파일의 코드만 업데이트하고 컴포넌트를 다시 렌더링합니다. 스타일, 렌더링 로직, 이벤트 핸들러 또는 이펙트를 포함하여 파일의 모든 내용을 편집할 수 있습니다.
  • React 컴포넌트가 아닌 내보내기가 있는 파일을 편집하는 경우, Fast Refresh는 해당 파일과 이를 가져오는 다른 파일을 다시 실행합니다. 예를 들어, Button.jsModal.jstheme.js를 가져오는 경우, theme.js를 편집하면 두 컴포넌트가 업데이트됩니다.
  • React 트리 외부에서 파일을 가져오는 경우 파일을 편집하면, Fast Refresh는 전체 리로드로 대체됩니다. 예를 들어, React 컴포넌트를 렌더링하지만 값도 내보내고 이를 비 React 유틸리티 파일이 가져오는 경우가 있습니다. 이 경우, 상수를 별도의 파일로 이동하고 두 파일 모두에서 가져오도록 고려해보세요. 이렇게 하면 Fast Refresh가 다시 작동합니다. 다른 경우도 유사한 방식으로 해결할 수 있습니다.

오류 복구

구문 오류

개발 중에 구문 오류가 발생하면 파일을 다시 저장하여 수정할 수 있습니다. 오류는 자동으로 사라지므로 앱을 리로드할 필요가 없습니다. 컴포넌트 상태는 유지됩니다.

런타임 오류

컴포넌트 내부에서 런타임 오류가 발생하면 컨텍스트 오버레이가 표시됩니다. 오류를 수정하면 오버레이가 자동으로 해제되며, 앱을 리로드할 필요가 없습니다.

오류가 렌더링 중에 발생하지 않았다면 컴포넌트 상태가 유지됩니다. 오류가 렌더링 중에 발생한 경우, React는 업데이트된 코드를 사용하여 애플리케이션을 다시 마운트합니다.

앱에 에러 경계 (opens in a new tab)가 있는 경우(프로덕션에서 우아한 실패를 위해 권장됨), 렌더링 오류 후 다음 수정 시 렌더링을 다시 시도합니다. 이는 에러 경계가 루트 앱 상태로 항상 리셋되는 것을 방지할 수 있습니다. 그러나 에러 경계가 너무 세분화되지 않도록 주의하세요. 이는 React가 프로덕션에서 사용하므로 항상 의도적으로 설계되어야 합니다.

제한 사항

Fast Refresh는 편집 중인 컴포넌트의 로컬 React 상태를 유지하려고 하지만, 안전한 경우에만 가능합니다. 파일을 편집할 때마다 로컬 상태가 재설정되는 몇 가지 이유는 다음과 같습니다:

  • 로컬 상태는 클래스 컴포넌트에 대해 유지되지 않습니다(함수 컴포넌트와 Hooks만 상태를 유지합니다).
  • 편집 중인 파일에 React 컴포넌트 외에 다른 내보내기가 있을 수 있습니다.
  • 때때로 파일은 HOC(WrappedComponent)와 같은 고차 컴포넌트를 호출한 결과를 내보냅니다. 반환된 컴포넌트가 클래스인 경우, 상태가 재설정됩니다.
  • export default () => <div />;와 같은 익명 화살표 함수는 Fast Refresh가 로컬 컴포넌트 상태를 유지하지 않도록 합니다. 큰 코드베이스의 경우 name-default-component codemod를 사용할 수 있습니다.

함수 컴포넌트와 Hooks로 코드를 점점 더 많이 이동함에 따라 더 많은 경우에 상태가 유지될 것으로 기대할 수 있습니다.

  • Fast Refresh는 기본적으로 함수 컴포넌트(및 Hooks)에서 React 로컬 상태를 유지합니다.
  • 때로는 상태를 강제로 리셋하고 컴포넌트를 다시 마운트하고 싶을 수 있습니다. 예를 들어, 마운트 시에만 발생하는 애니메이션을 조정할 때 유용할 수 있습니다. 이를 위해 편집 중인 파일 어디에나 // @refresh reset을 추가할 수 있습니다. 이 지시는 파일에 로컬이며, Fast Refresh에 해당 파일에 정의된 컴포넌트를 매번 편집할 때 다시 마운트하도록 지시합니다.
  • 개발 중에 편집하는 컴포넌트에 console.log 또는 debugger;를 넣을 수 있습니다.
  • 가져오기(import)는 대소문자를 구분한다는 점을 기억하세요. 가져오기가 실제 파일 이름과 일치하지 않으면 Fast 및 전체 리프레시가 실패할 수 있습니다. 예를 들어, './header''./Header'는 다릅니다.

Fast Refresh와 Hooks

가능한 경우, Fast Refresh는 편집 간에 컴포넌트의 상태를 유지하려고 합니다. 특히, useStateuseRef는 인수나 Hook 호출 순서를 변경하지 않는 한 이전 값을 유지합니다.

종속성이 있는 Hooks(useEffect, useMemo, useCallback)는 Fast Refresh 중에 항상 업데이트됩니다. Fast Refresh가 발생하는 동안 종속성 목록은 무시됩니다.

예를 들어, useMemo(() => x * 2, [x])useMemo(() => x * 10, [x])로 편집하면 x(종속성)가 변경되지 않았더라도 다시 실행됩니다. React가 그렇게 하지 않으면 편집 내용이 화면에 반영되지 않습니다!

때로는 이러한 동작이 예상치 못한 결과를 초래할 수 있습니다. 예를 들어, 종속성 배열이 빈 useEffect도 Fast Refresh 중에 한 번 다시 실행됩니다.

그러나 Fast Refresh가 없더라도 useEffect가 때때로 다시 실행되는 코드 작성은 좋은 연습입니다. 나중에 새로운 종속성을 도입하기 쉽게 만들고, React Strict Mode에 의해 강제되므로 이를 활성화하는 것이 좋습니다.