React는 현대 웹 개발에서 널리 사용되는 JavaScript 라이브러리입니다. React의 핵심 개념 중 하나는 상태(state)와 라이프 사이클 관리입니다. 전통적으로, React 컴포넌트에서는 클래스 컴포넌트를 사용하여 상태를 관리하고 라이프 사이클 메서드를 구현했지만, React 16.8부터 도입된 Hooks는 함수형 컴포넌트에서 상태 관리와 라이프 사이클을 쉽게 처리할 수 있도록 해줍니다.
React Hooks는 상태 관리와 컴포넌트 생애 주기를 훨씬 간편하게 처리할 수 있도록 돕습니다. 기존의 클래스 컴포넌트 방식에 비해 코드가 간결하고, 상태를 관리하는 데 있어 더 직관적인 방법을 제공합니다. 이번 포스트에서는 React에서 제공하는 대표적인 Hook들을 다루고, 실제로 어떻게 활용할 수 있는지에 대해 설명하겠습니다.
1. useState: 상태 관리
React에서 상태를 관리하는 가장 기본적인 Hook은 useState
입니다. 이 Hook은 함수형 컴포넌트에서 상태를 선언하고, 해당 상태를 업데이트할 수 있는 기능을 제공합니다. 사용법은 매우 간단하며, 다음과 같이 사용할 수 있습니다.
<pre><code>import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>증가</button>
</div>
);
}
</code></pre>
위 코드에서 useState(0)
는 count
라는 상태 변수를 선언하고, 이를 초기값 0으로 설정합니다. setCount
는 이 값을 변경하는 함수로, 버튼 클릭 시 상태 값이 변경됩니다. 이를 통해 컴포넌트에서 동적인 상태 변화를 관리할 수 있습니다.
2. useEffect: 사이클 관리 및 부수 효과 처리
useEffect
는 컴포넌트가 렌더링된 후에 실행되는 부수 효과(side effects)를 처리하기 위해 사용됩니다. 데이터 fetching, 이벤트 리스너 설정, 구독(subscription) 등의 작업을 처리할 때 유용하게 쓰입니다. 기본적인 사용법은 다음과 같습니다:
<pre><code>import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []); // 빈 배열을 두 번째 인수로 전달하면 컴포넌트가 마운트될 때만 실행됩니다.
return (
<div>
{data ? <p>{data}</p> : <p>로딩 중...</p>}
</div>
);
}
</code></pre>
위 코드에서 useEffect
는 컴포넌트가 마운트될 때마다 API 요청을 보내고, 받은 데이터를 상태로 업데이트합니다. 두 번째 인수로 빈 배열을 전달하면, 이 효과는 컴포넌트가 처음 마운트될 때만 실행됩니다.
3. useContext: 글로벌 상태 관리
useContext
는 React에서 컨텍스트(Context)를 사용하여, 컴포넌트 트리 전반에 걸쳐 데이터를 전달할 때 유용합니다. useContext
를 사용하면, props를 통해 데이터를 전달하는 대신, 전역적으로 데이터를 공유할 수 있습니다.
<pre><code>import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedComponent() {
const theme = useContext(ThemeContext);
return <p>현재 테마: {theme}</p>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedComponent />
</ThemeContext.Provider>
);
}
</code></pre>
위 코드에서 useContext
를 사용하여, ThemeContext
에서 제공하는 값을 ThemedComponent
에서 쉽게 사용할 수 있습니다. 이를 통해 복잡한 컴포넌트 트리 구조에서 props를 통해 값을 전달하지 않고도 필요한 데이터를 가져올 수 있습니다.
4. useRef: DOM 참조 및 값 유지
useRef
는 함수형 컴포넌트에서 DOM을 참조하거나 값의 변화를 추적할 때 사용됩니다. useRef
는 상태와는 달리, 값을 변경하더라도 컴포넌트를 리렌더링하지 않습니다. 이를 통해 성능 최적화와 DOM 참조를 효율적으로 처리할 수 있습니다.
<pre><code>import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleFocus}>포커스</button>
</div>
);
}
</code></pre>
위 코드에서 useRef
는 input
요소를 참조하여, 버튼을 클릭할 때 해당 요소에 포커스를 줄 수 있습니다. 이는 DOM 요소를 직접 조작하는 데 유용합니다.
5. 커스텀 Hook: 코드 재사용
React에서 자주 사용하는 로직을 커스텀 Hook으로 만들면 코드 재사용성을 높일 수 있습니다. 예를 들어, 로컬 스토리지에 데이터를 저장하고 불러오는 로직을 커스텀 Hook으로 만들 수 있습니다.
<pre><code>import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
const setValue = (value) => {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
};
return [storedValue, setValue];
}
</code></pre>
이렇게 커스텀 Hook을 사용하면, 로컬 스토리지에 데이터를 저장하고 불러오는 기능을 여러 컴포넌트에서 재사용할 수 있습니다.
결론
React Hooks는 상태 관리와 라이프 사이클 관리를 혁신적으로 변화시킨 기능입니다. 함수형 컴포넌트에서도 상태를 관리하고, 부수 효과를 처리하며, 글로벌 상태를 손쉽게 다룰 수 있습니다. useState
, useEffect
, useContext
, useRef
와 같은 기본적인 Hook들은 React 개발에서 필수적인 도구입니다. 또한, 커스텀 Hook을 활용하면 코드의 재사용성과 유지 보수성을 크게 향상시킬 수 있습니다. React Hooks를 잘 활용하면 더욱 간결하고 효율적인 코드를 작성할 수 있으며, React 애플리케이션의 성능과 품질을 향상시킬 수 있을 것입니다 :)