[React] useRef와 상태 끌어올리기 (#09-2)
[React] useRef와 상태 끌어올리기 (#09-2)
📍 연관 포스팅
Github
서론
입력 폼에서 데이터를 가져올 때, 모든 키 입력마다 상태를 업데이트하는 대신 “저장” 버튼을 누르는 시점에만 값을 읽어오고 싶다면 Ref 사용하자
-> 왜냐면 상태 변화를 계속 팔로업할 필요가 없으니까..
사실 useState로도 구현 가능하지만 왜 useRef를 사용해야할까?
useState 와 useRef의 차이
| 비교 항목 | useState (제어 컴포넌트) | useRef (비제어 컴포넌트) |
|---|---|---|
| 리렌더링 | 값이 바뀔 때마다 발생 (매 키입력 시) | 발생하지 않음 |
| 실시간 검사 | 가능 (글자 수 제한, 입력 즉시 경고 등) | 불가능 (버튼을 누르는 시점에만 확인 가능) |
| UI 동기화 | 입력값에 따라 UI가 즉시 변함 | 저장 전까지 UI 변화 없음 |
| 추천 상황 | 복잡한 유효성 검사, 실시간 피드백 필요 시 | 단순한 데이터 수집, 성능 최적화 필요 시 |
1. useRef를 이용한 입력값 수집
useState를 쓰면 코드가 복잡해질 수 있는 상황에서 useRef를 사용하면 DOM 요소에 직접 접근하여 필요할 때만 값을 가져올 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { useRef } from 'react';
const title = useRef();
const description = useRef();
const dueDate = useRef();
function handleSave() {
const enteredTitle = title.current.value;
const enteredDescription = description.current.value;
const enteredDueDate = dueDate.current.value;
// 수집된 데이터를 상위 컴포넌트로 전달
onAdd({
title: enteredTitle,
description: enteredDescription,
dueDate: enteredDueDate
});
}
2. 커스텀 컴포넌트에 Ref 전달하기 (forwardRef)
내장 HTML 태그(input, textarea)가 아닌 커스텀 컴포넌트에 ref 속성을 넘기려면 React의 forwardRef를 사용해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { forwardRef } from 'react';
const Input = forwardRef(function Input({ label, textarea, ...props }, ref) {
return (
<p>
<label>{label}</label>
{textarea ? (
<textarea ref={ref} {...props} />
) : (
<input ref={ref} {...props} />
)}
</p>
);
});
forwardRef로 감싼 컴포넌트는 두 번째 인자로ref를 전달받으며, 이를 내부의 실제 DOM 요소에 연결할 수 있다.
3. 상태 끌어올리기: App에서 데이터 관리
생성된 프로젝트 데이터는 사이드바와 상세 화면 모두에서 필요하므로, 가장 공통 분모인 App 컴포넌트에서 상태를 관리한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// App.jsx
function handleAddProject(projectData) {
setProjectsState(prevState => {
const newProject = {
...projectData,
id: Math.random() // 간단한 ID 생성
};
return {
...prevState,
projects: [...prevState.projects, newProject] // 기존 배열 복사 후 새 프로젝트 추가
};
});
}
// ...렌더링 부분
<NewProject onAdd={handleAddProject} />
4. 입력 타입 최적화 (Date Picker)
사용자로부터 정확한 날짜 형식을 받기 위해 input의 type 속성을 활용한다.
1
2
3
<Input type="text" ref={title} label="Title" />
<Input textarea ref={description} label="Description" />
<Input type="date" ref={dueDate} label="Due Date" />
type="date"를 설정하면 브라우저 내장 데이트 피커(Date Picker)가 활성화되어 편리하게 날짜를 선택할 수 있다.
💡 요약 및 핵심 포인트
- Ref vs State: 실시간 유효성 검사가 필요 없다면
useRef가 렌더링 최적화와 코드 간결성 면에서 유리하다. - forwardRef: 커스텀 컴포넌트를 설계할 때 외부에서 제어할 수 있도록
forwardRef를 적용하는 습관을 들이자. - 불변성 유지: 상태 배열을 업데이트할 때는
[...prevState.projects, newProject]와 같이 기존 데이터를 복사하여 불변성을 지켜야 한다.
5. 데모
다음 단계: 데이터 저장 로직은 완성되었다. 다음에는 입력값이 비어있을 때 경고를 띄우는 유효성 검사(Validation)와 모달(Modal) 창 구현 방법을 알아보자.
This post is licensed under
CC BY 4.0
by the author.

