Hook은 함수형 컴포넌트에서도 상태 관리와 생명주기 기능을 사용할 수 있도록 해주는 기능이다.
React의 Hook들을 하나씩 상세하게 정리해보려고 한다.
● 우선 리액트 Hook이란?
- 함수형 컴포넌트에서 상태와 라이프사이클을 관리할 수 있게 해주는 기능
- 주요 포인트
- useState로 상태 관리
- useEffect로 라이프사이클 제어
- useMemo,UseCallback으로 성능 최적화
- useContext,useReducer 등 다양한 Hook 사용 가능
● State란?
state는 컴포넌트가 가지고 있는 동적인 데이터
사용자 인터랙션, 네트워크 응답 등으로 인해 바뀔 수 있는 값을 저장해두는 React 내부의 기억 장소이다
예를 들어서
const [count, setCount] = useState(0);
- count라는 상태를 만들고
- setCount를 통해 상태를 변경하면
- 컴포넌트는 자동으로 리렌더링돼서 바뀐 값을 화면에 보여주는 로직이다.
● LifeCycle이란?
lifecycle은 컴포넌트가 생겨나고(render), 업데이트되며, 사라지는전 과정의 흐름을 말한다.
| 단계 | 설명 | 예시 |
| Mount | 컴포넌트가 처음 화면에 나타남 | API 호출, 초기 설정 |
| update | 상태 또는 props 변경으로 컴포넌트가 다시 렌더링 | count가 바뀔 때 |
| Unmount | 컴포넌트가 사라질 때 | 타이머 정리,이벤트 해제 |
예를 들어서
useEffect(() => {
console.log("마운트 or 업데이트 됨");
return () => {
console.log("언마운트 됨");
};
}, []);
- 마지막에 붙는 [] 배열을 의존성 배열이라고 한다
- 이 배열 안에 있는 값이 변경될 때만 useEffect를 다시 실행해준다.
- 컴포넌트가 마운트됨 → "마운트 or 업데이트 됨" 출력됨
- 컴포넌트가 언마운트됨 → "언마운트 됨" 출력됨
이제 hook과 state,lifecycle의 개념을 이해했으니 Hook을 더 자세하게 공부해 보도록 하겠다.
[9] 필수 리액트 Hook(훅)
🧩 1. useState – 상태(state) 저장하기
정의
컴포넌트 내부에서 상태 값을 선언하고 관리할 수 있게 해주는 Hook.
렌더링을 유발하며, 함수형 컴포넌트에서 가장 자주 사용된다.
함수 컴포넌트에서는 state라는 것을 제공하지 않기 때문에 useState() 훅을 사용해야함
문법
const [state, setState] = useState(initialValue);
- 첫 번째: 현재 상태값
- 두 번째: 첫 번째 상태를 업데이트하는 함수
- 상태를 직접 수정하는 것이 아니라, 상태 업데이트 함수를 호출하여 상태를 변경한다.
- 이렇게 초깃값을 넣어 호출하면 return값 ==> 배열 나옴
예제
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // count,setCount : getter,setter 개념으로 이해했음
const increment = () => {
// 잘못된 예시
count = count + 1;
// 올바른 예시
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
export default Counter;
★ 그런데 여기서 setCount 함수가 count를 증가시켜주는데 그럼 useState의 역할이 뭔지 로직이 헷갈렸음
- React에게 이 컴포넌트 안에 count라는 상태를 만들 건데, 초기값은 0 라고 알려줌
- 그러면 React는 이 상태를 컴포넌트 내부적으로 저장하고 관리하기 시작한다.
- setCount를 실행하면 React가 내부적으로 저장한 값을 변경함
- 그리고 자동으로 컴포넌트를 다시 렌더링해줌
- setCount()는 단순히 값을 바꾸는 게 아니라 "렌더링 요청"까지 포함된 함수인 것이다.
통합적 관리코드
import React, { useState } from "react";
function App() {
// 통합 상태 객체
const [state, setState] = useState({
score: 0,
name: "Alice",
});
const incrementScore = () => {
setState((prevState) => ({
...prevState,
score: prevState.score + 1,
}));
};
const changeName = () => {
setState((prevState) => ({
...prevState,
name: prevState.name === "Alice" ? "Bob" : "Alice",
}));
};
return (
<div>
<h1>점수: {state.score}</h1>
<button onClick={incrementScore}>Increase Score</button>
<h2>이름: {state.name}</h2>
<button onClick={changeName}>Change Name</button>
</div>
);
}
export default App;
특징
- 상태 변경 시 컴포넌트가 리렌더링된다.
- useState의 값은 비동기적으로 업데이트된다.
주의
- 상태는 직접 변경하지 않고 반드시 setState 함수를 사용해야 한다.
- 이전 상태를 기준으로 업데이트하려면 콜백 패턴 사용:
setCount(prev => prev + 1);
🧩 2. useEffect – 부수효과 처리 (데이터 fetch, 타이머 등)
정의
- 컴포넌트가 렌더링된 이후 또는 특정 상태가 변경될 때,
부수효과(side effect) 를 수행할 수 있도록 도와주는 Hook.
- 컴포넌트 생명주기 함수인componentDidMount(), componentDidUpdate(), componentWillUnmount 와 동일한 기능을 하나로 통합해서 제공
문법
useEffect(() => { // 실행 코드 return () => { // 클린업 코드 (옵션) }; }, [dependencies]);
예제
// componentDidMount, componentDidUpdate 를 대체합니다.
💫 처음 렌더링 될 때 + 리렌더링 될 때마다 실행
useEffect(() => {
console.log('useEffect 함수실행')
});
=> onChange 이벤트에 setState걸어서 확인해보기
💫 처음 렌더링 될 때만 실행
useEffect(() => {
console.log('useEffect 함수실행')
}, []);
💫 처음 렌더링 될 때 + 대괄호 안 값이 변할 때 실행
useEffect(() => {
console.log('useEffect 함수실행')
}, [state]);
// componentWillUnmount 를 대체합니다.
💫 useEffect에서 리턴하는 함수는 컴포넌트 언마운트시 호출됨
useEffect(() => {
console.log('useEffect 함수실행')
return() => {
// clean up 코드 작성
console.log('컴포넌트가 화면에서 사라질 때 실행 (자식컴포넌트가 부모컴포넌트에서 사라질 때 )');
}
}, []);
ex)
useEffect(()=> {
const time = setInterval(() => {
console.log('반복반복 setInterval')
}, 1000)
return() => {
clearInterval(time)
}
}, []);
함수형 컴포넌트 예제
import React, { useState, useEffect } from "react";
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
특징
- [] 의존성 배열이 비어 있으면 컴포넌트 마운트 시 1회만 실행된다.
- 반환 함수는 언마운트 시 클린업 용도로 실행된다.
주의
- 무한 루프를 막으려면 의존성 배열을 정확히 설정해야 한다.
- 상태(setState)를 useEffect 안에서 업데이트할 경우, 리렌더링이 발생한다.
🧩 4. useRef – DOM 접근 또는 값 기억
정의
- 렌더링 사이에도 값이 유지되며, 변경되어도 리렌더링을 유발하지 않는 mutable 객체를 반환한다.
주로 DOM 참조 또는 이전 값 저장에 사용된다.
- 특정 컴포넌트에 접근할 수 있는 객체를 의미한다.
문법
const ref = useRef(initialValue);
예제:
import React, { useRef, useState } from "react";
function App() {
const countRef = useRef(0);
const [renderCount, setRenderCount] = useState(0);
console.log("렌더링");
const increment = () => {
// 값을 바꿔도 렌더링이 일어나지 않음
countRef.current++;
console.log(`Count (useRef): ${countRef.current}`);
};
const triggerRender = () => {
setRenderCount(renderCount + 1);
};
return (
<div>
<p>Render Count: {renderCount}</p>
<button onClick={increment}>Increment useRef Count</button>
<button onClick={triggerRender}>Trigger Re-render</button>
</div>
);
}
export default App;
특징
- .current 속성을 통해 값을 읽고 쓸 수 있다.
- 값이 바뀌어도 컴포넌트는 리렌더링되지 않는다.
- 렌더링에 영향을 주지 않으면서 값을 저장하고 싶을 때 사용
변수,state,useRef의 차이
1. 변수 (let, const) – 함수 실행 중 잠깐 쓰는 값
특징
- 일반적인 자바스크립트 변수
- 컴포넌트 함수가 실행될 때마다 초기화됨
- 값이 바뀌어도 렌더링에 영향을 주지 않음
2. useState – 값 저장 + 렌더링까지 자동
특징
- React의 상태(state) 관리 도구
- 값이 바뀌면 컴포넌트가 자동으로 리렌더링
- 렌더링이 일어나도 이전 값을 유지한다.
3. useRef – 렌더링 안 일어나고 값은 기억됨
특징
- 값을 저장하되, 렌더링은 유발하지 않음
- .current 속성에 저장됨
- 렌더링 사이에서도 값 유지
- DOM 요소 참조 or 내부적으로 값 저장할 때 유용하다.
🧩 5. useMemo – 값 메모이제이션 (계산 최적화)
정의
- 계산 비용이 큰 연산의 결과를 메모이제이션(기억) 하여,
의존성 값이 변경될 때만 다시 계산한다.
문법
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- 의존성 배열에 있는 값이 바뀔때만 다시 계산한다.
- 계산된 결과가 저장되는 변수, 즉 캐시된 값 == memoizedValue
예제 : useMemo를 통해 최적화 구현해보기
import React, { useState, useMemo } from "react";
function App() {
const [number, setNumber] = useState(5);
const [text, setText] = useState("");
// 복잡한 계산을 수행하는 함수
const computeFactorial = (n) => {
console.log("Computing factorial...");
if (n <= 0) return 1;
return n * computeFactorial(n - 1);
};
// 1. useMemo를 사용하지 않은 경우
const factorialWithoutMemo = computeFactorial(number);
// 2. useMemo를 사용한 경우
const factorialWithMemo = useMemo(() => computeFactorial(number), [number]);
return (
<div>
<h1>Factorial Calculator</h1>
<p>
<strong>Without useMemo:</strong> Factorial of {number} is:{" "}
{factorialWithoutMemo}
</p>
<p>
<strong>With useMemo:</strong> Factorial of {number} is:{" "}
{factorialWithMemo}
</p>
<button onClick={() => setNumber(number + 1)}>Increment Number</button>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type something..."
/>
</div>
);
}
export default App;
특징
- 렌더링 최적화를 위해 불필요한 연산 방지
- 반드시 의존성 배열을 정확히 지정해야 한다
🧩 6. useCallback – 함수 메모이제이션
정의
- 함수를 메모이제이션하여 의존성 값이 바뀔 때만 새 함수를 생성하고,
그 외에는 이전 함수를 그대로 재사용한다.
- useCallback() 훅에서 파라미터로 받는 함수를 콜백이라고 부른다.
- 의존성 배열에 있는 변수 중 하나라도 변경되면 메모이제이션된 콜백함수를 반환한다.
문법
const memoizedCallback = useCallback(
() => {
doSomething(의존성 변수1, 의존성 변수2);
},
[의존성 변수1, 의존성 변수2],
);
- memo대신 이 hook을 쓰는 이유는?
- react에서 자식 컴포넌트에게 함수를 props로 넘길 때, 함수가 매번 새로 만들어지면
- 자식이 불필요하게 리렌더링될 수 있기 때문이다.
예제
import React, { useEffect, useState, useCallback } from "react";
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
// 해당 함수가 메모이제이션되어 의존성배열에 추가한 값이 바뀔 때만 함수가 호출된다.
const getCount = useCallback(() => {
console.log("getCount:", count);
return;
}, []);
useEffect(() => {
console.log("getCount 함수가 변경될 때 호출");
}, [getCount]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount((prev) => prev + 1)}>증가</button>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type something..."
/>
</div>
);
}
export default App;
특징
- 자식 컴포넌트에 props로 함수를 넘길 때 렌더링 최적화에 유용
- React.memo() 와 함께 사용하면 효과 극대화
- 자식컴포넌트에 props가 변하면 리렌더링됨
본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 (B-log) 리뷰로 작성 되었습니다.
'카카오클라우드 AIaaS 교육 > 클라우드 어플리케이션 개발' 카테고리의 다른 글
| [스나이퍼팩토리] AIaaS 마스터 클래스 8주차 DAY 35 - react (0) | 2025.05.19 |
|---|---|
| [스나이퍼팩토리] AIaaS 마스터 클래스 8주차 DAY33 - react (0) | 2025.05.13 |
| [스나이퍼팩토리] AIaaS 마스터 클래스 8주차 DAY32 - js 심화 (2) (0) | 2025.05.13 |
| [스나이퍼팩토리] AIaaS 마스터 클래스 7주차 DAY31 - js 심화 (0) | 2025.05.09 |
| [스나이퍼팩토리] AIaaS 마스터 클래스 6주차 DAY2 - html (2) | 2025.04.30 |