제어 컴포넌트와 비제어 컴포넌트
개요
리액트는 <input>
, <textarea>
, <select>
와 같이 입력받을 수 있는 HTML 폼 요소들을 제어 컴포넌트와 비제어 컴포넌트 두 가지의 개념으로 구분하고 있다.
이 글에서는 제어, 비제어 컴포넌트가 무엇인 지 소개하고 상황에 따라 어떻게 사용해야 적절한 지 소개하며 글을 마친다.
제어 컴포넌트와 비제어 컴포넌트
제어 컴포넌트란?
리액트에서 사용자의 입력을 받고자 해봤다면 아래와 같은 코드를 보고 다음과 같이 생각할 수 있을 것이다.
“이 input 요소의 값은 count일 것이고, 변경이 발생할 때마다 handleChange가 호출되겠구나.”
만약 value
와 onChange
속성이 없다면 당연히 위와 같은 생각을 할 수 없을 뿐더러 이후 어떠한 값이 될 지 알 수 없다.
또한 사용자가 값을 바꿀 경우 호출되는 이벤트 핸들러 함수 handleChange
에서 count
에 대한 작업을 해줘야만 값이 변경되므로 count
에 대한 작업을 하지 않을 경우에는 입력 폼 요소의 값이 그대로 유지된다는 것을 확신할 수 있다.
이 상황은 마치 입력 폼 요소가 이벤트 핸들러 외에 다른 누군가에 의해 변경될 수 없도록 제어하고 있는 것 같다.
이렇게 입력 폼 요소의 value
속성을 지정하여 값을 제어할 수 있는 컴포넌트를 제어 컴포넌트라고 한다.
비제어 컴포넌트란?
위 제어 컴포넌트의 개념과 반대로 생각하면 쉽다. 입력 폼 요소의 value
속성을 제어하지 않는 것이다.
이러한 경우 별도의 value
속성을 지정해주지 않았으므로 화면에는 DOM에 저장된 데이터 값이 나타내진다
자바스크립트에서 document.getElementById('id').value
를 통해 볼 수 있는 그 값이다.
value
속성을 제어하진 않더라도 기본값을 지정해주고 싶은 경우에는 리액트에서 제공하고 있는 defaultValue
, defaultChecked
속성을 통해 해결할 수 있으며 default...
속성은 이후 값이 바뀌더라도 화면에는 반영되지 않는다.
둘 중 어느 것을 사용하도록 해야하는가?
당연한 답변이겠지만 제어 컴포넌트를 사용하도록 해야하며 리액트 공식 문서에서도 다음과 같이 말하고 있다.
“대부분 경우에 폼을 구현하는데 제어 컴포넌트를 사용하는 것이 좋습니다.”
이 말은 단순히 값을 제어하고 사용할 수 있도록 하기 위함을 넘어서 리액트의 핵심 개념이 담겨져 있다.
리액트의 핵심 원칙 중 하나는 단일 진실 공급원 이며 모든 데이터 요소를 한 곳에서만 제어하도록 하는 설계이다.
이 원칙은 리액트 공식 문서 중 State 끌어올리기 에서 재차 강조되고 있는 원칙이며 읽어볼 것을 추천한다.
완전한 해결책
리액트 공식 문서에서는 유효성 검사, 방문한 필드 추적 및 폼 제출 처리와 같은 완벽한 해결을 원한다면 Formik 이 대중적인 선택 중 하나라고 소개하고 있다.
참고
- https://ko.reactjs.org/docs/forms.html
- https://ko.reactjs.org/docs/uncontrolled-components.html
- https://ko.reactjs.org/docs/lifting-state-up.html
- https://itnext.io/controlled-vs-uncontrolled-components-in-react-5cd13b2075f9
- https://fjorgedigital.com/insights/blog/the-philosophy-of-react-a-single-source-of-truth/