-
728x90
생명주기 (Life Cycle)이란?
일반적으로 생명주기라는 건 인간의 생애주기처럼 탄생부터 죽음까지 타임라인을 단계별로 나누어놓은 것을 말한다.
리액트 컴포넌트의 라이프사이클은 간단히 말하면 컴포넌트가 생성되고 제거되는 과정을 말하며
크게 Mount, Update, Unmount로 나눌 수 있다.
- Mount: 탄생. 컴포넌트가 화면에 렌더링 됨
- Update: 변화. 컴포넌트가 리렌더 됨
- Unmout: 죽음. 컴포넌트가 화면에서 제거됨
이 과정을 좀 더 자세하게 알아보기 위해 카운터 앱을 만들어보자!
import { useState, useEffect } from "react"; function App() { // useState 훅을 사용해서 count 상태와 그 값을 업데이트 하는 setCount 함수 생성 const [count, setCount] = useState(0); // useEffect 훅을 사용해서 컴포넌트가 마운트되거나 업데이트될 때마다 호출 useEffect(() => { console.log(count); }, [count]); const handleClickButton = () => { setCount(count + 1); }; return ( <div> <p>{count}</p> <button onClick={handleClickButton}>증가</button> </div> ); } export default App;
useEffect는 두 가지 인자를 받는데 첫 번째 인자는 원하는 동작을 수행하는 콜백함수, 두 번째는 의존성 배열로 의존성 배열에 있는 값 중 하나라도 변경되면 콜백 함수를 다시 실행시킨다.
그래서 의존성 배열에 있는 count의 변화를 감지해서 count가 변경될 때마다 콘솔에 해당 값을 출력하도록 설정했다.
그렇기 때문에 useEffect는 이 의존성 배열에 어떤 값을 넣어주느냐에 따라 동작이 달라진다라고 이해하면 되고, 값도 여러 개 넣을 수 있다.
근데 콘솔창에 가보면 count가 바뀌지 않았는데도 useEffct의 콜백함수가 실행되어 0이 찍혀있는데
이 App컴포넌트가 마운트 되어 useEffect가 한번 실행이 된다.
근데 이 과정은 굳이 useEffect를 사용하지 않아도 버튼을 클릭했을 때 콘솔에 count값을 출력하면 되지 않을까?
const handleClickButton = () => { setCount(count + 1); console.log(count); };
보는 것처럼 화면과 콘솔이 출력하는데 차이가 있는데 setCount 함수는 비동기로 동작한다.
그래서 버튼을 클릭해서 setCount함수를 호출 후 즉시 콘솔을 실행한다면 새로운 count값이 콘솔에 반영되지 않을 수 있다.
하지만 useEffect를 사용해서 count 값의 변화를 감지하고 있다면, count가 업데이트된 후에 실행이 되므로 항상 최신의 count값을 콘솔에 출력할 수 있다.
이제 위에서 컴포넌트의 라이프 사이클 Mount, Upadate, Unmount 이 3가지는 useEffect로 제어할 수 있다.
Update시 라이프 사이클 제어하기
useEffect(() => { console.log("업데이트"); });
컴포넌트가 업데이트될 때 어떠한 동작을 수행시키려면 위처럼 콜백함수만 전달하고 두 번째 인수를 생략하면 된다.
따라서 맨 처음 컴포넌트가 마운트 되었을 때와, 그 이후 버튼을 클릭해서 count가 증가가 되면 콘솔에 '업데이트'가 출력될 것
하지만 새로고침을 하면 업데이트가 되지 않았는데 마운트 되어 콘솔에 업데이트가 출력이 되는데 이걸 방지하고 싶다면,
useRef를 사용하면 된다.
const isMountRef = useRef(false); // 레퍼런스 객체 생성 (초기값 false) useEffect(() => { if (!isMountRef.current) { isMountRef.current = true; return; } console.log("업데이트"); });
useRef는 DOM요소를 참조하는 것 외에 값이나 상태를 저장할 때도 사용이 가능하다.
useEffect안에 조건문을 추가해서 isMountRef.current값이 false일 때 true로 바꿔주고 return 시키면
현재 isMount값이 false이기 때문에 true로만 변경하고 함수가 종료되면서 콘솔을 출력하지 않게 되면서 업데이트할 때만 콘솔에 출력할 수 있게 된다.
Mount시 라이프 사이클 제어하기
useEffect(() => { console.log("마운트"); }, []);
컴포넌트의 Mount는 두 번째 인수 의존성배열을 빈배열로 전달하면 된다.
이 뜻은 어떠한 값도 감지 하지 않는다를 의미하며 원래 useEffect는 의존성 배열에 들어간 값을 감지해서 값이 바뀌면 콜백함수를 실행하지만, 값이 아무것도 없으면 콜백함수를 한번 컴포넌트가 마운트 될 때만 실행되게 한다는 뜻
Unmount시 라이프 사이클 제어하기
Unmount는 컴포넌트가 제거가 되어야하기 때문에 count의 값이 짝수일 때 나타날 수 있게끔 Even 컴포넌트를 따로 만들어주었다.
// Even.jsx const Even = () => { return <div>짝수입니다.</div>; };
// App.jsx {count % 2 === 0 && <Even />}
count가 2로 나누었을 때 0으로 나누어 떨어진다면 짝수이기 때문에 참이면 Even 컴포넌트를 렌더링 하게 했다.
import { useEffect } from "react"; const Even = () => { useEffect(() => { return () => { console.log("언마운트"); }; }, []); return <div>짝수입니다.</div>; };
앞서 봤듯이 useEffect는 컴포넌트가 Mount 될 때 콜백함수를 실행할 수 있다.
근데 콜백함수내에 다시 함수를 반환하면 그 반환된 함수는 컴포넌트가 제거될 때 실행되며 이걸 클린업 함수라고 한다.
그리고 의존성배열에 빈 배열을 전달하면 컴포넌트가 Mount 될 때 한 번만 실행되어야하지만,
클린업 함수로 인해 컴포넌트가 제거될 때만 실행되게 된다.
'React, Next' 카테고리의 다른 글
[React] React Query(TanStack Query) 사용하기 (0) 2024.03.17 [React] React Hook Form 라이브러리 사용하기 (0) 2024.03.16 [React] Virtual DOM 이해하기 (0) 2024.02.27 [React] React로 카카오맵 API 사용하기 (0) 2024.01.27 [React] 올바른 초기값 설정하기 (0) 2024.01.17 댓글