[React] Effect Hook(useEffect), AJAX request(fetch)

Steve·2021년 5월 25일
0

웹개발 코스

목록 보기
32/59

React Data Flow
React Effect Hook

  • side effect
  • pure function
  • useEffect()

컴포넌트 내에서 Ajax 요청


React Data Flow

리엑트는 "단방향 데이터 흐름(one-way data flow)" 이라는 특징을 가지고 있다.
부모 컴포넌트가 자식 컴포넌트에게 Props 를 이용하여 데이터를 전달한다.

그런데 부모 컴포넌트의 상태가 하위 컴포넌트에 의해 변하는 상황도 존재한다.
이럴 경우 상태 끌어올리기(lifting state up) 을 해야 한다.

부모 컴포넌트에서 상태를 변경시키는 함수(setState() 를 넣은 함수)를 만들어 props를 통해 자식 컴포넌트에 전달하면, 하위 컴포넌트가 이 함수를 실행한다. 마치 콜백 사용과 비슷하다.

function Parent() {
  const [state, setState] = useState(false);
  
  // state를 변경하는 함수 만듦
  const handleChangeValue = value => { 
    setState(value);
  }
  
  // children 에 함수를 전달
  return (
  <div>
    <Children handleButtonClick={handleChangeValue} />
  </div>
  )
}

React Effect Hook (useEffect)

Side Effect (부수 효과)

프로그래밍에서 side effect 는 함수가 자신의 외부에 영향을 끼치는 경우 "함수가 side effect 를 발생시킨다" 라고 한다.

Pure Function (순수 함수)

순수 함수는...

  1. 동일한 입력(input)에는 항상 동일한 결과를 낸다. (예측 가능)
  2. 자신 외부의 상태를 변경하지 않는다.
  3. 자신 또한 외부의 상태에 영향을 받지 않는다

수학에서 정의하는 '함수' 와 비슷하다

예시)

  • Math.random() 은 순수함수가 아니다 - 1. 동일한 입력에 동일한 결과를 내지 않는다.
  • fetch API 로 Ajax 요청을 하는 함수는 순수 함수가 아니다 - 3. 자기 자신이 외부의 상태에 영향을 받는다.
    • 여기서 외부의 상태는 인터넷 연결 상태, 요청의 상태, 서버 상태 등이 있을 수 있다.

React 에서의 Side effect

React의 함수 컴포넌트는 props가 입력으로, JSX Element가 출력으로 나간다. 여기에는 그 어떤 Side Effect도 없으며, 순수 함수로 작동한다.

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

  • Web API - setTimeout, fetch
  • Browser API - LocalStorage, DOM 접근 (document.title 사용 하여 <title> 변경 등)

React 와 상관없는 API 를 사용하면 side effect 이며, Effect Hook 을 사용하여야 한다.

useEffect()

React 에서 useEffect는 컴포넌트 내에서 side effect (fetch, setTimeout, LocalStorage 등) 를 실행할 수 있게 하는 Hook 이다.
useEffect 는 컴포넌트 안에 작성한다.

useEffect(function [, depencency 1, depencency 2, ...])

Parameters:
1. function - 실행할 함수
2. dependencies - 종속될 요소 배열 (dependency array) [optional]

Parameters 설명:

  1. 실행할 함수: function 인자에 annonymous function 을 넣고 그 안에 실행할 side effect 를 적어주면 된다.

  2. 종속될 요소 배열: 종속성 배열 내의 값이 변경이 일어날 때만 useEffect 의 실행할 함수가 호출되게 만들 수 있다. 그래서 배열 안에는 변화가 일어나는 state 변수들을 넣어준다.

종속될 요소 배열 인자useEffect() callback 작동
없음매번 자신이 위치한 컴포넌트가 렌더링 될 때 실행
빈 배열 ([])컴포넌트 최초 생성 시에만 한번 실행되고 다시 실행되지 않음
배열종속성 배열 내의 값이 변경이 일어날 때만 실행

컴포넌트는 다음 경우 렌더링된다(이때 useEffect 의 함수가 호출된다):

  1. 컴포넌트 최초 생성 후 한번
  2. 컴포넌트에 새로운 Props 가 전달될 때마다
  3. 컴포넌트 내의 state(상태) 가 바뀔 때마다

Hook 을 쓸 때 주의할 점

https://reactjs.org/docs/hooks-rules.html

  1. 최상위에서만 호출한다 (반복문, 조건문, 고차함수에서 사용하지 않는다)
  2. React 컴포넌트 내에서만 호출한다.

컴포넌트 내에서 Ajax 요청

서버 요청(fetch)은 side effect 를 일으키는 동작이기 때문에, React component 에서 AJAX 요청을 하려면 useEffect() 안에 fetch 를 쓴다.

useEffect(() => {
  fetch(`http://address.com/method?parameter=value)
    .then(resp => resp.json())
    .then(result => {...});
}, [filter]);

입력창을 통한 목록 필터링을 구현하기 위해 다음 두가지의 접근이 있을 수 있다:

  1. 컴포넌트 내부에서 필터링:
    전체 목록 데이터를 불러오고, 목록을 검색어로 필터

  2. 컴포넌트 외부에서 필터링:
    컴포넌트 외부로 API 요청을 할 때에, 필터링한 결과를 받아옴.
    (보통 서버에 매번 검색어와 함께 요청하는 경우)

 장점단점
컴포넌트 내부에서 처리HTTP 요청의 빈도를 줄일 수 있다.브라우저의 메모리 상에 많은 데이터를 갖게 되므로 클라이언트의 부담이 늘어난다.
컴포넌트 외부에서 처리클라이언트의 부담이 줄어든다.HTTP 요청이 늘어나며, 서버의 부담이 늘어난다.

상용 어플리케이션은 클라이언트와 서버의 부담을 적절히 분배하여 설계한다.

Loading indicator

Ajax 요청이 느릴 경우에는 로딩 화면(loading indicator)을 사용한다.

클라이언트가 서버에 요청을 덜 보내는 방법

  • throttling
  • debouncing

Debouncing and Throttling Explained Through Examples | CSS-Tricks

서버가 클라이언트에게 돌려줄 응답을 캐싱하는 방법

HTTP caching | MDN

profile
게임과 프론트엔드에 관심이 많습니다.

0개의 댓글