이 글에서는 각각의 React의 Hook이 무엇인지, 장단점, 사용 예시, 그리고 어떤 상황에서 사용하는 것이 적절한지 자세히 설명하겠습니다.
useState는 함수형 컴포넌트에서 상태를 관리하는 기본적인 Hook입니다. 이 Hook을 사용하면 상태 값을 선언하고 그 값을 업데이트할 수 있는 함수를 얻을 수 있습니다.
const [count, setCount] = useState(0);
useState는 두 개의 값을 반환하는데, 첫 번째는 상태 값(count), 두 번째는 그 상태를 변경할 수 있는 함수(setCount)입니다.
useEffect는 사이드 이펙트(Side Effect)를 관리하는 Hook입니다. 사이드 이펙트는 컴포넌트가 렌더링된 후에 발생해야 하는 작업으로, 네트워크 요청, DOM 업데이트, 또는 외부 API 호출과 같은 작업이 포함됩니다.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
위의 예시에서는 count 값이 변경될 때마다 document.title이 업데이트됩니다.
컴포넌트가 마운트, 언마운트될 때 또는 특정 상태나 props가 변경될 때 발생하는 사이드 이펙트를 처리할 때
비동기 작업이나 이벤트 리스너 설정, 데이터 페칭 등
useRef는 DOM 요소 또는 어떤 값에 대해 변경을 감지하지 않으면서도 참조할 수 있는 값을 저장하는 데 사용됩니다. useRef로 만든 객체는 리렌더링 시에도 유지되며, 값이 바뀌어도 컴포넌트를 다시 렌더링하지 않습니다.
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
위의 예시에서는 useRef를 통해 DOM 요소를 참조하여 focus 메서드를 실행하고 있습니다.
useMemo는 메모이제이션(Memoization)된 값을 반환하는 Hook입니다. 이 값은 컴포넌트가 리렌더링될 때 특정 의존성 배열(Dependency Array)이 변경되지 않는 한 다시 계산되지 않습니다. 이를 통해 불필요한 계산을 피하고 성능을 최적화할 수 있습니다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
위의 코드는 a와 b가 변경될 때만 computeExpensiveValue 함수를 호출하여 그 결과를 다시 계산합니다. 만약 a와 b가 변경되지 않았다면, 이전에 계산된 값을 그대로 사용합니다.
useReducer는 상태 업데이트 로직이 복잡하거나 여러 상태가 상호작용하는 경우에 유용한 Hook입니다. 상태와 이를 업데이트하는 로직을 컴포넌트 외부에서 분리하여 재사용할 수 있습니다.
const [state, dispatch] = useReducer(reducer, initialState);
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
useContext는 부모 컴포넌트에서 자식 컴포넌트로 Props를 전달하는 대신, 전역적으로 상태를 관리하고 전달할 수 있는 Hook입니다. 이를 통해 컴포넌트 트리 전반에 걸쳐 데이터를 공유할 수 있습니다.
const value = useContext(MyContext);
useLayoutEffect는 useEffect와 유사하지만, 차이점은 렌더링 이후 화면이 그려지기 전에 실행된다는 점입니다. 이 Hook은 DOM이 업데이트된 직후에 실행되므로 화면에 표시되는 것에 즉각적으로 영향을 미치는 작업을 수행할 때 유용합니다.
코드 복사
useLayoutEffect(() => {
// DOM 조작 및 레이아웃 관련 작업
}, []);
useCallback은 함수의 메모이제이션을 제공하는 Hook입니다. 이 Hook은 특정 의존성이 변경되지 않는 한 동일한 함수 객체를 반환하여, 불필요한 함수 재생성을 방지합니다.
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
React의 Hook은 모두 서로 다른 목적으로 컴포넌트 성능과 동작을 최적화하는 데 중요한 역할을 합니다. 각각의 Hook은 적절한 상황에서 사용할 때 매우 유용하며, 사용 목적과 상황에 맞게 선택하는 것이 중요합니다.
Hook | 목적 | 장점 | 단점 | 사용 예시 |
---|---|---|---|---|
useState | 간단한 상태 관리 | 간단한 상태 관리 가능 | 상태 관리가 복잡해지면 적합하지 않음 | 클릭 카운터, 입력 필드 관리 |
useEffect | 사이드 이펙트 처리 (렌더 후 동작) | 컴포넌트의 라이프사이클 동안 다양한 작업 처리 가능 | 의존성 관리가 복잡할 수 있으며, 메모리 누수 가능성 있음 | 데이터 페칭, 이벤트 리스너, 타이머 설정 등 |
useRef | 참조 값 관리 (렌더링에 영향 없음) | 렌더링에 영향을 주지 않고 값 참조 가능 | 값 변경에 리액티브하지 않음 | DOM 요소 접근, 이전 값 저장 등 |
useMemo | 계산된 값 메모이제이션 | 불필요한 계산을 방지하고 성능 최적화 | 지나친 사용은 오히려 복잡성을 증가시킬 수 있음 | 복잡한 계산, 정렬된 리스트 등 |
useReducer | 복잡한 상태와 액션 관리 | 복잡한 상태 관리에 적합, 상태 로직 분리 가능 | 초기 설정이 복잡할 수 있음 | 복잡한 폼, 쇼핑 카트 관리 |
useContext | 전역 상태 관리 | 전역 상태를 쉽게 공유 가능 | 리렌더링 최적화 어려움 | 테마 설정, 사용자 인증 상태 |
useLayoutEffect | DOM이 그려지기 전 작업 수행 | 화면 그리기 전에 작업을 실행할 수 있음 | 렌더링 지연 가능 | 레이아웃 관련 작업, DOM 조작 |
useCallback | 함수의 메모이제이션 | 불필요한 함수 재생성을 방지하여 성능 최적화 | 과도한 사용은 성능 저하로 이어질 수 있음 | 이벤트 핸들러, 자식 컴포넌트에 props로 전달하는 함수 |