Fast Refresh
Fast Refresh는 리액트 네이티브의 기능으로, 리액트 컴포넌트의 변경 사항을 거의 즉각적으로 확인할 수 있게 해준다. Fast Refresh는 기본적으로 활성화되어 있으며, 리액트 네이티브 개발자 메뉴에서 "Fast Refresh 활성화"를 토글할 수 있다. Fast Refresh를 활성화하면 대부분의 수정 사항이 1~2초 내에 반영된다.
동작 원리
-
React 컴포넌트만 내보내는 모듈을 수정하면, Fast Refresh는 해당 모듈의 코드만 업데이트하고 컴포넌트를 리렌더링한다. 파일 내의 스타일, 렌더링 로직, 이벤트 핸들러, 혹은 효과(effects) 등 모든 부분을 수정할 수 있다.
-
React 컴포넌트가 아닌 다른 것을 내보내는 모듈을 수정하면, Fast Refresh는 해당 모듈과 이를 임포트하는 다른 모듈도 함께 다시 실행한다. 예를 들어,
Button.js
와Modal.js
가 모두Theme.js
를 임포트하는 경우,Theme.js
를 수정하면 두 컴포넌트 모두 업데이트된다. -
마지막으로, React 트리 외부의 모듈에서 임포트하는 파일을 수정하면, Fast Refresh는 전체 페이지를 새로고침하는 방식으로 동작한다. React 컴포넌트를 렌더링하는 파일이지만, 동시에 React가 아닌 컴포넌트에서 임포트하는 값을 내보내는 경우가 여기에 해당한다. 예를 들어, 컴포넌트가 상수를 내보내고, 이를 React가 아닌 유틸리티 모듈에서 임포트하는 경우가 있다. 이런 경우에는 상수를 별도의 파일로 분리한 뒤, 두 파일에서 모두 임포트하는 방식으로 해결할 수 있다. 이렇게 하면 Fast Refresh가 다시 작동한다. 다른 경우도 대부분 비슷한 방식으로 해결할 수 있다.
오류 복구 기능
Fast Refresh 세션 중에 구문 오류가 발생하면, 오류를 수정하고 파일을 다시 저장하면 된다. 이때 빨간 오류 창이 사라진다. 구문 오류가 있는 모듈은 실행되지 않으므로 앱을 다시 로드할 필요가 없다.
모듈 초기화 과정에서 런타임 오류가 발생한 경우(예: StyleSheet.create
대신 Style.create
를 입력한 경우), 오류를 수정하면 Fast Refresh 세션이 계속된다. 빨간 오류 창이 사라지고, 모듈이 업데이트된다.
컴포넌트 내부에서 런타임 오류가 발생한 경우에도, 오류를 수정하면 Fast Refresh 세션이 계속된다. 이때 React는 업데이트된 코드를 사용해 애플리케이션을 다시 마운트한다.
앱에 에러 바운더리가 있다면(프로덕션 환경에서 우아한 실패 처리를 위해 권장), 다음 수정 후에 렌더링을 다시 시도한다. 이 경우 에러 바운더리가 있으면 루트 앱 화면으로 이동하는 상황을 방지할 수 있다. 다만, 에러 바운더리를 지나치게 세분화하지 않도록 주의해야 한다. React는 프로덕션 환경에서 에러 바운더리를 사용하며, 항상 의도적으로 설계해야 한다.
제한 사항
Fast Refresh는 편집 중인 컴포넌트의 로컬 React 상태를 안전한 경우에 한해 유지하려고 한다. 하지만 파일을 수정할 때마다 로컬 상태가 초기화되는 몇 가지 이유가 있다:
- 클래스 컴포넌트의 경우 로컬 상태가 유지되지 않는다. (함수 컴포넌트와 훅만 상태를 유지한다.)
- 편집 중인 모듈이 React 컴포넌트 외에 다른 export를 포함할 수 있다.
- 때로는 모듈이
createNavigationContainer(MyScreen)
과 같은 고차 컴포넌트 호출 결과를 export할 수 있다. 반환된 컴포넌트가 클래스라면 상태가 초기화된다.
장기적으로, 코드베이스의 더 많은 부분이 함수 컴포넌트와 훅으로 전환되면 더 많은 경우에 상태가 유지될 것으로 기대할 수 있다.
팁
- Fast Refresh는 기본적으로 함수형 컴포넌트(그리고 훅)의 React 로컬 상태를 유지한다.
- 때로는 상태를 강제로 초기화하고 컴포넌트를 다시 마운트하고 싶을 수 있다. 예를 들어, 마운트 시에만 발생하는 애니메이션을 조정할 때 유용할 수 있다. 이를 위해 편집 중인 파일 어디든
// @refresh reset
을 추가하면 된다. 이 지시문은 해당 파일에만 적용되며, Fast Refresh가 파일 내 정의된 컴포넌트를 매번 편집할 때마다 다시 마운트하도록 지시한다.
Fast Refresh와 훅
가능한 경우, Fast Refresh는 컴포넌트의 상태를 편집 과정에서 유지하려고 시도한다. 특히, useState
와 useRef
는 인자나 훅 호출 순서를 변경하지 않는 한 이전 값을 그대로 유지한다.
useEffect
, useMemo
, useCallback
과 같이 의존성을 가진 훅은 Fast Refresh 중에 항상 업데이트된다. Fast Refresh가 진행되는 동안 의존성 목록은 무시된다.
예를 들어, useMemo(() => x * 2, [x])
를 useMemo(() => x * 10, [x])
로 편집하면, x
(의존성)가 변경되지 않았더라도 다시 실행된다. React가 이렇게 하지 않는다면, 편집 내용이 화면에 반영되지 않을 것이다!
때로는 이로 인해 예상치 못한 결과가 발생할 수 있다. 예를 들어, 의존성 배열이 비어 있는 useEffect
조차도 Fast Refresh 중에 한 번 다시 실행된다. 그러나 useEffect
가 가끔 다시 실행되더라도 코드가 견고하게 작성되는 것은 Fast Refresh 없이도 좋은 습관이다. 이렇게 하면 나중에 새로운 의존성을 추가하기가 더 쉬워진다.