<< 학습 목표 >>
1. 컴포넌트가 마운트, 언마운트 될 때 리엑트가 컴포넌트를 어떻게 관리하는지 설명할 수 있다.
2. useEffect 훅을 사용해 컴포넌트가 언마운트 될 때 호출될 함수를 지정할 수 있다.
전 글 ( https://codingaja.tistory.com/80 ) 을 작성하다가 한가지 전혀 생각지 못핸 현상을 발견했음
발견한 현상을 간략히한 코드를 보자
프로젝트 -> src -> chapter03 -> Component16.jsx 를 추가하고 아래 코드를 추가하자
import React, { useState, useEffect } from 'react';
function Component16() {
const [ click, setClick ] = useState(0);
setInterval(function() {
console.log("interval");
}, 1000);
return(
<div>
<button onClick={() => { setClick(click+1) }}>클릭</button>
</div>
);
}
export default Component16;
위 코드는 setInterval을 사용해서 1초에 한번씩 console 패널에 "interval" 을 출력하고 버튼을 클릭하면 setter 함수를 사용해 click 변수의 값을 하나씩 증가시키고 있음
위 컴포넌트를 출력해서 확인 해보자
위 컴포넌트를 출력하고 개발자 모드를 열어 [ console ] 패널을 보자
우선 console 패널에 "interval" 이 두 번씩 출력되는 이유는 전 글에서 설명했음
만약 왜 두 번씩 출력되는지 모르겠다면 전 글을 다시 읽어보자
출력된 컴포넌트에서 [ 클릭 ] 버튼을 여러 번 클릭해보자
그러면 "interval" 이 마구 출력되는걸 볼 수 있음

아무것도 클릭하지 않고 가만히 있을때는 1초에 두번씩 "interval" 이 출력되는데 버튼을 클릭하면 왜 여러번 출력될까?
이는 리엑트가 컴포넌트를 생성하는 방식 때문에 생기는 현상임
리엑트는 컴포넌트 내 변화가 생기면 기존의 컴포넌트에 변화를 주는게 아니라 기존의 컴포넌트를 버리고 변화된 새로운 컴포넌트를 만듬

우리가 페이지에 막 들어갔을 때 click 변수의 값이 0인 컴포넌트가 만들어지면서 setInterval이 등록됨
그리고 그 컴포넌트를 아이디가 root인 div에 출력함
화면에 출력된 Component16이 갖고 있는 [ 클릭 ] 버튼을 클릭하면 useState 훅이 동작해 Conponent16이 갖고 있는 click 변수의 값을 하나 증가시킴
그러나 리엑트는 현재 화면에 보여지고 있는 Component16의 click 변수의 값을 증가시키기는 방식이 아님
현재 컴포넌트(click 변수의 값이 0인 Component16)를 버리고 click 변수의 값이 1인 새로운 Component16을 만들어 현재 컴포넌트와 교체함

이 과정에서 기존의 컴포넌트가 등록한 setInterval이 멈추지 않고 그대로 동작하면서 새로운 컴포넌트의 setInterval도 함께 새로 등록되 setInterval이 두 번 등록되는 것
클릭을 한 횟수만큼 컴포넌트 교체가 이뤄지므로 그만큼 setInterval 로 등록하게 되는 것
setInterval이 많아지면 사용자의 컴퓨터가 처리해야할 setInterval의 수가 늘어나는 것이므로 사용자가 느끼는 사이트 내 속도가 굉장히 느려질 것
따라서 setInterval은 꼭 필요한 경우에만 사용해야하거나 아예 사용하면 안됨
그럼 setInterval이 필요한 상황에서는 어떻게 해야할까?
그래서 존재하는 것이 훅임
setInterval을 위해서 훅이 나온건 아니지만 setInterval을 대체해서 사용할 수 있는 훅들이 있음
또는~ useEffect 훅을 사용하면 컴포넌트가 마운트 됬을 때만 함수가 동작하도록 할 수 있으니 useEffect 훅을 사용하면 클릭 시 setInterval이 마구 등록되는 문제를 해결할 수 있음

이렇게 리엑트에서 setInterval을 사용해야한다면 useEffect 를 사용해서 등록하는 것이 좋음
이 문제를 더 잘 이해할 수 있는 컴포넌트들을 마지막으로 알아보자
프로젝트 -> src -> Component18.jsx 를 추가 하고 아래 코드를 추가하자
import React, { useEffect } from 'react';
function Component18() {
useEffect(() => {
setInterval(() => {
console.log("Component18 마운트됨");
}, 1000);
}, []);
return(
<div>
<p>안녕하세요~!</p>
</div>
);
}
export default Component18;
프로젝트 -> src -> Component17.jsx 를 추가하고 아래 코드를 추가하자
import React, {useState} from 'react';
import Component18 from './Component18';
function Component17() {
const [isShow, setIsShow] = useState(false);
const [btnText, setBtnText] = useState("보이기");
let toggle = () => {
if(isShow) {
setBtnText("보이기");
} else {
setBtnText("감추기");
}
setIsShow(!isShow);
}
return(
<div>
<button onClick={toggle}>{btnText}</button>
{
isShow && <Component18 />
}
</div>
);
}
export default Component17;
그리고 Component17을 화면에 출력하자
[ 보이기 ] 버튼이 보이는데 이 버튼을 클릭하면 Component18이 보이게됨

이 글의 위에서 이미 설명했는데 [ 보이기 ] 버튼을 눌렀을 때 컴포넌트가 보이는 이유는 뭘까?
잘모르겠다면 이 글을 다시 처음부터 읽어보자
리엑트를 이해하는데 굉장히 중요하고 지금까지는 당연하듯 코딩해왔던 부분을 뻥! 뚫어 줄 수 있는 내용을 설명했음
Component17은 맨 처음 아래와 같은 상황임
Component17의 isShow 변수는 false, btnText 변수는 "보이기" 를 갖고 있는 상황이므로 [ 보이기 ] 버튼이 보여지고 있는 상황이고 버튼 바로 밑으로는 조건부 렌더링을 설정해뒀는데 isShow 변수의 값이 false이므로 Component18이 안보이는 상황

위와 같은 상황에서 [ 보이기 ] 버튼을 클릭하면 toogle 함수가 동작하면서 btnText 변수의 값은 "감추기"로 바뀌고 isShow 변수의 값은 true 로 바뀜
이 글에서 컴포넌트의 변수 값이 바뀌면 어떻게 된다? 바뀐 값을 갖고 있는 새로운 컴포넌트를 만든다~!
그 후 기존의 컴포넌트는 버리고 새로운 컴포넌트로 교체한다~!

isShow 변수의 값은 true, btnText 변수의 값은 "감추기" 인 새 컴포넌트가 만들어지는데 이때 button 태그의 텍스트는 감추기 로 조건부 렌더링은 isShow 변수의 값이 true이므로 Component18 컴포넌트 또한 만들어지면서 Component17이 새로운 Component17로 교체됨

이때 Component18이 만들어지면서 setInterval 을 등록하기 때문에 콘솔에 1초에 한번씩 "Component18 마운트됨" 이라고 출력됨
이번에는 [ 감추기 ] 버튼을 클릭해보자
그랬을 때 어떤 현상이 발생한다? 새로운 컴포넌트로 컴포넌트 교체 현상이 발생함

여기까지 제대로 이해했다면 [ 감추기 ], [ 보이기 ] 버튼을 여러 번 클릭했을 때 "Component18 마운트됨" 이 여러번 출력되는게 자연스러운 현상임
만약 "왜? 감추기 버튼을 누르면 Component18이 사라지니까 setInterval도 사라지는거 아닌가?" 라는 생각이 들면 다시 이 글의 처음부터 보고와야함
만약 다시 처음부터 보고 왔는데도 "왜?" 라는 생각이 들면 더 여러번 다시 보고 그래도 "왜?" 라면 [ 소플의 처음 만난 리액트 ] 책을 보고 오자
Component17의 [ 보이기 ], [ 감추기 ] 버튼을 클릭을 계속 하다보면 "Component18 마운트 됨" 이 여러번 출력되는데 이건 어떻게 해결할 수 있을까?
Component17의 [ 보이기 ], [ 감추기 ] 버튼을 클릭을 계속 하다보면 "Component18 마운트 됨" 이 여러번 출력되는 이유 먼저 알아야함
Component18에는 setInterval을 등록하는 코드는 있지만 clearInterval 이 없어서 발생하는 문제
만약 setInterval, clearInterval을 모른다면 JS부터 먼저 공부하고 와야함
Component18이 만들어질 때 마다 setInterval이 등록은 되지만 Component18이 사라질 때 clearInterval을 해줘야하는 부분이 빠졌음
Component18이 사라질 때 clearInterval은 다음과 같이 할 수 있음

기존의 Component18과 바뀐 점을 비교해보면 다음과 같음
수정한 Component18에서는 setInterval로 등록하고 반환 받은 객체를 interval 변수에 저장함
그 다음 useEffect 훅 내에서 cleatInterval로 setInterval을 해제하는 함수를 반환하고 있음

이렇게 useEffect 훅에서 함수를 반환하면 컴포넌트가 언마운트 될 때(사라질 때) 반환한 함수가 호출됨
이를 사용해서 [ 보이기 ] 버튼을 누르면 Component18이 마운트 되며(보이며) setInterval로 등록하고 [ 감추기 ] 버튼을 누르면 Component18이 언마운트 되며(사라지며) clearInterval로 등록을 해제함
여기까지 useEffect 훅을 보면서 컴포넌트의 라이프 사이클에 대해서 알아봤음
setInterval 뿐만 아니라 여러 상황에서 발생하는 이해할 수 없는 문제를 해결 할 수 있는 내용이니 "setInterval을 이렇게 하는 거구나" 로 생각하지 말고 "useEffect 를 이렇게 활용하는구나" 로 넓게 생각해주기~!
'JS + React > React-Chapter03' 카테고리의 다른 글
| Chapter03. 리엑트 프로젝트 / 주소록 관리 (0) | 2023.04.01 |
|---|---|
| Chapter03. 리엑트 훅 / useRef 훅 (0) | 2023.04.01 |
| Chapter03. 리엑트 훅 / useEffect 훅 (0) | 2023.03.31 |
| Chapter03. 리엑트 훅 / useState 훅 익히기 / 조건부 렌더링 (0) | 2023.03.31 |
| Chapter03. 리엑트 훅 / useState 훅 기초 (0) | 2023.03.30 |