React는 사용자 인터페이스를 구축하기 위한 강력한 라이브러리로, 그 중심에는 컴포넌트의 생명주기(Lifecycle)가 있습니다. 생명주기는 컴포넌트가 생성되고 업데이트되고, 사라지는 일련의 과정을 의미합니다. 이 글에서는 클래스 컴포넌트와 함수형 컴포넌트의 생명주기 차이를 설명하고, 각 생명주기 메서드와 훅이 언제, 왜 사용되는지에 대해 깊이 있게 다뤄보겠습니다.
클래스 컴포넌트에서는 다양한 생명주기 메서드를 통해 컴포넌트의 상태 변화를 관리할 수 있습니다. 주요 메서드는 componentDidMount, componentDidUpdate, componentWillUnmount가 있습니다.
componentDidMount
실행 시점: 컴포넌트가 처음 렌더링된 후 한 번 실행됩니다. 즉, 컴포넌트가 화면에 나타난 직후 호출됩니다.
주요 사용 사례: 서버에서 데이터를 가져오거나, DOM을 직접 다뤄야 할 때 사용됩니다.
componentDidMount() {
// API 호출하여 데이터 가져오기
fetchData();
}
componentDidUpdate
실행 시점: 컴포넌트가 업데이트된 후에 실행됩니다. 주로 props나 state가 변경된 뒤 호출됩니다.
주요 사용 사례: 특정 상태나 props의 변경에 따른 추가 작업을 할 때 사용됩니다.
componentDidUpdate(prevProps, prevState) {
if (prevProps.value !== this.props.value) {
console.log('value가 변경됨');
}
}
componentWillUnmount
실행 시점: 컴포넌트가 사라지기 직전에 실행됩니다. 주로 컴포넌트가 더 이상 필요하지 않아 화면에서 제거되기 전 호출됩니다.
주요 사용 사례: 타이머나 이벤트 리스너 등 리소스를 해제하거나 정리할 때 사용됩니다.
componentWillUnmount() {
clearInterval(this.timer);
}
함수형 컴포넌트에서는 생명주기 메서드 대신 useEffect 훅을 사용해 생명주기를 관리합니다.
useEffect
는 의존성 배열에 따라 다양한 시점에 실행됩니다.
useEffect의 배열 형태에 따른 실행 시점 차이
useEffect(() => {
console.log('마운트 및 리렌더링마다 실행');
});
componentDidMount
와 유사한 역할을 합니다.useEffect(() => {
console.log('마운트될 때 한 번만 실행');
}, []);
componentDidUpdate
와 유사합니다.useEffect(() => {
console.log('value가 변경될 때만 실행');
}, [value]);
마운트, 언마운트, 리렌더링, 특정 상태값 변화
useEffect(() => { ... }, [])
형태로 마운트 시 실행할 작업을 지정합니다.useEffect
내부에서 클린업 함수를 반환하여 언마운트 시 실행할 작업을 지정합니다.useEffect(() => {
return () => {
console.log('컴포넌트 언마운트 시 실행');
};
}, []);
useEffect(() => { ... })
형태로 아무 배열도 주지 않으면 마운트와 모든 리렌더링 시마다 실행됩니다.useEffect(() => { ... }, [특정 값])
형태로 해당 상태나 props가 변경될 때만 실행되도록 합니다.의존성 배열이란?
useEffect
가 언제 실행될지를 결정하는 중요한 요소입니다. 배열 안에 있는 값이 변경될 때마다 useEffect
가 실행됩니다. 만약 배열이 빈 상태라면, 이는 컴포넌트가 처음 마운트될 때 한 번만 실행됨을 의미합니다.생명주기 함수는 다양한 상황에서 매우 유용하게 사용됩니다. 몇 가지 주요 사례를 통해 그 필요성을 설명해 보겠습니다.
서버에서 데이터 받아오는 경우
componentDidMount
나 useEffect
를 사용해 데이터를 가져오고 상태에 저장합니다.이벤트 핸들러를 사용하는 경우
window
나 document
에 이벤트 핸들러를 추가할 때는 마운트 시 핸들러를 등록하고, 언마운트 시 반드시 핸들러를 제거해야 합니다. 이렇게 해야 메모리 누수나 불필요한 이벤트 호출을 방지할 수 있습니다.useEffect(() => {
const handleResize = () => {
console.log('윈도우 크기 변경');
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
타이머 함수 사용하는 경우
setInterval
, setTimeout
)하는 경우, 컴포넌트가 언마운트될 때 해당 타이머를 해제해 줘야 합니다. 그렇지 않으면 타이머가 계속 동작해 불필요한 리소스를 사용하게 됩니다.클린업(Clean-up) 함수란?
React에서 컴포넌트의 생명주기를 이해하는 것은 컴포넌트의 상태와 동작을 효율적으로 관리하는 데 필수적입니다. 클래스 컴포넌트와 함수형 컴포넌트 각각의 생명주기 관리 방법을 이해하고 적절히 사용하면 코드의 유지보수성과 성능을 크게 향상시킬 수 있습니다. 특히 함수형 컴포넌트에서 useEffect
훅의 활용은 간결하고 직관적인 생명주기 관리를 가능하게 합니다.