안녕하세요 ! 오늘은 useEffect를 왜 사용하는지 공부해봤습니다.
useEffect 함수란
- 어떤 컴포넌트가 Mount, Update, Unmount될 때 특정 작업을 실행할 처리 코드를 실행시켜 주고 싶을 때 실행하는 기능입니다.
모던 리액트 Deep Dive 책에 따르면 "useEffect는 애플리케이션 내 컴포넌트의 여러 값들을 활용해 동기적으로 부수 효과를 만드는 메커니즘이다. 그리고 이 부수효과가 '언제' 일어나는지보다 어떤 상태값과 함께 실행되는지 사려보는 것이 중요하다"고 정의되어 있습니다.
**Mount : 화면에 첫 렌더링 / Update : 다시 렌더링 / Unmount : 화면에서 사라질 때
다음 예제 코드로 useEffect를 왜 사용하는지 알아보자
import React, { useState, useEffect } from 'react';
function App() {
const [count, setCount] = useState(0);
const clickCount = () => { //click 버튼을 눌렀을 때 실행되는 함수
setCount(count + 1);
console.log("Count click했음");
};
console.log("기본 렌더링 될 때마다");
return (
<>
<button onClick={clickCount}>Count Button</button>
<div>{count}</div>
</>
);
}
위의 상태로 React 코드를 실행시켜 확인해 보면
이렇게 "기본 렌더링 될 때마다" 실행되는 모습을 볼 수 있습니다. 여기서 기억해야 할 사실은 함수형 컴포넌트는 매번 함수를 실행해 렌더링을 수행한다는 점입니다.
이 현상으로 인해 외부에서 API를 가져오거나 대량의 데이터를 다룰 때 다른 state값이 변경되면 그때마다 API를 새로 가져오게 되고, 대량의 데이터를 리렌더링해야 하기 때문에 성능상 비효율적이라는 것을 알 수 있습니다.
따라서 이를 해결하기 위해 useEffect를 사용합니다.
import React, { useState, useEffect } from 'react';
function App() {
const [count, setCount] = useState(0);
const clickCount = () => { //click 버튼을 눌렀을 때 실행되는 함수
setCount(count + 1);
console.log("Count click했음");
};
console.log("기본 렌더링 될 때마다");
//위의 console.log()와 같이 기본 렌더링 될 때마다 실행됨
useEffect(() => { console.log("렌더링 될 때마다 | useEffect"); });
//Dependency array를 빈 배열로 실행 시킬 시 화면이 첫 렌더링 될 때만 실행됨
useEffect(() => { console.log("처음 렌더링 될때만 실행"); },[]);
return (
<>
<button onClick={clickCount}>Count Button</button>
<div>{count}</div>
</>
);
}
위의 코드를 실행시켜 보면,
이렇게 출력 값이 나오게 되는데, 여기서 useEffect의 유형에 따라 실행 결과가 달라지게 됩니다.
useEffect는 크게 2가지 유형으로 볼 수 있습니다.
useEffect 유형
1. component가 렌더링 될때마다 실행되는 유형 → 컨포넌트가 렌더링 되었는지 확인하기 위한 방법으로 사용
2. 의존성 배열(Dependency array)에 의해 실행되는 유형
따라서, 1번의 유형은 "렌더링이 될 때마다 | useEffect"가 출력된 예시이며, 2번 유형은 "처음 렌더링 될 때만 실행"가 출력된 예시가 됩니다.
2번 유형 중에서는 의존성 배열에 값이 있느냐 없느냐에 따라 결과 값이 달라지기도 합니다.
먼저, 앞서 보여드렸던 "처음 렌더링 될 때만 실행"을 출력할 경우네는 의존성 배열을 빈 배열을 넣으면 처음 컴포넌트가 마운트될 때만 실행됩니다.
또 의존성 배열에 value값을 넣게 되면 해당 value값이 변경 될 때마다 호출 됩니다.
아래는 의존성 배열에 value값을 넣었을 때 예시 코드입니다.
import React, { useState, useEffect } from 'react';
function App() {
const [count, setCount] = useState(0);
const clickCount = () => { //click 버튼을 눌렀을 때 실행되는 함수
setCount(count + 1);
console.log("Count click했음");
};
const [text, setText] = useState("");
const clickText = () => {
setText(text + "Hi! useEffect!");
console.log("Text click했음");
}
//Dependct array에 count를 넣어 count 값이 바뀔 때에만 리렌더링 시켜줌.
useEffect(() => { console.log("count 값이 변할 때 실행"); }, [count]);
//Dependct array에 text를 넣어 text 값이 바뀔 때에만 리렌더링 시켜줌.
useEffect(() => { console.log("text 값이 변할 때 실행"); }, [text]);
//Dependct array에 count,text를 넣어 count나 text 둘 중 한개가 바뀌면 리렌더링 시켜줌.
useEffect(() => { console.log("count, text 값이 변할 때 실행"); }, [count, text]);
return (
<>
<button onClick={ clickCount }>Count Button</button>
<div>{count}</div>
<button onClick={ clickText }>Text Button</button>
<div>{text}</div>
</>
);
}
먼저 모든 값이 렌더링 상태에 Count Button을 눌렀을 때, "Count click했음", "count 값이 변할 때 실행", "count, text 값이 변할 때 실행"을 출력하였고, 다음 두번 연속 Text Button 눌렀을 때 "Text click했음", "text 값이 변할 때 실행", "count, text 값이 변할 때 실행"이 2번 반복하여 출력 되는 것을 확인할 수 있습니다.
또 하나의 궁금점
import React, { useState, useEffect } from 'react';
function App() {
const [count, setCount] = useState(0);
const clickCount = () => { //click 버튼을 눌렀을 때 실행되는 함수
setCount(count + 1);
console.log("Count click했음");
};
console.log("기본 렌더링 될 때마다");
//위의 console.log()와 같이 기본 렌더링 될 때마다 실행됨
useEffect(() => { console.log("렌더링 될 때마다 | useEffect"); });
return (
<>
<button onClick={ clickCount }>Count Button</button>
<div>{count}</div>
</>
);
}
위의 코드를 실행한다고 하였을 때, "기본 렌더링 될 때마다"와 "렌더링 될 때마다 | useEffect"의 차이점은 뭘까?라는 의문점이 들었습니다.
알아본 결과, useEffect는 컴포넌트 렌더링의 부수 효과, 즉 컴포넌트의 렌더링이 완료된 이후에 실행됩니다.
반면에 직접 실행인 "기본 렌더링 될 때마다"는 렌더링 도중에 실행되는 차이점이라고 볼 수 있습니다.
위의 포스터는 제 개인적인 견해이므로, 부족한 부분이나 틀린 부분이 있다면 언제든지 편하게 댓글로 남겨주시면 감사하겠습니다 🙇🏻♀️ :)