본문 바로가기

React

제어 컴포넌트 vs 비제어 컴포넌트

반응형

리액트로 폼을 다루는 방법은 크게 두 가지가 있다. 바로 제어 컴포넌트비제어 컴포넌트이다. 우테코 강의 시간에서도 두 방식에 대해 크루들과 코치들이 같이 논의하는 시간을 가졌던 기억이 있다. 그런데 그때에 잘 이해하지 못 한 부분이 많았어서 오늘 한 번 정리해보고자 한다.

참고로 나는 제어 컴포넌트를 선호하는 편인 것 같다 ㅎ ㅎ 이유는 흠,,,,아무래도 나는 리액트에서 ref의 사용을 지양하고자 하는 생각이 있어서 자연스레 제어 컴포넌트를 통해 폼을 구현하는 편인 것 같다.

 

HTML Form 엘리먼트는 그 자체가 내부에 상태를 가진다. 이 특성에 의해 폼을 다루는 두 가지 방법이 존재할 수 있다.

미리 정리해보면, 폼 엘리먼트가 가지는 상태를 그대로 사용하는 것이 비제어 컴포넌트이고, 중간에 React의 상태가 폼 제어에 관여하는 것이 제어 컴포넌트이다.

제어 컴포넌트

제어 컴포넌트에 대해서 리액트 공식문서는 다음과 같이 표현한다.

제어 컴포넌트는 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트합니다. React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트됩니다.

(중략)

이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 “제어 컴포넌트 (controlled component)“라고 합니다.

 

즉, 폼 엘리먼트를 리액트가 제어하는 방식으로 제어 컴포넌트는 동작한다. 제어 컴포넌트가 동작하는 순서는 다음과 같다.

 

  1. 사용자가 input element에 값을 입력한다.
  2. input element에 새로운 data가 입력될때마다(onChange가 발생할 때마다) setState를 통해 미리 정의한 state를 변경한다.
  3. input element의 value에는 변경된 state를 할당한다.
const [newStationName, setNewStationName] = useState('');

return(
  <form onSubmit={addStation}>
    <Input
      type="text"
      labelText="지하철 역 이름을 입력해주세요."
      value={newStationName}
      onChange={(event) => setNewStationName(event.target.value)}
    />
    <Button>추가</Button>
  </form>
);

 

위의 코드에서는 사용자가 어떤 값을 입력하게되면

 

onChange={(event) => setNewStationName(event.target.value)}

 

가 실행된다. 그리고 setter함수에 의해 newStationName가 변경되고, input의 value에는 newStationName이 할당된다.

 

제어 컴포넌트에서 input의 value는 React의 state에 의해 결정되는데, 이를 리액트 공식문서에서는 다음과 같이 표현한다.

React state는 신뢰 가능한 단일 출처 (single source of truth)가 됩니다.

비제어 컴포넌트

비제어 컴포넌트는 ref를 통해 form element에 접근한다. 따라서 기존의 바닐라 자바스크립트와 비슷하다. 만약 버튼을 눌러 submit 하는 상황이라면, submit 할 때 실행되는 함수 내에서 ref를 통해 form 내 value들에 접근한다.

 

const inputRef = useRef(); // ref 사용

const addStation = () => {
  const newStationName = inputRef.current.value;

  ...

};

return (
  <form onSubmit={addStation}>
    <Input
      type="text"
      labelText="지하철 역 이름을 입력해주세요."
      ref={inputRef}
    />
    <Button>추가</Button>
  </form>
);

제어 컴포넌트 vs 비제어 컴포넌트

내가 생각하기에 제어 컴포넌트와 비제어 컴포넌트의 가장 큰 차이점은 동기화이다.

 

제어 컴포넌트는 사용자가 입력할 때마다 state가 동기화된다. 따라서 input의 유효성 검사를 할 때 제어 컴포넌트가 용이하다. 항상 최신 값을 유지하는 특성에 따라 현재 input의 value가 유효한지 안 한 지에 대한 검사를 실시간으로 할 수 있다.

그러다 보니 사용자 입력 액션이 있을 때마다 리렌더링이 발생한다. 그리고 불필요한 단어를 입력했을 때도 값이 입력되고 state에 반영되는데, 이는 만약 실시간으로 api 요청을 하는 상황이었다면 자원의 낭비로 이어질 수 있다.

 

반면, 비제어 컴포넌트에서는 버튼을 누르는 최종적인 상황에서만 input의 value에 접근하므로 리렌더링이 계속해서 발생하진 않는다. 하지만 그만큼 비제어 컴포넌트는 사용자 입력의 가장 최신 값에 접근하기 힘들다는 특성이 있다.

 

 

아마 여태까지 내가 진행한 미션에서는 input의 value마다 유효성 검사를 하는 경우가 많았기 때문에 주로 제어 컴포넌트를 사용했던 것 같다. 무엇이 더 좋고 안 좋다 보다는, 나한테 주어진 상황에 따라 잘 판단하여 알맞은 방법으로 form을 다루는 게 가장 좋은 방법인 것 같다.

 

 

출처

https://ko.reactjs.org/docs/forms.html#controlled-components

https://velog.io/@yukyung/React-제어-컴포넌트와-비제어-컴포넌트의-차이점-톺아보기

반응형

'React' 카테고리의 다른 글

State vs Props  (0) 2021.06.22
Immutable이란?  (0) 2021.06.22
Key  (0) 2021.06.16
Virtual DOM  (0) 2021.06.15
명령형 프로그래밍 vs 선언형 프로그래밍  (0) 2021.06.12