React를 처음 접하는 개발자라면, 함수형 컴포넌트와 클래스형 컴포넌트의 차이, 그리고 상태 관리 방식에 대한 고민이 많을 것입니다.
과거에는 React에서 상태(state)를 관리하려면 클래스형 컴포넌트를 사용해야 했습니다. 하지만 코드가 길어지고, 재사용성이 떨어지는 문제가 있었습니다. 이를 해결하기 위해 React Hook이 등장하였으며, 함수형 컴포넌트에서도 상태 관리와 생명주기 메서드의 역할을 수행할 수 있도록 도와줍니다.
React Hook이 필요한 이유
- 더 간결한 코드: 클래스형 컴포넌트보다 코드가 직관적이고 짧아짐
- 가독성과 유지보수성 향상: 관심사 분리가 쉬워지고, 재사용성이 증가
- 부수 효과 관리가 용이: useEffect를 활용하여 사이드 이펙트 관리를 쉽게 수행 가능
백엔드 개발자의 입장에서 보면, Hook은 마치 Spring에서 AOP(Aspect-Oriented Programming)를 사용해 중복 코드 없이 관심사를 분리하는 것과 같은 개념이라고 생각하면 됩니다.
이번 글에서는 백엔드 개발자의 시선에서 React Hook을 이해하기 쉽게 설명하고, 실무에서 어떻게 활용할 수 있는지 살펴보겠습니다.
주요 React Hook 소개
[useState - 상태 관리]
useState는 컴포넌트 내부에서 상태(state)를 선언하고 변경할 수 있도록 도와줍니다.
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // 상태 선언
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>증가</button>
</div>
);
}
✅ useState는 Java에서 변수와 Setter 메서드를 사용하는 방식과 유사합니다.
하지만 React에서는 상태가 변경될 때마다 컴포넌트가 다시 렌더링된다는 차이점이 있습니다.
[useEffect - 부수 효과(Site Effect) 처리]
useEffect는 컴포넌트가 렌더링될 때 실행해야 하는 코드(데이터 가져오기, 이벤트 리스너 등록 등)를 처리하는 Hook 입니다.
import { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <p>타이머: {seconds}초</p>;
}
✅ useEffect는 Spring의 @PostConstruct 및 @PreDestroy와 유사합니다.
- @PostConstruct: 컴포넌트가 처음 렌더링될 때 실행 (useEffect의 초기 실행)
- @PreDestroy: 컴포넌트가 사라질 때 정리 (useEffect의 Cleanup)
[useMemo - 성능 최적화]
useMemo는 불필요한 연산을 방지하여 성능을 최적화할 때 사용됩니다.
import { useState, useMemo } from "react";
function ExpensiveCalculation({ num }) {
const squaredValue = useMemo(() => {
console.log("연산 수행 중...");
return num * num;
}, [num]); // num이 변경될 때만 다시 계산
return <p>계산 결과: {squaredValue}</p>;
}
✅ useMemo는 Java의 캐싱(Cache)과 비슷합니다.
useMemo를 활용하면 같은 입력값에 대해 불필요한 연산을 줄이고 캐싱된 값을 활용할 수 있습니다.
[useCallback - 함수 메모이제이션]
useCallback은 useMemo와 유사하지만, 함수의 참조값을 유지하여 불필요한 렌더링을 방지하는 Hook입니다.
import { useState, useCallback } from "react";
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount((prev) => prev + 1);
}, []);
return <button onClick={handleClick}>증가</button>;
}
✅ useCallback은 Spring의 Singleton 패턴과 비슷합니다.
[useRef - DOM 접근 & 상태 유지]
useRef는 컴포넌트의 상태를 변경하지 않고도 특정 값을 유지하거나, DOM 요소에 직접 접근할 때 사용됩니다.
import { useRef } from "react";
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>포커스 이동</button>
</div>
);
}
✅ useRef는 Java의 인스턴스 변수와 비슷한 역할을 합니다.
React Hook 비교 정리
Hook | 역할 및 목적 | 특징 | 예제 |
useState | 상태(state) 관리 | - 상태 값이 변경되면 컴포넌트가 다시 렌더링됨 - 초기값을 설정 가능 |
const [count, setCount] = useState(0); |
useEffect | 부수 효과 (Side Effect) 처리 | - API 호출, 이벤트 리스너 등록 등 비동기 작업 수행 - 의존성 배열을 설정 가능 ([]: 처음 한 번만 실행) |
useEffect(() => { fetchData(); }, []); |
useMemo | 연산 결과 캐싱 | - 불필요한 연산 방지 (성능 최적화) - 의존성 값이 변경될 때만 다시 계산됨 |
const result = useMemo(() => num * num, [num]); |
useCallback | 함수 메모이제이션 | - 함수의 참조값을 유지하여 불필요한 렌더링 방지 - useMemo와 유사하지만, 함수 자체를 캐싱 |
const handleClick = useCallback(() => setCount(c + 1), []); |
useRef | DOM 요소 접근 & 값 유지 | - 컴포넌트가 리렌더링되어도 값이 유지됨 - current 프로퍼티로 값 접근 가능 |
const inputRef = useRef(null); |
결론
React Hook은 함수형 컴포넌트에서 상태 관리와 부수 효과 처리를 쉽게 구현할 수 있도록 도와줍니다.
각 Hook의 활용 사례를 정리하면 다음과 같습니다.
- useState → 컴포넌트 내부의 상태 관리
- useEffect → 부수 효과 처리 (API 호출, 이벤트 리스너 등록 등)
- useMemo → 연산 결과 캐싱 (불필요한 재계산 방지)
- useCallback → 함수 메모이제이션 (불필요한 렌더링 방지)
- useRef → DOM 접근 및 값 유지
백엔드 개발자라면, React를 API 연동이 필요한 대시보드나 어드민 UI 개발에 활용할 때가 많을 것입니다.
Hook을 잘 활용하면 성능을 최적화하고 유지보수하기 쉬운 코드 작성이 가능하므로, 실무에서도 유용하게 사용할 수 있습니다!
'React' 카테고리의 다른 글
Spring Boot&React에서 새로 고침 404 오류 해결 방법 (1) | 2025.01.15 |
---|