결론부터 말하고 가자면 React에 의해서 값이 제어되는 컴포넌트를 제어 컴포넌트, React에 의해서 값이 제어되지 않는 컴포넌트를 비제어 컴포넌트라고 한다.
우리는 form
이나 input
요소를 다룰 때, 요소에 입력되는 값을 state로 관리하거나 DOM API를 통해서 관리할 수 있다. state로 DOM element의 값을 다루는 컴포넌트가 제어 컴포넌트, 후자가 비제어 컴포넌트이다. 이 둘은 코드에서 어떻게 다른지 input
요소를 다루는 예시 코드를 통해 살펴보자.
import React, { useState } from 'react';
function MyInput() {
const [inputValue, setInputValue] = useState(null);
const handleChange = (e) => {
setInputValue(e.target.value);
};
return <input onChange={(e) => handleChange(e)} value={inputValue} />;
}
위 코드는 input
의 값을 state로 관리하고 사용자가 값을 입력할 때마다 handleChange
를 통해 state 값을 업데이트 해주는 제어 컴포넌트이다. 제어 컴포넌트는 React, Real DOM, 사용자가 보는 화면을 동기화해줘야하는 번거로움이 있다.
import React, { useRef } from 'react';
function Test() {
return <MyInput />;
}
function MyInput() {
const inputNode = useRef(null);
return <input ref={inputNode} />;
}
export default MyInput;
위 코드는 input
의 값은 사용자만이 상호작용할 수 있고, 우리는 필요한 시점에 이벤트 핸들러를 통해 ref
에 저장된 엘리먼트의 값을 가져와 활용하는 비제어 컴포넌트이다. 비제어 컴포넌트는 state로 값을 관리하지 않기 때문에 값이 업데이트할 때마다 리렌더링이 되지 않기 때문에 성능상의 이점이 있다.
비제어 컴포넌트는 DOM에 신뢰 가능한 출처를 유지하므로 비제어 컴포넌트를 사용할 때 React와 non-React 코드를 통합하는 것이 쉬울 수 있다. 빠르고 간편하게 적은 코드를 작성할 수 있지만, 그 외에는 일반적으로 제어된 컴포넌트를 사용해야 한다.
아래 사진을 통해 제어 컴포넌트가 할 수 있는 것과 비제어 컴포넌트가 할 수 있는 것을 비교해보고 상황적으로도, 기능적으로도 비제어 컴포넌트로 충분하다면 비제어 컴포넌트를 고려해보자.