- 지난번에 읽었던 글(클로저로 동작하여 메모리 정리 되지 않는 문제가 발생할 수 있다는 내용)
- 메모이제이션 하기 위해 컨텍스트를 통째로 기억하고 있는데 이때 클로저 형태로 참조하고 있어 정리 할 수 없기 때문이다
The general problem is that different **useCallback** hooks in a single component might reference each other and other expensive data through the closure scopes. The closures are then held in memory until the **useCallback** hooks are recreated. Having more than one **useCallback** hook in a component makes it super hard to reason about what's being held in memory and when it's being released. The more callbacks you have, the more likely it is that you'll encounter this issue.
- 이에 대한 해결책으로 작게 쪼개고 차라리 메모이제이션 하지 않는 방법이 있다
To avoid these memory leaks, keep your closure scopes as small as possible, avoid memoization when it's not necessary, and possibly fall back to **useRef** for large objects.
- 무분별한 메모이제이션을 하다보면 앱이 들고 있는 메모리가 커지기 때문에 문제가 된다고 생각해왔다
- 맞는 내용이지만 위에서 예시로 보여준 것처럼 컨텍스트가 컨텍스트를 부르는 무한 증분을 하고 있다면?
- 단순 로직을 개선하는 것이 아니라 지금 어디서 무한증분을 하고 있는지 찾아내야한다
- (후속 글에서
이것은 대체로 함수형 자바스크립트의 근본적인 ‘문제’이지 리액트의 문제는 아닙니다. 다만 리액트는 클로저와 메모이제이션을 많이 사용하기 때문에 이 문제가 발생할 가능성이 훨씬 더 높습니다.
라고 리액트만의 문제가 아님을 다시 짚어주었다)
- 이제 새로 나올 리액트 컴파일러는 이러한 메모이제이션을 대신 해주겠다고 어필하고 있다
- 미래의 슈퍼 리액트 컴파일러도 아직은 완벽하지 않다
한 가지 확실한 것은 컴파일러가 클로저로 인한 메모리 누수로부터 여러분을 구해주지 못한다는 것입니다. 제 생각에 이것은 자바스크립트와 함수형 프로그래밍 패러다임의 근본적인 문제입니다. 자바스크립트(적어도 V8)의 클로저는 세분화된 메모리 최적화를 위해 설계되지 않았습니다. 컴포넌트를 빠르게 마운트/언마운트하거나 적은 양의 데이터를 처리하는 경우에는 괜찮지만, 데이터 종속성이 크고 수명이 긴 컴포넌트가 있는 경우에는 문제가 될 수 있습니다.
- 작고 순수한 컴포넌트와 컨텍스트 분리된 커스텀 훅을 작성하고
- 가장 문제가 크다고 보여지는 메모리는 프로파일러 사용하여 확인해야한다는 것이다
리액트 애플리케이션을 처음 작성할 때 이러한 네트워크 요청은 보통 리액트 앱이 마운트된 후에 시작됩니다. 이 접근 방식은 효과가 있긴 하지만, 애플리케이션이 확장됨에 따라 비효율적일 수 있습니다. 앱 번들이 다운로드, 파싱되고 리액트 앱이 로드될 때까지 기다려서 네트워크 요청을 시작할 필요가 있을까요? 이런 과정과 네트워크 요청을 병렬로 실행할 수도 있는데 말이죠.
프리로딩 스크립트에 과도하게 의존성을 추가하지 않도록 주의하세요. 그렇지 않으면 스크립트가 너무 커져서 다운로드 및 파싱이 비효율적일 수 있습니다.
- RN 번들을 읽을때 미리 호출할 수 있다면?
- 이미 실행중인 프로미스를 취소 할 수 없기 때문에 발생하는 사건
- 이때 실행중인 프로미스가 점유하는 메모리는 또 다시 해제 되지 않는다
- 아직 실행중이기 때문이다 🙈
- 위에서 이미지 검색 시나리오를 예제로 이미 요청된 것을 취소할 수 없는 문제를 이야기 했는데
- AbortController 를 이용해 커스텀 훅으로 abort 하고 재요청을 한다면 이전에 요청되었던 것은 취소할 수 있다
- 서버 요청은 진행되겠지만 앱 네트워크 요청은 취소된 것이다
- 그렇다면 다른 내용으로 요청하거나 페이지 이동 등으로 필요없어진 경우 언마운트, 해제가 아니라 요청을 취소하는 것을 우선시한다면 어떻게 될까?