React 클라이언트 Ajax 요청(2) Effect Hook

HanSungUk·2022년 6월 19일
0

React

목록 보기
4/13
post-thumbnail

React 클라이언트 Ajax 요청(2) Effect Hook

현재 코드스테이츠 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.

학습목표

  • Side effect가 어떤 의미인지 알 수 있다.
  • React 컴포넌트를 만들 때 side effect로부터 분리해서 생각할 수 있다.(비즈니스 로직과 표현 영역 구분)
    • Side effect의 예를 들 수 있다.
  • Effect Hook을 이용해 비동기 호출 및 AJAX 요청과 같은 side effect를 React 컴포넌트 내에서 처리할 수 있다.
  • Effect Hook에서의 dependency array 사용법을 이해할 수 있다.
  • 컴포넌트 내에서 네트워크 요청 시, 로딩 화면과 같이 보다 나은 UI를 만드는 법을 이해할 수 있다.

1. Side Effect

  • Side Effect(부수 효과)
    함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect가 있다고 이야기 합니다. React에서는 컴포넌트 내에서 fetch를 사용해 API 정보를 가져오거나 이벤트를 활용해 DOM을 직접 조작할 때 Side Effect가 발생했다고 말합니다.
let foo = 'hello';

function bar(){
	foo = 'world';
}

bar(); // bar는 Side Effect를 발생시킵니다.
  • Pure Function(순수 함수)
    순수 함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미합니다. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우, 순수 함수라고 부를 수 없습니다. 또한 순수 함수는 입력으로 전달된 값을 수정하지 않습니다.
function upper(str){
	return str.toUpperCase(); //toUpperCase 메소드는 원본을 수정하지 않습니다.(immutable)
}

upper('hello') // 'HELLO'

순수 함수에는 네트워크 요청과 같은 Side Effect가 없습니다. 순수 함수의 특징 중 하나는, 어떠한 전달 인자가 주어질 경우, 항상 똑같은 값이 리턴됨을 보장합니다. 그래서 예측 가능한 함수이기도 합니다.

Q. Math.squrt()는 순수 함수인가요?
A. Math.squrt()는 전달 인자 x의 제곱근 값을 구하는 메서드입니다. 주어진 인자에 대해 항상 동일한 결과값을 리턴하므로 순수함수입니다.

Q. Math.random()은 순수 함수인가요?
A.

다음 예제를 생각해봅시다.
Math.random(); // => 0.4011148700956255
Math.random(); // => 0.8533405303023756
Math.random(); // => 0.3550692005082965
함수를 호출할 때 우리가 아무런 인자도 넘기지 않았음에도 불구하고, 이 함수들은 각각 다른 출력 값을 만들어냅니다. 이 사실이 의미하는 바는 Math.random() 함수는 순수하지 않다는 것을 의미합니다.

Q. 어떤 함수가 fetch API를 이용해 AJAX 요청을 한다고 가정해 봅시다. 이 함수는 순수 함수가 아닙니다. 왜일까요?
A. Ajax 요청은 외부 상태를 바꾸기 때문에 해당 기능을 가진 함수는 순수 함수가 아닙니다.

  • React의 함수 컴포넌트
    아래의 함수 컴포넌트는 props가 입력으로, JSX Element가 출력으로 나갑니다. 여기에는 그 어떤 Side Effect도 없으며, 순수 함수로 작동합니다.
function SingleTweet({writer, body, createdAt}){
	return <div>
      <div>{writer}</div>
  	  <div>{createdAt}</div>
  	  <div>{body}</div>
  	</div>
}

하지만 보통 React 애플리케이션을 작성할 때는 AJAX 요청이 필요하거나, LocalStorage 또는 React와 상관없는 API를 사용하는 경우가 발생할 수 있습니다. 이는 React의 입장에서는 전부 Side Effect입니다.

React 컴포넌트의 Side Effect

  • 타이머 사용(setTimeout)
  • 데이터 가져오기(fetch API, localStorage)

순수 함수의 출력값에 영향을 미치는 작업들이 바로 Side Effect라고 할 수 있습니다. 따라서 Side Effect를 최소화하거나 따로 분리하여 함수로 묶어주는 작업은 해당 프로젝트나 소프트웨어의 유지보수를 좀 더 수월하게 해줍니다.

2. Effect Hook

Effect Hook은 다음의 경우처럼 매번 새롭게 컴포넌트가 렌더링 될 때 Effect Hook이 실행됩니다.

  • 컴포넌트 생성 후 처음 화면에 렌더링 될때(Mount)
  • 컴포넌트에 새로운 props가 전달되며 렌더링 될때(Update)
  • 컴포넌트에 상태(state)가 바뀌며 렌더링 될때(Update)

Hook을 쓸 때 주의할 점은 다음과 같습니다,.

  • 최상위에서만 Hook을 호출합니다.
    그래야만 컴포넌트가 렌더링 될때마다 동일한 순서의 Hook 호출이 보장됩니다.

  • React 함수 내에서 Hook을 호출합니다.

1. useEffect

useEffect는 컴포넌트 내에서 Side Effect를 실행할 수 있게 하는 Hook입니다.

어떤 컴포넌트가 Mount(화면에 첫 렌더링)되었을 때, Update(다시 렌더링)될 때 혹은 Unmount(화면에서 사라질 때) 특정 작업을 처리할 코드를 실행시키고자 할 때 useEffect()를 사용하면 됩니다.

  • 기본 형태
    useEffect(()=>{})
    기본적으로 useEffect Hook은 인자로 콜백 함수를 받습니다.
    콜백 함수란 다른 함수의 인자로 전달된 함수를 의미합니다.
    이 콜백 함수 내부에 우리가 원하는 작업을 작성하면 됩니다.

useEffect Hook은 두 가지 형태가 있습니다.
첫 번째 형태는 인자로 콜백 함수만 받습니다.
실행은 컴포넌트가 렌더링 될때마다 매번 실행됩니다.

useEffect(()=>{
	// 작업..
});

두 번째 형태는 첫 번째 인자로 콜백 함수를 받고 두 번째 인자로 배열을 받습니다. 이 배열은 다른 이름으로 dependency array(종속성 배열)라고도 합니다.
실행은 화면에 첫 렌더링(Mount) 될때, value 값이 바뀔때마다 실행됩니다.

useEffect(()=>{
	// 작업..
}, [value]);

dependency array(종속성 배열)은 조건을 담고 있습니다. 여기서 조건은 boolean 형태의 표현식이 아닌, 어떤 값의 변경이 일어날 때 를 의미합니다. 따라서 해당 배열엔 어떤 값 의 목록이 들어갑니다.

만약 두 번째 인자로 빈 배열이 전달된다면 실행은 화면에 첫 렌더링(Mount) 될때만 실행됩니다.

useEffect(()=>{
	// 작업..
}, []);
  • Clean up - 정리
const Timer = (props)=>{
  useEffect(()=>{
    // 타이머 컴포넌트가 맨 처음 브라우저에 렌더링(Mount) 됐을 때 실행
      const timer = setInterval(()=>{
      console.log('타이머, 돌아가는 중..')}, 1000)

      // 타이머 컴포넌트가 화면에서 사라질 때(Unmount) 실행됩니다.
    return ()=>{
      ClearInterval(timer)
    }
  }, []);
}

목록 내 필터링을 구현하기 위해서는 다음과 같은 두 가지 접근을 할 수 있습니다.

  1. 컴포넌트 내에서 필터링 : 전체 목록 데이터를 불러오고, 목록을 검색어로 filter하는 방법(처음 단 한 번, 외부 API로부터 목록 데이터를 받아오는 경우가 해당합니다.)

  2. 컴포넌트 외부에서 필터링 : 컴포넌트 외부로 API 요청을 할 때, 필터링 한 결과를 받아오는 방법(서버에 매번 검색어와 함께 요청하는 경우가 이에 해당합니다.)

두 방식의 차이점은 다음과 같습니다.

방식장점단점
컴포넌트 내부에서 처리HTTP 요청의 빈도를 줄일 수 있다.브라우저(클라이언트)의 메모리 상에 많은 데이터를 갖게 되므로, 클라이언트의 부담이 늘어난다.
컴포넌트 외부에서 처리클라이언트가 필터링 구현을 생각하지 않아도 된다.빈번한 HTTP 요청이 일어나게 되며, 서버가 필터링을 처리하므로 서버가 부담을 가져간다.

Q. React에서 Ajax 요청을 보낼 때 Effect Hook을 사용하는 것이 좋나요?
A. 웹 앱을 구성할 때, 서버로의 네트워크 요청을 보내야 되는 경우가 있습니다. React에서는 이러한 Ajax 요청을 처리할 때, Side Effect를 최소화하기 위해서 Effect Hook을 사용합니다. 만약 Hook을 사용하지 않고 네트워크 요청을 하면 그 동안에 페이지가 멈추거나 깜빡할 수 있습니다.

0개의 댓글