Controlled vs Uncontrolled — 폼 입력 다루기
이 토픽을 마치면
React에서 input을 다루는 두 가지 방식의 차이를 이해하고, 상황에 맞게 선택할 수 있게 됩니다.
HTML의 기본 동작
HTML의 input은 자체적으로 값을 관리합니다:
<input type="text" />사용자가 입력하면 input 자체가 값을 보관합니다. JavaScript가 관여하지 않아도 동작합니다.
React에서는 이 값을 React가 관리할지, input이 스스로 관리하게 둘지 선택합니다.
Controlled: React가 관리
function SearchBox() {
const [query, setQuery] = useState("");
return (
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
);
}value를 state로 지정하고, onChange로 state를 업데이트합니다. 사용자가 타이핑할 때마다:
- onChange 이벤트 발생
- setQuery로 state 변경
- 리렌더링
- input에 새 값 반영
React가 input의 값을 통제합니다. 그래서 "Controlled"입니다.
장점: 입력값에 대한 완전한 제어. 실시간 유효성 검사, 입력 제한, 포맷팅이 가능합니다.
function PhoneInput() {
const [phone, setPhone] = useState("");
const handleChange = (e) => {
const cleaned = e.target.value.replace(/\D/g, "");
if (cleaned.length <= 11) {
setPhone(cleaned);
}
};
return <input value={phone} onChange={handleChange} />;
}숫자만 입력되고 11자리를 넘길 수 없습니다.
Uncontrolled: DOM이 관리
function FileUpload() {
const inputRef = useRef(null);
const handleSubmit = () => {
const file = inputRef.current.files[0];
console.log(file.name);
};
return (
<div>
<input type="file" ref={inputRef} />
<button onClick={handleSubmit}>Upload</button>
</div>
);
}ref로 DOM 요소에 직접 접근해서 값을 읽습니다. React state를 거치지 않습니다. input 자신이 값을 관리하고, 필요할 때만 읽습니다.
파일 input은 보안상 value를 프로그래밍으로 설정할 수 없어서, uncontrolled로 쓸 수밖에 없습니다.
선택 기준
Controlled를 쓸 때:
- 실시간 유효성 검사 (이메일 형식 확인, 글자 수 제한)
- 입력값에 따라 다른 UI를 즉시 보여줘야 할 때
- 여러 input의 값을 하나의 state로 관리할 때
- 폼 제출 전에 데이터를 가공해야 할 때
Uncontrolled를 쓸 때:
- 파일 업로드
- 값을 제출 시점에만 읽으면 될 때
- 기존 HTML 폼을 React로 마이그레이션할 때
대부분의 경우 Controlled가 기본 선택입니다. React 공식 문서도 Controlled를 권장합니다.
핵심
Controlled 컴포넌트는 React state가 input 값을 관리합니다. 실시간 제어가 가능합니다. Uncontrolled 컴포넌트는 DOM이 값을 관리하고, ref로 필요할 때 읽습니다. 대부분의 폼에서 Controlled가 기본 선택입니다.