React - useEffect

UseEffect를 공부하기전 사이드 이펙트란 것을 먼저 알아야 이해가 수월하다.
그냥 있구나~하고 공부하는것과 왜 쓰는지 알고 공부하는 것의 차이는 크기때문에..
먼저,
리액트에서 사이드 이펙트란?
리액트의 중요 임무 중 하나는 앱의 컴포넌트나 상태변경에 의해
UI Rendering 이라는 중요한 임무를 수행한다.
이는 리액트는 가상돔(Virtual DOM)을 이용하여 변경된 부분만 감지하고 이를 랜더링 하는데
리액트의 중요임무 랜더링을 수행함에 있어서 상태변화를 감지하고 이벤트를 처리하는 것을
사이드이펙트라고 볼수 있다.
즉, 사이드 이펙트는 함수나 프로세스의 주된 목적이 아닌 부수적인 동작들을 말한다.
예로, 함수가 데이터를 변경하거나 외부 리소스에 접근하는 것 또한 사이드 이펙트라고 한다.
쉽게 말해서 어플레케이션에서 일어나는 다른 모든 것을 뜻한다.
http 리퀘스트를 보내던지, 브라우저에 저장소에 저장하던지
메인 이벤트를 수행 위해 잠재적 이벤트나 과정을 위해 일어나는
이벤트들을 사이드이펙트라고 한다
하지만 이 리액트의 장점은 단점으로도 작용이 되는데
프로미스나 http 리퀘스트를 요청하여 상태를 변경한다고 한다면 상태변경이 됨에 따라 재 랜더링이 되게 됨으로
'http요청 > 상태변경 > 변경에 의한 재 랜더링> http요청 > 상태변경 > 변경에 의한 재 랜더링'
위와 같은 무한루프에 빠질 가능성도 있다.
여러 방면으로 사용 할 수있겠지만 이러한 문제 또한 방지할 수 있는 유용한 기능으로
리액트 내장 Hook인 UseEffect가 있다.
Dependencies (의존성 )
UseEffect(()=>{ 함수... },[의존성]);
useEffect Hook은 함수, 그리고 괄호 "[ ]"로 의존성을 지정할수 있는 디펜던스(dependencies)로
2개의 매개변수로 정의되어져 있다.
UseEffect는 괄호 "[ ]"에 의존성배열로 지정된 변수가 변경이 되면 함수 부분을 실행, 재실행 한다.
만일 빈 배열이면 처음 마운트 될때, 첫 랜더링 시에 실행이 되고 빈배열이기에 의존성을 찾기못하기 때문에
초기 마운트 때만 실행된다. 이 부분은 테스트할때 console.log 찍는 방안으로 많이 사용하기도 한다.
const [state , setState] = useState('');
UseEffect(()=>{
console.log(state);
},[state]);
예로 위와 같이 설정이 되었다고 가정해보자
UseEffect Hook은 State 상태변수를 의존하고 변경이 감지되면 UseEffect는 state를 console.log를 보여주게 된다.
매우 유용하지 않은가?
변경되었을때만 실행이 된다라는 아주 큰 장점을 가진 Hook으로
다양한 방법으로 응용하여 사용 할 수 있을 것이다.
Clean up
클린업 함수란 간단하게 말해서 useEffect가 종료되기 직전에 실행되는 함수를 말한다.
아래 간단한 코드예제를 보자.
useEffect(() => {
console.log('마운트');
// 클린업 함수
return () => {
console.log('언마운트');
};
}, []);
마운트되면서 '마운트' 라는 로그를 출력할 것이고 함수가 종료되면서 언마운트 되기 때문에
'언마운트'라는 로그를 출력할 것이다.
조금 더 심화적으로 들여다보자.
예로 input에 유효성 검사를 하여 사용자에게 알려주는 기능을 useEffect로 구현해 볼 수 있다.
function App() {
const [value, setValue] = useState('');
const [form , setForm] = useState(false);
useEffect(()=>{
setForm(value.trim().length > 9)
},[value]);
const inputValue = (e) =>{
setValue(e.target.value);
}
return (
<>
<form>
<input type="text" onChange={inputValue} />
{form && '충족함!'}
{!form && '불충족'}
</form>
</>
);
}
간단한 예로 useState를 이용해서 form의 상태변수를 불리언으로 확인하며
충족 / 불충족으로 사용자에게 보여지는 코드이다.
키 값이 입력되면 setValue가 되게되어 value를 의존하고 있는 useEffect는 실행이되게되며 setForm함수도 매번 반영한다
만일 이게 지금 간단한 앱이아닌 무거운 api를 호출한다고 하면 웹사이트자체가 무거워 지거나 불필요한 리소스를 실행하게 되며 자원낭비를 초래한다.
여기서 useEffect에서 클린업함수를 사용하여 지속적인 호출을 막을 수가 있는데
useEffect(()=>{
const call = setTimeout(()=>{
setForm(value.trim().length > 9)
},500);
return ()=>{
clearTimeout(call);
};
},[value]);
위와 같이 클린업 함수를 사용하여 효율적으로 변경 가능하다.
위의 함수는 useEffect를 매번 호출하지만 setTimeout으로 작업을 예정하며 클린업함수가 실행되고 setTimeout ,
'call'함수를 종료시켜버린다.
지속적으로 타이핑을 할경우에 연속적으로 검사하는 것이 아닌 최종적으로 입력된 후에 0.5초에 검사를 한번 실행한다.
유동적으로 검사 할 수 있는 기능이며, 불필요한 호출을 제거하는 '디바운싱' 이라는 기술이다.
디바운싱은 Javasciprt나 다른 언어로도 구현 가능하나 React에서는 UseEffect로 효율적으로 관리가 가능함으로
예시를 들어보았다.
위와같이 UseEffect는 매우 효율적이면서 강력한 Hook이며
fetch에 프로미스 async / await를 이용하여 동기적으로 관리하고 자원낭비를 줄일 수도 있으며,
컴포넌트의 마운트, 언마운트, 업데이트 , 생명주기 등 부수적인 사이드이펙트를 효율적으로 관리한다.
Hook들은 정말유용하지만
개인적으로 useEffect는 React에서 useState 다음으로 중요한 Hook이 아닐까란 생각이 든다.
'React' 카테고리의 다른 글
| [React] Css in js / Styled.component (0) | 2024.02.03 |
|---|---|
| [React-Query 사용하기] (1) | 2024.01.30 |
| [React-datePicker] 시작날짜, 종료날짜 컴포넌트 만들기 (1) (1) | 2024.01.27 |
| React - Router [ action , loader ] (2) | 2024.01.09 |
| React - useMemo (1) | 2023.12.09 |