[React] 데이터 흐름 이해와 비동기 요청 처리

hosik kim·2021년 11월 3일
0

With CodeStates

목록 보기
14/45
post-thumbnail

💡React 데이터 흐름

🔸React에서의 데이터 흐름


1) 컴포넌트로 생각하기

React를 사용하는 개발 방식은 component 단위로 개발을 시작한다.
component 단위를 찾고나면, component를 만들고 조립해나가면서 Web page를 만든다. 이것을 상향식(bottom-up)으로 앱을 만든다 라고 말한다.

상향식의 장점

  • 테스트가 쉽고 확장성이 좋다.
  • 단일 책임 원칙(한 컴포넌트는 하나의 일만 한다)

[그림] 컴포넌트의 분할

[그림] 컴포넌트의 트리구조화

2) 데이터는 위에서 아래로 흐른다. <top-down (하향식) data flow>

one-way data flow(단방향 데이터 흐름)이다.
컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 인자(arguments) 혹은 속성(attributes)처럼 전달받을 수 있다.

  • 데이터를 전달하는 주체 : 부모 component
  • 데이터를 전달받는 객체 : 자식 component
    자식 component는 props 를 통해 전달받은 data 가 어디에서부터 전달되었는지 알지 못한다.

    [그림] top-down(하향식) data-flow

3) 데이터의 정의

  • 변하지 않는 값 (전체 기록된 데이터)
  • 변하는 값 (작성중인 새로운 데이터) ======> ‼️ STATE ‼️

State 다루는 법

  • State를 최소화하는 것이 가장 좋다.

  • 아래 조건이 맞다면 State가 아니다(X)!!

    • 부모로부터 props를 통해 전달이 된다.
    • 시간이 지나도 변하지 않는다.
    • 컴포넌트 안의 다른 state나 props를 가지고 계산이 가능한가?
  • State를 어디에 위치시켜야 하는가?

[그림] 두 개의 자식 컴포넌트가 하나의 상태에 접근하고자 할 때는 두 자식의 공통 부모 컴포넌트에 상태를 위치해야 한다.

4) State 끌어올리기 (Lifting state up)

하위 컴포넌트(NewTweetForm)에서의 클릭 이벤트가, 부모의 상태를 바꾸어야만 하는 상황이 왔다. 이를 어떻게 해결할 수 있을까?

이를 해결할 수 있는 키워드는 바로 "State 끌어올리기(Liftin state up)"이다.

[그림] 상태를 변경시키는 함수(handler)를 하위 컴포넌트에 props로 전달해서 해결할 수 있다.

💡Effect Hook

🔸Side Effect (부수 효과)


: 함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect가 있다고 이야기한다.

다음은, 전역 변수 foo를 bar라는 함수가 수정하는 예제이다.

let foo = 'hello';

function bar() {
 foo = 'world';
}
bar(); // bar는 Side Effect를 발생시킨다!

🔸Pure Function (순수 함수)


: 순수 함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미한다. 함수의 입력이 아닌 다른 값이 함수의
결과에 영향을 미치는 경우, 순수 함수라고 부를 수 없다. 또한 순수 함수는, 입력으로 전달된 값을 수정하지 않는다.

function upper(str) P
return str.toUpperCase(); // toUpperCase 메소드는 원복을 수정하지 않는다 (Immutable)
}
upper('hello') // 'HELLO'

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

🔸React의 함수 컴포넌트


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

function SingleTweet({ writer, body, createAt}) {
  return <div>
    <div>{writer}</div>
    <div>{createAt}</div>
    <div>{body}</div>
  </div>
}

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

React 컴포넌트에서의 Side Effect

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

🔸API


useEffect(함수, [종속성1, 종속성2, ...])
: 컴포넌트 내에서 Side effect를 실행할 수 있게 하는 Hook

  • 첫번째 인자: 함수
  • 두번째 인자: 우리가 관찰하고 싶은 값이 배열(어떤 값의 목록)로 들어간다. 배열 내의 어떤 값이 변할때에만,(effect가 발생하는) 함수가
    실행된다. Hook은 최상위 컴포넌트에서 쓰며 함수 내에서 호출한다.

effect hook의 실행

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

이와 같이 매 번 새롭게 컴포넌트가 렌더링될 때 Effect Hook이 실행된다.

Hook을 쓸 때 주의할 점

  • 최상위에서만 Hook을 호출한다.
  • React 함수 내에서 Hook을 호출한다.
    공식 문서

🔸단 한번만 실행되는 Effect 함수


:두 번째 배열을 빈 배열[]로 둘 경우

1. 빈 배열 넣기
useEffect(함수, [])
: 빈 배열을 useEffect의 두번째 인자로 사용하면, 이 때에는 컴포넌트가 처음 생성될때만 effect 함수가 실행된다.
처음 단 한번, 외부 API를 통해 리소스를 받아오고 더이상 API 호출이 필요하지 않을 떄에 사용할 수 있다.

2. 아무것도 넣지 않기(기본 형태)
useEffect(함수)
: 기본 형태의 useEffect는 컴포넌트가 처음 생성되거나, props가 업데이트되거나, 상태(state)가 업데이트될 때 effect 함수가 실행된다.

🔸 컴포넌트 내에서 AJAX 요청

Data Fetching


1. 컴포넌트 내에서 필터링
2. 컴포넌트 외부에서 필터링

두 방식의 차이점은 무엇일까?

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

💡AJAX (Asynchronous Javascript And XML)


: JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 데이터를 주고 받는 기술
AJAX란, JavaScript의 라이브러리중 하나이다. 웹 페이지 전체를 렌더할 필요 없이 페이지의 일부만을 위해
데이터를 로드하는 기법이다. 동적인 웹페이지를 만들기 위한 개발 방법이라고 할 수 있다.

  • JavaScript에서 비동기 HTTP 통신이 가능하도록 해준다. 비동기 Http 통신이란 response와 request를 비동기식으로
    다룰 수 있다는 것의 의미한다.

  • 페이스북에서 좋아요 버튼을 누를 때마다 페이지가 갱신된다면, 구글에서 검색을 하는데 추천 검색어가 로드될때마다 페이지가 새로고침 된다면?
    비동기식으로 주고받으며 이 같은 문제들을 해결하는 것이다.

🔸Axios와 Fecth


: 기존에 web에서 어떤 리소스를 비동기로 요청하기 위해서는 XHR(XML HTTP Request)객체를 사용했어야 했었는데,
XHR은 잘 디자인되어 있는 API가 아니다. 이를 보완하기 위해 HTTP 요청에 최적화 되어 있고 상태도 잘 추상화 되어 있는
API들이 생겨나기 시작했다. 대표적으로 Axios와 fetch가 있다.

Axios

promise based HTTP client for the browser and node.js
: 즉, node.js와 브라우저를 위한 HTTP통신 라이브러리이다. 비동기로 HTTP 통신을 가능하게 해주며 return을 promise 객체로
해주기 때문에 response 데이터를 다루기도 쉽다.

Axios의 post method 구현

axios({
  method: 'POST',
  url: '/user/12345',
  data: {
     firstName: 'hosik',
     lastName: 'Kim'
  }
});

Fetch

: fecth는 ES6부터 JavaScript의 내장 라이브러리로 들어왔다. promise 기반으로 만들어졌기에 Axios와 마찬가지로
데이터를 다루는데 어렵지 않다.

fecth(url)
 .then((response) => reponse.json()) 
// 자체적으로 json() 메소드가 있어, 응답을 JSON 형태로 변환시켜서 다음 Promise로 전달한다.
 .then((json) => console.log(json))
// 콘솔에 json을 출력한다.
 .catch((error) => console.log(error))
// 에러가 발생한 경우, 에러를 띄운다.
profile
안되면 될 때까지👌

0개의 댓글