본문 바로가기
FE/React

controlled components vs uncontrolled components 란

by Jiyoon-park 2022. 11. 11.

controlled, uncontrolled(=제어, 비제어 컴포넌트) 그게 뭐지? 처음 들어봐~라고 할 수 있지만, 용어 상에서 오는 낯설음일 뿐이지 우리 대부분은 이미 알고 있고 사용해본 적도 있을 것이다.

uncontrolled components

개발을 하면서 흔하디 흔하게 작성하는 form의 구성요소들을 생각해보자. input이나 textarea, select 같은 태그들이 떠오를 텐데, 요 dom 태그들에 ref를 주고 해당 ref의 current에 접근해서 값을 꺼내오거나/본 적이 있는가?

const MyComponent = () => {
  const inputRef = useRef<HTMLInputElement | null>(null)
​
  return (
    <div>
      <input ref={inputRef} />
      <button onClick={() => console.log(inputRef.current.value)}/>
    </div>
  )
}

이런식으로 따로 상태값을 외부에서 주입해주지 않은 채로, dom 내부에 상태값을 사용하는 것을 비제어 컴포넌트(uncontrolled component)라고 한다.

 

`왜 비제어 컴포넌트라고 부를까?`라고 물음표가 머릿속에 떠오른다면, React 입장에서 생각해보자. React는 상태값에 예민하게 반응하는 친구이다. 컴포넌트 내의 상태값의 변화를 감지하고 리렌더링 된다. 하지만 위의 컴포넌트들처럼, dom 내부에 상태값이 숨어져있다면, react는 상태값의 변화를 감지할 수도 상태값을 제어할수도 없다. 그렇기에 `비제어-제어되지 않는다`는 말로 표현하는 것이 아닐까. 하고 이해했다.

 

controlled components

그렇다면 react에서 상태값의 변화를 감지하고 제어하는 제어 컴포넌트는 뭐지? 라고 한다면, 우리가 정말 흔하게 쓰는 요론 패턴- 컴포넌트 내에 상태값과 상태값을 변화시키는 액션을 정의해주고, 해당 값을 넘겨준다. 요게 conrolled components로 쓰이는 모습이다. useEffect로 inputValue의 변화를 감지하면 매번의 입력마다 입력값이 감지될 것이다.

const MyComponent = () => {
  const [inputValue, setInputValue] = useState<string>('');
​
  return (
    <div>
      <input value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
      <button onClick={() => console.log(inputValue)}/>
    </div>
  )
}

react docs에서는 unconrolled components에 대한 설명의 머릿글에서 대부분의 상황에서 controlled components를 사용할 것을 권장하고 있다. ㅎ 엥 그러면 unconrolled components는 언제 사용하는 걸까? 사용함으로써 얻을 수 있는 이점은 뭘까나? 생각이 든다. 질문에 답을 내려보자면, uncontrolled components은 React는 상태값이 변할 시에 리렌더링이 되는데, unconrolled component로 사용할 때에는 상태값 변화가 감지되지 않아 리렌더링이 되지 않아 성능상의 이점을 챙겨갈 수 있다. 더불어 상태값이나 상태를 변화하는 change action을 따로 선언하는 번거로움이 없음도 장점이다. 🙇

 

 

결론

controlled components와 uncontrolled components는 요구 조건에 맞게 상황 따라 사용하자~,

예를 들어 form validation에는 두가지 케이스가 있을 수 있다. 실시간으로 validation을 하는 경우와, form을 제출했을 때 validation을 하는 경우.

 

케이스) 인풋에 숫자가 아닌 값이 들어오면 바로 error message를 띄워주고 싶다면, react가 상태값을 바로 감지할 수 있게 controlled component를 사용해야 한다.

바이케이스이다) 인풋에 모든 입력값들이 입력되고, 폼을 제출할 시에 한꺼번에 validation이 일어났으면 좋겠다면, 폼 제출시의 인풋 값만 알면 되니까 uncontrolled component를 사용하면 된다.