특징/기준 | 제어 컴포넌트 (Controlled Component) | 비제어 컴포넌트 (Uncontrolled Component) |
---|---|---|
개념 | React의 **상태(state)**가 폼 요소의 값을 직접 제어하고 업데이트한다. 폼 요소 값은 항상 React 상태와 동기화된다. | 폼 요소가 DOM을 가지고 값을 관리한다. React는 값을 단순히 읽어오기만 한다. |
값의 근원 | React state (useState 등으로 관리한다) | DOM 자체 (HTML 요소의 value 속성이다) |
값 변경 방식 | onChange 이벤트 핸들러를 통해 React 상태를 업데이트하고, 이 상태가 다시 폼 요소의 value로 반영된다. | 사용자의 입력으로 폼 요소의 DOM 값이 직접 변경된다. |
데이터 흐름 | 단방향 데이터 흐름: 상태 변경 -> UI 업데이트로 예측 가능하고 추적하기 쉽다. | 폼 요소의 DOM 값과 React 상태가 분리되어 있어 데이터 흐름이 불분명할 수 있다. |
구현 방법 | value prop에 React 상태를 바인딩하고, onChange prop에 상태를 업데이트하는 함수를 연결한다. | defaultValue prop으로 초기값을 설정하고, useRef 등을 사용하여 폼 제출 시 DOM에서 직접 값을 읽어온다. |
장점 | - 모든 입력에 대한 즉각적인 제어: 실시간 유효성 검사, 조건부 버튼 활성화, 입력 마스킹 등을 쉽게 구현한다. - 쉬운 디버깅: 상태만 확인하면 폼의 현재 값을 알 수 있다.- 일관된 동작: 모든 폼 요소가 동일한 방식으로 React 상태에 의해 관리된다. | - 구현이 간단하다: 특히 초기값이 필요 없거나, 값을 읽는 시점이 중요하지 않을 때 코드가 더 짧을 수 있다. - 외부 라이브러리 연동이 편하다: DOM 직접 접근이 필요한 서드파티 라이브러리와 연동하기 쉬울 수 있다. |
단점 | - 더 많은 코드가 필요하다: 각 입력 필드마다 useState와 onChange 핸들러를 설정해야 한다. - 불필요한 리렌더링 가능성: 모든 키 입력마다 컴포넌트가 리렌더링될 수 있다. (하지만 React는 이를 효율적으로 처리한다.) | - 실시간 유효성 검사가 어렵다: 값을 실시간으로 제어하기 어렵다. - 데이터 추적 및 디버깅이 어렵다: 폼의 현재 상태를 알기 위해 DOM에 직접 접근해야 한다. - React의 강점 활용이 제한된다: React의 상태 관리 및 데이터 흐름 철학을 제대로 활용하지 못한다. |
주요 사용처 | - 대부분의 React 폼 개발: 복잡한 폼, 실시간 피드백이 필요한 폼에 사용한다. - React의 상태 관리 로직과 긴밀하게 연동해야 할 때 사용한다. | - 간단한 단일 입력 필드: 초기값을 한 번만 설정하고 제출 시에만 값이 필요한 경우에 사용한다. - 파일 입력 (<input type="file">)과 같이 DOM 자체의 동작이 더 중요한 경우에 사용한다. - React 외의 DOM 기반 라이브러리와 함께 사용할 때 고려한다. |
onChange
: 입력 필드(input, textarea, select)의 값이 변경될 때마다 발생
onSubmit
: 폼 전체가 제출될 때 발생
onClick
: