제어 컴포넌트와 비제어 컴포넌트

5_wintaek·2025년 3월 25일
0

📌 들어가며

리액트를 개발하다 프로젝트에서 그룹생성 기능을 맡고 기능 개발을 하였습니다. 서버에서 get 해온 데이터를 렌더링하고 유저가 input 데이터를 입력하고 Form 제출을 서버에 put 요청을 보내는 작업이 많았었는데요.
저는 너무나 당연하게도 제어 컴포넌트(controlled)를 사용했습니다. 물론 input 태그가 엄청나게 많지는 않아서 이슈는 없었지만 리렌더링 관련된 생각이 나서 글을 정리하게 되었습니다.

📌 Form Tage Elements

제어,비제어 컴포넌트를 설명하기 앞서 Form Tage ELements를 설명하겠습니다.

대표적인 input,textarea,select 태그들이 있습니다. 사용자가 입력한 값에 대해서 그 값을 가쟈올 수 있는데 value Attribute 를 통해 값에 접근할 수 있습니다.

  • Value Attribute 라고 하면 Value Attribute를 통해 사용자가 입력한 값을 가져올 수 있습니다.
  • 즉 사용자가 입력한 값이 Value Attribute에 저장됩니다.
  • 이 Value Attribute 는 DOM에 속해있습니다.
  • 사용자가 입력한 값은 DOM 에 저장됩니다.

📌 신뢰 가능한 단일 출처(Single Source Of Truth)

신뢰 가능한 단일 출처란 하나의 상태는 한곳에만 있어야 한다.라는 뜻입니다.
input 을 보면 DOM 에 있는 Value Attribute 를 실시간으로 보여줍니다.

  • Value Attribute 는 최신화 된 값을 가지고 있습니다.
  • 그렇기에 Value Attribute 는 신뢰가 가능합니다.
  • inputTage 의 Value Attribute 는 유일합니다
  • 따라서 Value Attribute 는 신뢰 가능한 단일 출처라는것을 알 수 있습니다.

코드를 보시면 지금 변수 Variable 그리고 Value Attribute 2가지를 볼 수 있습니다. 이 코드를 그림으로 표현해보면 다음과 같습니다.

현재 Input에서 2개의 Varibale 과 Value Attribute를 받고 있는것을 볼 수 있습니다.
Value Attribute 가 계속 최신화가 되고 그 값을 Varibale 갖고 있습니다.

만약 A컴포넌트는 Value Attribute 가 갖고있고, B컴포넌트는 Varibale가 갖고 있다고 가정합니다.

만약 동료 개발자가 실수로 인해 변수 코드를 지운다면 Varibale로 선언된 변수는 갱신되지 못하게 됩니다.

상태는 하나였지만 두가지 출처로 인해 이러한 차이점이 발생할 수 있기 떄문에 신뢰 가능한 단일 출처를 받는것이 중요합니다.

📌 React에서 Form을 다루는 방법(제어,비제어)

제어 컴포넌트
이에 React는 제어 컴포넌트를 통해서 문제를 해결할 수 있습니다. 대표적인 예시를 코드를 보여드리겠습니다.

Value Attribute와 state를 결합하여 name State를 신뢰 가능한 단일 출처로 만든 사진입니다.
따라서 제어 컴포넌트는 Form의 사용자 입력값을 React가 제어한다고 보면 되겠습니다.

비제어 컴포넌트
비제어 컴포넌트는 다음과 같은 코드블록이 대표적인 예시입니다.

state와 달리 useRef를 사용해준 모습입니다. Ref 같은 경우엔 순수 자바스크립트 객체이기 때문에 input 태그에 직접 접근할 수 있고, 값이 변하더라도 리렌더링이 발생하지 않는 것을 볼 수 있습니다.

따라서 비제어 컴포넌트는 React가 Form의 입력값을 제어하지 않습니다. Value Attribute가 신뢰 가능한 단일 출처를 갖고 있다고 보면 되겠습니다.

📌 제어 컴포넌트와 비제어 컴포넌트 비교

제어 컴포넌트 단점

컴포넌트 분리를 잘 해주면 리렌더링 이슈가 없는지도 모르겠습니다. 하지만 유저가 많은 데이터를 수정했을 때, 데이터들을 한 데 모아 서버에 한번에 보내기 위해서는 각 value 값을 input 태그들의 부모 컴포넌트에서 관리하게 됩니다. 이 경우 하나의 input 태그의 데이터를 변경하기만 해도 부모 컴포넌트가 갖고 있는 모든 태그가 리렌더링이 됩니다.

input 태그가 몇 개 되지 않는 경우 리렌더링이 오래 걸리지 않기 때문에 문제가 되지는 않습니다. 하지만 부모 컴포넌트가 갖고 있는 자식 컴포넌트(input태그)가 수백개가 될 경우 리렌더링이 상당히 오래 걸리게 됩니다. 이 경우에는 UX가 당연히 좋게 보이지 않을 수 밖에 없습니다.

비제어 컴포넌트를 고려해야 하는 상황

비제어 컴포넌트를 사용할 경우 위에서 설명했듯이 DOM에게 직접적으로 맡기게 됩니다. 유저가 입력한 값의 동기화는 이뤄지지 않는다는 이야기죠. 대신 리렌더링을 거치지 않고 유저의 입력 값을 화면에 빠르게 보여줄 수 있게 됩니다.

관리하고 있는 프로젝트에 유저 수가 많다고 가정하고!! 수정 버튼을 눌러 변경 사항을 서버에 보내야 할 경우에 useRef를 활용하여 input태그의 값들을 불러올 수 있습니다.

📌 정리

리액트 공식문서에서는 모든 상황에서 제어 컴포넌트를 사용할 것을 권장합니다. 하지만 특별한 케이스에서는 비제어 컴포넌트를 사용할 수도 있다고 합니다.

제어 컴포넌트를 사용하면 input 값이 항상 동기화 되어있기 때문에 서버에 요청을 보낼 떄 따로 useRef를 사용해서 값을 불러올 팔요가 없습니다. 또한 이메일,비밀번호 형식 등을 input 값의 매 변경때마다 유효성 검사를 하고 싶다면 매번 동기화되는 제어 컴폰넌트를 사용하는게 훨씬 수월 할 수 있습니다.

개인적으로 만약 내 프로젝트에서 부모 컴포넌트에서 관리해야하는 input,textarea,select태그가 많고, 수많은 데이터를 한번에 수정해야 한다는 상황이 온다면 UX가 조금 더 수월한 비제어 컴포넌트를 사용하는 것이 더 좋다고 생각합니다.

참고자료

React controlled vs. uncontrolled components

10분 테코톡

profile
물음표를 느낌표로 바꾸는 개발자

0개의 댓글