TIL 46일차 Section2 HA 2차 AjaxCallCount 🙃

shleecloud·2021년 9월 30일
0

Codestates

목록 보기
46/95
post-custom-banner

✍️ 들어가며

테스트가 끝났다. 하루가 지난 지금 결과는 합격이지만 시험 과정이 마냥 쉽지만은 않아서 제일 까다로웠던 부분을 적어두고자 한다. 이 부분 때문에 어제는 너무 어이없고 화가났지만 하루가 지난 지금 곰곰히 생각해보니 그럴 수도 있다고 납득이 된다. 오늘은 백신을 맞고 컨디션이 애매해서 간단하게 쓴다.

🛎 AjaxCallCount

Nock 모듈을 이용해서 테스트 코드에서 서버 통신을 유사하게 구현할 수 있다.
scope.interceptors[0].interceptionCounter; 이 테스팅 코드로 몇 번 호출했는지 확인하는 구문이 있었다. Nock(HTTP server mocking and expectations library for Node.js)

테스트 케이스에서 <App /> 컴포넌트를 부르면서 카운터가 계속 올라가게 되고 카운터가 누적되어 결국 실패가 뜨는게 핵심이었다.

🕳 Try1: React useEffect 랜더링 조건

처음엔 useEffect 랜더링 조건을 봤다. useEffect 두번째 인자로 빈 배열을 할당하면 페이지가 처음 랜더링 될 때 실행하게 된다. 근데 결국 컴포넌트가 호출되면서 랜더링이 일어나고 fetch()가 실행되더라. 결국 실패. 이렇게 쉽게 해결됐으면 내가 글도 안썼지.

🛁 Try2: React useEffect Clean-up

테스트 통과가 안되는 와중에 경고메세지도 떴다. 요약하면 컴포넌트가 언마운트 된 상태에서 비동기 작업이 끝나 상태를 할당하니 불필요한 메모리 사용이 발생한다는 뜻이다.

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in %s.%s a useEffect cleanup function

정리(clean-up)를 이용하는 Effects

위에서 정리(clean-up)가 필요하지 않은 side effect를 보았지만, 정리(clean-up)가 필요한 effect도 있습니다. 외부 데이터에 구독(subscription)을 설정해야 하는 경우를 생각해보겠습니다. 이런 경우에 메모리 누수가 발생하지 않도록 정리(clean-up)하는 것은 매우 중요합니다. class와 Hook을 사용하는 두 경우를 비교해보겠습니다.

return문으로 콜백함수와 상태변수를 추가하면 경고메세지가 사라진다. 하지만 여전히 테스트는 통과가 안된다.
팁: Effect를 건너뛰어 성능 최적화하기

    // ! SuccessCase - Cleanup 함수로 메모리누수 방지
    // ? 참조URL https://ko.reactjs.org/docs/hooks-effect.html#effects-with-cleanup
export const App = () => {
  useEffect(() => {
    let isComponentMounted = true;
    movieData.then(res => {
      if (isComponentMounted) setMovies(res);
    });
    return () => {
      isComponentMounted = false;
    };
  }, []);

🗺 Try3: Fetch문의 위치

해답은 Fetch를 할당하는 위치에 있었다. App 컴포넌트 안에 두면 결국 재랜더링 과정에서 fetch() 비동기 함수가 실행된다. 그렇다면 App 밖에 비동기 작업이 있다면 어떨까? 이렇게 처리하면 전역변수가 늘어나긴 하지만 재랜더링 과정에서 불필요한 서버 호출이 없어진다. 이 방법으로 해결되긴 하지만 이게 권장되는 방식일까?

// ! SuccessCase - App 컴포넌트 밖에 있어야 Re_Render 하더라도 AjaxCounter가 갱신되지 않음
const movieData = getMovies();
export const App = () => {
...
    // ! SuccessCase - Cleanup 함수로 메모리누수 방지
    // ? 참조URL https://ko.reactjs.org/docs/hooks-effect.html#effects-with-cleanup
    let isComponentMounted = true;
    movieData.then(res => {
      if (isComponentMounted) setMovies(res);
    });
    return () => {
      isComponentMounted = false;
    };
  }, []);
profile
블로그 옮겼습니다. https://shlee.cloud
post-custom-banner

0개의 댓글