리액트를 사용하다보면 상태변수의 값이 변하지 않았는데도 다시 렌더링이 되는 상황을 맞이하곤 한다. (다른 상태변수의 변화 등으로 인해) 이러한 불필요한 리렌더링을 막아주고, 성능을 최적화해줄 수 있는 Hook이 있다-! 그거슨 바로 'useEffect'
이왕이면 무엇이 렌더링이 되나 보는 것도 신경써주는 것도 중요하지만, 리렌더링하는 횟수를 최대한 줄여주도록 노력하는 것 또한 개발자로서 중요한 작업이 될 것이다. 그렇다면 useEffect에 대해,, 알아보자-!
side Effect는 우리가 알고 있듯이 '부작용'이라는 의미를 담고 있다. 프로그래밍에서의 side Effect는 조금 다르다. '나쁘다' '좋지 않다'의 의미를 품고 있기보다는 그냥 현상 자체를 말할 때 side Effect라는 표현을 쓴다!
컴퓨터 과학에서 함수가 결과값 이외에 다른 상태를 변경시킬 때 'side effect'이 있다고 말한다.
그러니까 정확히 어떤 상황에서?🤔
input이나 output에 아무런 영향도 미치지 않을 때
input, output 외에 다른 값을 조작하는 경우도 포함한다.
👉 즉 렌더링이 아니고 외부 세계에 영향을 주는 어떠한 행위
👉 더 쉽게 말하면 렌더링을 제외한 다른 모든 행위
예시를 들어보자
const addNum = 10
const sumNum = num => {
return num + addNum }
위의 sumNum 함수는 side effect가 있을까?
return num + addNum
이 부분 자체가 side effect라고 말할 수 있다. addNum이라는 외부의 값을 가져와서 조작했기 때문!
또다른 예시!
const variable = 10
const sumVar = (num) => {
variable = 20; // 외부의 값을 조작 - side effect
return num + 1 }
variable = 20;
가 외부의 값을 조작했기 때문에 side effect로 볼 수 있다.
더 구체적으로는 크게 세가지의 예로 나눌 수 있다.
✔️ Data fetching, (외부 데이터를 조작하므로)
✔️ dom에 직접 접근 (ex. Event listener -외부의 DOM에 접근 하는 것이므로)
✔️ 구독(setInterval) - (시간의 흐름을 계속해서 관찰한다)
✔️ rendering을 막는다. - 코드를 순차적으로 실행시킬 때 side effect다음 렌더링이 있는 경우 side effect를 먼저 실행 시키는 것
✔️ 매 랜더링마다 실행된다.
이러한 Side Effect의 단점을 보완하기 위해 "useEffect"를 사용할 수 있다.
useEffect(()=>{}, [])
useEffect(side effect를 실행시키는 함수, 의존성 배열)
useEffect는 콜백함수와 의존성 배열을 인자로 받는다.
이 useEffect는 기존의 side effect와 달리 'rendering 되고나서 ' callback function 을 실행시켜 준다. 👉 rendring 쓸 데 없이 지연시킬 일이 없음. side effect의 단점을 보완시켜준다.
useEffect안에 들어가는 인자값을 조금만 자세히 보자면,
useEffect(Arg1, Arg2)
Arg1 callback function : side effect를 실행시키는 함수
Arg2 dependancy array : array 안에 있는 값이 바뀔 때만 effect를 실행한다.
👉 즉 두번째 인자에 '어떠한 상태값'이 들어가냐에 따라 첫번째 인자에 있는 함수가 실행될지 말지가 결정되는 것이다. 그렇기에 두 번째 인자를 '의존성'배열 이라고 부르는 것!
예를 들자면
useEffect(()=>{ console.log(“quiz”)}, [count,input])
위의 console.log('quiz')는 count나 input 상태변수의 값이 하나라도 변한다면 다시 실행된다.
만약, useEffect 두번째 인자에 아무것도 안넣어주면 렌더링 될때마다 실행된다.
ex)
useEffect(()=>{ console.log(“quiz”)})
두번째 인자에 아무 것도 넣어주지 않았기 때문에 side effect의 기본값 그대로 렌더링 될 때마다 실행된다.
또, 페이지가 load될 때 한번만 함수를 실행시킬 수도 있다.
ex)
useEffect(()=>{ console.log(“quiz”), []})
위 의존성 배열은 빈 배열[]의 형태로 어떠한 상태값도 들어가 있지 않기 때문에 처음에 페이지가 로드 되었을 때 한번만 함수가 실행이 된다.
Clean up : effect를 clean up 하다 (구독과 같은 경우는 항상 clean up을 해줘야한다)
effect를 clean up 해준다는 게 무슨 의미일까?
setInterval을 예로 들어보자면
function interval(){
Const id = setInterval(()=> console.log(“1 second”), 1000);
return () => {
clearInterval(id)}}
useEffect(interval)
위 interval이라는 함수는 interval를 멈추는 함수를 return함으로써 effect를 clean up 한다.
함수가 종료되는 시점에 기존의 side effect를 멈춰주는 새로운 함수를 return함으로써 다른 컴포넌트로 옮겨갔을 때 자동으로 interval 함수가 불필요하게 실행되지 않게끔 해준다.
핵심만 기억하자-! ⭐️👉 useEffect안에 들어간 콜백함수가 return하는 함수는 그 콜백함수가 사라지는 시점에 return하는 것이다!
지금 만들고 있는 웹사이트(위스타그램)에서 fetch 사용하는 경우 이외에 또 useEffect 써줄 수 있는 구간을 한 번 찾아봐야겠다,, 보여지는 화면 뿐만 아니라 코드도 깔끔하게, 성능도 최적화된(!!!!) 웹사이트 구현할 수 있는 개발자가 되고 싶다---!!