React에서 상태(state)와 생명주기(lifecycle)를 다룰 때 가장 많이 사용하는 두 가지 Hook이 있습니다: useState & useEffect. 이 글에서는 이 두 Hook의 개념과 사용법을 정리하고, 홈페이지 코드에서 사용한 예시를 들어 이해를 돕겠습니다.
Hook이란?
Hook은 React 16.8에서 도입된 기능으로, 함수형 컴포넌트에서도 상태 관리와 생명주기 관련 기능을 사용할 수 있도록 해주는 함수입니다. 기존 클래스 컴포넌트에서 사용하던 this.state와 componentDidMount, componentDidUpdate 등의 기능을 대체할 수 있습니다.
대표적인 Hook에는 다음과 같은 것들이 있습니다:
- useState: 상태 관리
- useEffect: 부수 효과(side effect) 관리
- useContext: 전역 상태 공유
- useReducer: 복잡한 상태 로직 관리
UseState
useState는 컴포넌트의 상태를 관리하는 Hook입니다. 함수형 컴포넌트에서도 상태를 사용할 수 있도록 돕습니다.
import { useState } from React;
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p> 현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
- useState(초기값)을 호출하면 배열을 반환합니다.
- 첫 번째 요소: 현재 상태 값(count)
- 두 번째 요소: 상태를 업데이트하는 함수(setCount)
- setCount를 호출하면 컴포넌트가 리랜더링되어 새로운 값이 반영됩니다.
UseEffect
useEffect는 컴포넌트가 랜더링될 때 특정 로직을 실행할 수 있도록 하는 Hook입니다.
기본 사용법
import { useState, useEffect } from React;
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`현재 카운트: ${count}`);
};
return(
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
- useEffect 내부의 함수는 렌더링될 때 마다 실행됩니다.
- 위 코드에서 버튼을 클릭할 때마다 count가 변경되고, 컴포넌트가 리렌더링되면서 useEffect가 실행됩니다.
특정 값이 변경할 때만 실행 (의존성 배열 사용)
useEffect(() => {
console.log(`count가 변경됨: ${count}`);
}, [count]);
- 두 번째 인자로 의존성 배열([])을 전달하면, count가 변경될 때만 실행됩니다.
- 의존성 배열이 빈 배열인 경우, 처음 마운트가 실행될 때만 실행됩니다.
정리(cleanup) 함수 사용
useEffect(() => {
const interval = setInterval(() => {
console.log("1초마다 실행");
}, 1000);
return () => {
clearInterval(interval);
console.log("컴포넌트가 언마운트됨");
};
}, []);
- useEffect 내부에서 return 문을 사용하면 언마운트 시 실행할 정리 함수를 지정할 수 있습니다.
- 위 예제에서는 setInterval을 설정한 후, 컴포넌트가 제거될 때 clearInterval을 호출하여 메모리 누수를 방지할 수 있습니다.
메모리 누수란?
프로그램이 사용한 메모리를 제대로 해제하지 않아서 불필요한 메모리가 계속 쌓이는 현상을 의미합니다.
Genie95 프로젝트에서 쓰인 예제
import { useState, useEffect } from 'react';
function Desktop({ onClose }) {
const { openModal, closeModal } = useModal();
const [notepadOpened, setNotepadOpened] = useState(false);
const [isMobile, setIsMobile] = useState(window.innerWidth < 850);
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 850);
};
window.addEventListener("resize", handleResize);
setNotepadOpened(!isMobile);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [isMobile]);
return (
<div>
<p>현재 상태: {notepadOpened ? "메모장 열림" : "메모장 닫힘"}</p>
</div>
);
}
- isMobile 상태를 useState로 관리하여, window.innerWidth의 변경을 반영할 수 있도록 합니다.
- useEffect에서 window.addEventListener("resize", handleResize) 추가하여 화면 크기가 변경될 때 isMobile 상태를 업데이트합니다.
- 정리(cleanup) 함수 추가하여 컴포넌트가 사라질 때 resize 이벤트 리스너를 제거하여 메모리 누수를 방지합니다.
정리
useState | 컴포넌트의 상태를 관리 |
useEffect | 사이드 이펙트(예: API 호출, 이벤트 리스너) 관리 |
언제 사용해야 할까?
- useState: 사용자의 입력, UI 상태 관리 등 동적인 데이터를 다룰 때
- useEffect: API 호출, 구독(subscription) 관리, DOM 변경 효과 적용 등
React의 useState와 useEffect를 잘 이해하면 함수형 컴포넌트를 더욱 효율적으로 사용할 수 있습니다.
'Projects' 카테고리의 다른 글
[Genie95] #5. React Props란? (0) | 2025.04.03 |
---|---|
[Genie95] #2. React 기반 프론트엔드 개발의 장점은? (1) | 2025.03.07 |
[Genie95] #1. AWS EC2 기반 포트폴리오 웹사이트 구축 & 자동 배포 과정 (0) | 2025.03.03 |
[Genie95] #0. Windows95 테마 포트폴리오 웹사이트 만들기 (1) | 2025.02.28 |