제어 컴포넌트와 비제어 컴포넌트의 차이점

Haizel·2023년 5월 22일
1
post-thumbnail

1. 제어 컴포넌트


React에 의해 값이 제어되는 컴포넌트를 제어 컴포넌트라고 합니다. 보통 form 이나 input 등의 입력 요소 태그를 다룰 때, 요소에 입력되는 값을 state로 관리하거나 DOM API를 통해서 관리할 수 있습니다. 이때 state로 DOM 요소의 값을 다루는 컴포넌트가 바로 제어 컴포넌트입니다.

예제 코드

아래 코드는 input 의 값이 바뀔 때마다 ChangeName 함수를 통해 state의 값을 업데이트해주는 제어 컴포넌트입니다.

import React, { useState } from "React";

function Control() {
	const [name, setName] = useState(null);

	const ChangeName = (e) => {
		setName(e.current.value);
	}

	return (
		<input onChange={ChangeName} value={name} />
	 )
}

제어 컴포넌트는 사용자의 입력을 기반으로 state를 관리하고 update합니다. 이처럼 제어 컴포넌트는 React에 의해 값이 제어되는 입력, 폼 요소에서 사용됩니다.


문제점

제어 컴포넌트는 입력할 때마다 렌더링 하기 때문에, 불필요하게 리렌더링되거나 API를 호출할 수 있습니다. 즉 사용자가 입력하는 모든 데이터가 동기화됩니다.
이 문제를 해결하기 위해서 쓰로틀링(Throttling)과 디바운싱(Debouncing)을 활용할 수 있습니다.

  • 쓰로틀링(Throttling) : 마지막 함수가 호출된 후 일정시간이 지나기 전에 다시 호출되지 않도록 하는 것
  • 디바운싱(Debouncing) : 연이어 호출되는 함수들 중 마지막(혹은 맨 처음) 함수만 호출하도록 하는 것

📎  참고자료 - 쓰로틀링과 디바운싱


언제 사용할까?

  1. 유효성 검사
  2. 실시간으로 필드 검사를 해야하는 경우
  3. 조건에 따라 버튼의 활성화 여부가 바뀌는 경우

2. 비제어 컴포넌트


React에 의해 값이 제어되지 않은 컴포넌트를 비제어 컴포넌트라고 합니다. 제어 컴포넌트에서 폼 데이터는 React 컴포넌트에서 다뤄지는 반면, 비제어 컴포넌트는 DOM 자체에서 폼 데이터가 다뤄집니다.

따라서 모든 state 업데이트에 대한 이벤트 핸들러를 작성하는 대신 ref를 사용해 DOM에서 폼 값을 가져올 수 있습니다.

예제 코드

아래 코드는 ref를 통해 input 값에 접근 할 수 있고, 이벤트 핸들러를 통해 ref에 저장된 요소의 값을 가져와 활용하는 비제어 컴포넌트입니다.

import React, { useRef } from "React";

function UnControl() {
	const nameRef = useRef(null);
	
	return (
		<input ref={nameRef} />
	)
}

비제어 컴포넌트는 state로 값을 관리하지 않기 때문에 값이 바뀔 때마다 리렌더링, API 호출을 하지 않아 성능상 이점이 있습니다. 즉 비제어 컴포넌트는 사용자가 직접 트리거 하지 전까지는 리렌더링을 발생시키지 않고 값을 동기화 시키지도 않습니다.
대표적 예로 submit 버튼을 클릭하면 함수 내에서 ref를 통해 form 내 value들에 접근합니다.


💡 useRef와 reRendering 에 대해

왜 비제어 컴포넌트를 사용할 때 useRef를 사용하고, useRef는 리렌더링을 발생시키지 않을까?
1. useRef()는 heap 영역에 저장되는 일반적인 자바스크립트 객체이다.
2. 메번 렌더링할 때 동일한 객체를 제공한다. heap에 저장되어 있기 때문에 어플리케이션이 종료되거나 가비지 컬렉팅될 때까지, 참조할 때마다 같은 메모리 값을 가진다고 할 수 있다.
3. 값이 변경되어도 리렌더링 되지 않는다. 같은 메모리 주소를 가지고 있기 때문에 자바스크립트의 일치 연산(===)이 항상 true를 반환한다.

→ 즉 변경을 감지할 수 없어 리렌더링 하지 않는다.


언제 사용할까?

일반적으로 모든 form 요소의 동기화가 필요하지 않고, form 요소가 증가할수록 면 모든 컴포넌트에 쓰로틀링이나 디바운싱을 걸기엔 어려움이 있습니다. 따라서 만약 값이 트리거 된 이후에 값이 갱신되어도 된다면, 비제어 컴포넌트를 통해 불필요한 렌더링을 방지하고 성능 향상을 할 수 있습니다.

대표적으로 비제어 컴포넌트를 사용해 렌더링을 최적화하는 라이브러리로 react-hook-form이 있습니다.


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


차이점

제어 컴포넌트비제어 컴포넌트
1. 동기화 항상 동기화(제어 컴포넌트의 값은 항상 최신값을 유지)동기화 X
2. 폼 데이터React 컴포넌트DOM 자체

✔️ React 공식 문서에 따르면 대부분의 경우 폼 구현 시 제어 컴포넌트를 사용하는 것을 권장


언제 무엇을 사용해야 할까?

기능제어 컴포넌트비제어 컴포넌트
일회성 정보 검색 (ex. 제출)
제출 시 값 검증
실시간으로 필드값의 유효성 검사
조건부로 제출 버튼 비활성화(disabled)
실시간으로 입력 형식 적용하기(ex. 숫자만 가능하게 등)
동적 입력
  • 즉각적, 실시간으로 값에 대한 피드백이 필요하다 → 제어 컴포넌트
  • 즉각적인 피드백이 불필요하고 제출시에만 값이 필요하다 혹은 불필요한 렌더링과 값 동기화가 싫다 → 비제어 컴포넌트


📎 참고문서

profile
한입 크기로 베어먹는 개발지식 🍰

0개의 댓글