비제어 컴포넌트(Uncontrolled Component)와 제어 컴포넌트(Controlled Component)
제어 컴포넌트 (Controlled Component)
React의 state가 입력 값을 관리하는 방식으로 useState나 useReducer 등의 state를 사용해 값이 변경될 때마다 UI를 업데이트한다.
특징
- 입력값이
state에 저장되며,onChange를 통해 값이 업데이트됨 - React가 폼 입력의 현재 값을 완전히 제어함
- UI의 값이 state를 통해 단방향으로 흐름
- 폼 데이터를 쉽게 검증하고 관리 가능 (ex:
onChange에서 유효성 검사 적용 가능)
예제
import { useState } from "react";
const ControlledInput = () => {
const [text, setText] = useState("");
return (
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)} // React 상태 업데이트
/>
);
};
장점
- 입력 값이 state에 저장되므로, 유효성 검사와 로직을 쉽게 추가 가능
- 입력 값 동기화가 React 상태와 일치하여 유지보수가 쉬움
- Formik, react-hook-form 같은 라이브러리와 쉽게 통합 가능
단점
- 입력이 많아질수록 state 업데이트가 많아져 성능 저하 가능성
- 단순한 폼에서도 state와
onChange처리가 필요하여 코드가 길어질 수 있음
비제어 컴포넌트 (Uncontrolled Component)
React의 state가 아닌, DOM 자체가 값을 관리하는 방식이다. React에서 제공하는 ref를 사용해 필요할 때 DOM에서 값을 직접 가져온다.
ref를 사용하는 이유는 React에서 사용하는 ref의 경우 리렌더링을 유발하지 않기 때문에 렌더링 과정에서의 성능적 이점을 누릴 수 있다.
특징
useRef를 사용하여 DOM 요소를 직접 조작함value와onChange없이<input>자체의 내부 상태를 활용- 필요할 때만
ref.current.value를 통해 값을 읽음 - 브라우저의 기본 폼 동작을 활용 가능
예제
import { useRef } from "react";
const UncontrolledInput = () => {
const inputRef = useRef<HTMLInputElement>(null);
const handleSubmit = () => {
if (inputRef.current) {
alert(`입력 값: ${inputRef.current.value}`);
}
};
return (
<>
<input type="text" ref={inputRef} />
<button onClick={handleSubmit}>Submit</button>
</>
);
};
장점
- 입력값을 실시간으로 반영할 필요가 없을 때 성능이 좋음
- 간단한 폼에서 불필요한 state 업데이트를 줄일 수 있음
- React 외부 라이브러리(jQuery, D3 등)와 통합이 쉬움
단점
- React가 입력값을 관리하지 않으므로 유효성 검사나 동적 업데이트가 어렵다
useRef로 값에 접근해야 하므로 라이브러리를 사용하지 않는다면 코드가 더 드러워질 수 있다