React 데이터 흐름?
React 데이터 흐름
React의 개발 방식의 가장 큰 특징은 컴포넌트 단위로 페이지를 구성하는 것이다. 한개의 웹 페이지를 여러 컴포넌트로 잘라서 구성한 뒤 조립하는 형식으로 웹 애플리케이션을 구성할 수 있다. 이 방식은 가장 기초 단위인 컴포넌트에서 시작해서 전체 페이지를 구성하는 상향식(Bottom-up) 방식이다.
상향식 방식으로 웹 애플리케이션을 구성할 때 장점은 단위 테스트가 용이하고 확장성이 높다는 것이다. 따라서 웹 애플리케이션의 프론트를 설계 할 때 가장 먼저 해야 할 일이 컴포넌트 단위로 구조를 쪼개는 작업이다.
모든 컴포넌트는 단일 책임 원칙을 따른다. 즉 컴포넌트는 한가지 일만 수행해야 한다는 것이다.
props?
컴포넌트에 전달되는 데이터는 props로 관리된다. React는 상위 컴포넌트에서 하위 컴포넌트로 데이터가 흘러가는 단방향 데이터 흐름(One-Way Data Flow)을 가지고 있으며, 하향식(Top-Down) 방식을 따른다. props를 전달받은 하위 컴포넌트는 데이터가 어디서 왔는지 알지 못한다.
state?
컴포넌트 내에는 변하는 값과 변하지 않는 값이 동시에 존재한다. 사용자와 상호작용하는 부분에서는 데이터가 변하게 될 것이고, 그렇지 않은 부분은 데이터가 고정된다. 여기서 시시각각으로 변하는 데이터를 state로 관리하게 된다. state로 관리할 데이터를 정하는 기준은 다음과 같다.
state인지 판별하는 방법
- 부모로 부터 props를 통해 전달된다면 state가 아니다.
- 시간이 지나도 변하지 않는다면 state가 아니다.
- 컴포넌트 안의 다른 state나 props를 가지고 계산이 가능하다면 state가 아니다.
state는 하위 컴포넌트에서 공유할 수 있기 때문에 모든 컴포넌트가 공유하는 상위 컴포넌트에 위치해야 한다. 사용자의 입력을 통해 state에 접근에 데이터를 변경하는 경우 상위 컴포넌트에서 변경된 state를 관리하게 된다.
React 역방향 데이터 흐름
분명 React는 단방향 데이터 흐름을 가지고 운용된다. 하지만 부모의 state가 하위 컴포넌트의 기능을 통해 변하는 경우가 있따. 만약 사용자가 새로운 정보를 입력하고 submit을 하는 경우 상위 컴포넌트에서 관리되고 있는 state는 변하게 된다.
하위 컴포넌트에서의 상호작용이 상위 컴포넌트의 state를 변경하기 위해서 필요한 기술이 state 끌어올리기(Lifting state up)이다.
state 끌어올리기를 구현하기 위해서는 하위 컴포넌트에 state를 변경하는 handler 함수를 props로 내려주어야 한다. 하위 컴포넌트에서는 props로 전달받은 handler 함수를 콜백함수처럼 사용해서 상위 컴포넌트의 state를 변경한다.
upperComponent에서는 value값을 state로 관리하고 있다. 만약 하위 컴포넌트에서 이 state 값을 변경하기 위해서는 state 값에 접근할 수 있는 valueHandler() 함수를 props로 내려주게 된다.
이제 lowerComponent에서는 props로 전달받은 valueHandler() 함수를 콜백함수로 사용해서 상위 컴포넌트의 state에 접근 및 데이터 변경을 할 수 있게 된다. 이 과정이 state 끌어올리기다.
import {useState} from 'react';
function upperComponent() {
const [value, setValue] = useState();
const valueHandler=()=>{
setValue("변경할 값")
}
return (
<div>
<lowerComponent valueHandler={valueHandler}/>
</div>
)
}
function lowerComponent(props){
return (
<div>
<button onClick={props.valueHandler}>Click</button>
</div>
)
}
React Side Effect 관리
일반적으로 Side Effect는 부작용이라는 뜻을 가지고 있다. Javascript에서 side Effect는 함수 내부의 어떤 코드가 함수 외부에 영향을 미치는 것을 의미한다.
반대로 순수 함수는 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미한다. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우 순수함수가 아니다. 순수함수에 전달된 입력값은 변하지 않는다. 순수함수는 어떤 인자를 전달받아 항상 똑같은 값을 반환한다.
순수함수 예제
// 순수함수다.
function pureFunc (input){
return input;
}
// 순수 함수가 아니다.
function non_pureFunc(input){
return input*2;
}
React에서 Side Effect
React에서 AJAX 요청이나, 타이머 API, LocalStorage 캐시 관리 등은 모두 Side Effect가 된다. 입력값이 변경되어 반환되고, 함수를 실행할 때 마다 동일한 결과값을 보장하지 않기 때문이다. React에서 Side Effect를 관리하기 위한 API는 Effect Hook이다.
useEffect(func, [state])
Effect Hook은 useEffect()라는 함수를 지원한다. useEffect()함수가 실행되는 시점은 React의 생명주기를 이해할 필요가 있다. React의 컴포넌트는 최초 렌더링 되는 시점과 관리 중인 state가 변경될 때 리렌더링이 발생한다. useEffect()가 실행되는 시점은 React 생명주기와 연결되어 있다.
useEffec()가 실행되는 시점
Effect Hook이 실행되는 시점은 기본적으로 컴포넌트가 새롭게 렌더링 되는 시점이다. 아래에서 살펴볼 종속성 배열값이 빈 배열이나 주어지지 않는 경우 아래 시점에 useEffect() 함수가 호출된다. 즉 useEffect() 단 한번만 실행하기 위해서는 종속성 배열값을 비우는 것이다. 서버에서 API 호출을 한 뒤 리소스를 받고 더 이상 API 호출을 하지 않는 경우 종속성 배열을 비울 수 있다.
- 컴포넌트 생성 후 처음 화면에 렌더링 되는 시점
- 컴포넌트에 새로운 props가 전달되어 렌더링 되는 시점
- 컴포넌트과 관리중인 state가 변경되어 리렌더링 되는 시점
useEffect()를 사용할 때 주의 사항은 최상위 지점에서 HOOK API를 사용해야 한다는 점이다. 반복문, 조건문, 중첩된 함수 내에서 HOOK API를 사용하면 안된다. 이 규칙을 따라야 동일한 순서로 HOOK API가 정상적으로 호출된다.
또한 일반적인 함수 안에서 HOOK API를 사용하면 안된다. 오직 React 함수(컴포넌트) 내에서만 HOOK API를 사용해야 한다.
Effect Hook 사용 규칙
- React 함수 내에서만 사용해야 한다.
- 최상위 지점에서만 사용해야 한다. (반복문, 조건문, 중첩 함수 내부 X)
useEffect() 인자
useEffect의 첫번째 인자는 함수를 전달받는다. 컴포넌트가 새롭게 렌더링 되는 시점에 useEffect()가 호출되었을 때 호출할 콜백함수를 첫번째 매개변수로 전달받는다. 두번째 매개변수는 종속성 배열을 전달받는다. 배열의 값이 변경될 때 useEffect() 함수가 호출된다. 종속성 값은 여러개를 담을 수 있다.
useEffect(callback, [종속성1, 종속성2, 종속성3... ])
value1, value2, value3 state를 소유한 컴포넌트가 있다. 종속성 배열에 담긴 값들이 변경될 때 마다 useEffect() 함수가 호출되고, 첫번째 매개변수로 전달받은 함수를 실행하게 된다. 즉, value값이 변경될 때(Side Effect가 발생할 때 마다) 마다 변경된 value값이 화면에 출력된다.
import {useState} from 'react';
function upperComponent() {
const [value1, setValue1] = useState();
const [value2, setValue2] = useState();
const [value3, setValue3] = useState();
const valueHandler=()=>{
setValue1("변경할 값")
setValue2("변경할 값")
setValue3("변경할 값")
}
useEffec(()=>{
console.log(`
value1:${value1}
value2:${value2}
value3:${value3}
`)
},[value1, value2, value3])
return (
<div>
<lowerComponent valueHandler={valueHandler}/>
</div>
)
}
Reference
'Programming' 카테고리의 다른 글
[Programming] 웹서버(Web)와 웹 어플리케이션 서버(WAS) 차이점 The difference between Web Server and Web Application Server (0) | 2022.05.25 |
---|---|
[Programming] CORS란? (preflight, OPTIONS 메소드?) (0) | 2022.05.25 |
[Javascript] setTimeout vs setInterval 차이 (debounce, throttle ?) (0) | 2022.05.22 |
[Javascript] apply() vs call() vs bind() 차이 (0) | 2022.05.21 |
[Javascript] AJAX란? (feat. Fetch, XHR, 장점 단점) (0) | 2022.05.20 |
댓글