React Hooks 정리

이규성·2025년 5월 9일
post-thumbnail

📌 Hook

Hook 사용시 함수 컴포넌트에서 state(상태)와 생명주기를 할 수 있게됩니다.

📌 useState

useState는 함수 컴포넌트에서 상태(state)를 관리하기 위해 사용하는 훅(hook)입니다.

리액트에서는 변수의 값이 변경되어도 화면이 자동으로 리렌더링되지 않습니다.
따라서 값을 상태로 관리하고, 변경할 때는 useState를 통해 업데이트해야 화면에 반영됩니다.

const [state, setState] = useState(initialState)

최적화 하기

useState를 효율적으로 사용하여 애플리케이션의 성능을 향상시키는 방법을 알아봅시다.

전개 연산자(...) 활용

setUser(prev => ({ ...prev, name: 'June' }));

이전 state를 안전하게 유지하면서 필요한 부분만 변경할 수 있습니다.


무거운 초기값 최적화하기

const heavy() => {
	return [1, 2];
}

const [number, setNumber] = useState(() => heavy());

초기값이 무거운 경우, 콜백 함수를 사용하여 최초 렌더링 시에만 실행되도록 최적화할 수 있습니다.

📌 useEffect

useEffect는 특정 시점에 원하는 작업을 수행할 수 있게 해주는 Hook입니다.

컴포넌트의 마운트, 업데이트, 언마운트 시점에 특정 코드를 실행할 때 유용하게 사용됩니다.

useEffect를 사용할 때 2가지 방식이 있습니다.

// 1. 기본 문법
useEffect( () => {작업} );

가장 기본적인 형태로, 콜백 함수를 인자로 받아, 컴포넌트가 렌더링될 때마다 실행됩니다.


// 2. 의존성 배열 사용
useEffect( () => {작업}, [의존성] );

두 번째 인자로 의존성 배열을 넣으면, 콜백 함수는 처음 렌더링될 때, 배열 안 값이 바뀔 때만 다시 실행됩니다. 만약 배열이 비어 있다면, 마운트 시에 한 번만 실행됩니다.

클린업 함수

useEffect에서 함수를 반환하면, 이 함수는 '클린업(정리) 함수'로 동작합니다.

useEffect( () => {
	작업
    return () => {
		작업 해제
	}
}, [의존성] );

클린업 함수는 컴포넌트가 언마운트(제거)될 때, 의존성이 변경되어 effect가 다시 실행되기 전에 정리 작업을 수행합니다.

클린업 함수와 최적화의 관계

클린업 함수는 React 애플리케이션의 성능 최적화와 깊은 관련이 있습니다:

  • 메모리 누수 방지: 이벤트 리스너, 타이머, 구독 등을 정리하지 않으면 컴포넌트가 사라질 때 메모리 누수가 발생할 수 있습니다.

  • 불필요한 동작 방지: 이전 effect의 영향이 새로운 effect에 간섭하는 것을 방지합니다.

📌 useRef

변수를 저장하고 관리할 수 있는 Hook입니다.

const inputRef = useRef(null);

useEffect(() => {
  inputRef.current.focus();
}, []);

return <input ref={inputRef} />;

useRef는 current 속성을 가진 변경 가능한 객체를 반환합니다.
useRef로 생성된 객체는 컴포넌트의 전체 생애주기 동안 유지됩니다.

useState vs useRef 차이점

1. DOM 요소에 접근

  • useRef를 사용하면 특정 DOM 요소에 직접 접근할 수 있습니다.
    예: 특정 input 요소에 초기값으로 포커스를 주는 경우

2.렌더링 여부

  • useState의 값이 변경되면 컴포넌트가 다시 렌더링됩니다.

  • useRef의 값이 변경되어도 컴포넌트가 렌더링되지 않습니다.
    컴포넌트가 리렌더링되어도 useRef의 값은 유지됩니다.

📌 useContext

useContext는 전역 데이터를 간편하게 가져올 수 있도록 해주는 Hook입니다.

const ThemeContext = createContext('light');

const App = () => {
  const [isDark, setIsDark] = useState(false);

  return (
    <ThemeContext.Provider value={{ isDark, setIsDark }}>
      <Page />
    </ThemeContext.Provider>
  );
};

const Page = () => {
  const { isDark } = useContext(ThemeContext);
  return <div>{isDark ? 'Dark Mode' : 'Light Mode'}</div>;
};

Props vs Context 차이점

1. 전달 방식

  • Props : 부모에서 자식으로 직접 데이터를 전달합니다.

  • Context : 컴포넌트 트리 안의 어떤 컴포넌트든 필요한 곳에서 데이터를 바로 사용할 수 있습니다.

2. 사용 목적

  • Props : 개별 컴포넌트 간 명확한 데이터 전달에 적합합니다.

  • Context : 테마, 사용자 정보, 언어 설정 등 전역 상태를 여러 컴포넌트에서 공유할 때 유용합니다.

꼭 필요할때만 사용하기

  • Context를 사용하면 컴포넌트 재사용성이 떨어집니다.
  • Prop drilling 을 피할 목적이면 Component Composition 을 고려하는게 좋습니다.

📌 useMemo

useMemo는 리렌더링 사이에 계산 결과 값을 캐싱해 주는 Hook입니다.

const cachedValue = useMemo(value, [의존성])

함수형 컴포넌트는 렌더링될 때마다 내부 변수와 함수가 새로 실행됩니다.
useMemo는 결과값을 기억해서, 의존성 배열의 값이 바뀌지 않는 한 재계산을 건너뜁니다.

주의점

1. 불필요한 사용 줄이기

  • useMemo는 메모리를 사용해서 값을 캐싱하므로, 단순한 값이나 가벼운 계산에는 오히려 성능이 나빠질 수 있습니다.

  • 꼭 무거운 연산이거나 렌더링마다 다시 계산되면 문제가 되는 경우에만 사용해야 합니다.

2. 상태 관리 도구가 아닙니다.

  • useMemo는 값을 저장하는 목적이 아니라, 계산 비용을 줄이기 위한 최적화 도구입니다.

  • 상태를 유지하거나 공유하려면 useState나 useContext 같은 전용 훅을 사용해야 합니다.

📌 useCallback

useCallback은 리렌더링 간에 함수 정의를 캐싱해 주는 Hook입니다.

const cachedFn = useCallback(fn, [의존성])

함수형 컴포넌트는 렌더링될 때마다 내부 변수와 함수가 새로 실행됩니다.
useCallback은 함수 정의를 기억해서, 의존성 배열의 값이 바뀌지 않는 한 재계산을 건너뜁니다.

📌 useReducer

useReducer는 컴포넌트에 reducer를 추가하는 Hook입니다.

const [state, dispatch] = useReducer(reducer, initialState);

useReducer는 다음 세 가지 핵심 요소로 구성됩니다

  • Dispatch : action을 발생시키는 함수입니다. action을 reducer에 전달하여 상태를 변경합니다.

  • Action : 상태를 어떻게 바꿀지를 설명하는 객체입니다. 일반적으로 type과 payload를 포함합니다.

  • Reducer : 상태를 업데이트하는 함수입니다. 현재 상태와 action을 받아서 새로운 상태를 반환합니다.

useState vs useReducer 차이점

1. 사용 목적

  • useState : 간단한 상태 관리에 적합합니다.
  • useReducer : 복잡한 상태 로직 관리에 적합합니다.

2. 상태 업데이트 방식

  • useState : 직접 상태를 설정합니다.
  • useReducer: reducer 함수에서 상태를 계산합니다.

📌 Custom Hooks

React를 사용하다 보면 비슷한 로직을 여러 컴포넌트에서 반복하게 되는 일이 많습니다. 이런 반복 코드를 줄이고 재사용성을 높이기 위해, 나만의 Hook(Custom Hook)을 만들어 사용할 수 있습니다.

// 커스텀 훅 생성
function useWindowWidth() { 
	//작업 
}
export default useWindowWidth;
// 커스텀 훅 사용
import useWindowWidth from "./useWindowWidth";

function MyComponent() {
  const width = useWindowWidth();
  return <p>너비는 {width}px 입니다.</p>;
}

주의점

커스텀 훅의 이름은 "use"로 시작하기.
일관성, 식별성, 자동 검사 기능이 제대로 작동하도록 하기 위해 반드시 "use"로 시작해야 합니다.
이 네이밍 규칙을 따르지 않으면 ESLint가 훅 규칙 위반을 감지하지 못하고, 이로 인해 예기치 않은 버그가 발생할 수 있습니다.

0개의 댓글