[React] 제어 컴포넌트와 비제어 컴포넌트

SungWoo·2024년 12월 31일
1

React

목록 보기
13/16
post-thumbnail

Form Tag Elements

대표적인 폼 태그 엘리먼트로는 <input/> , <textarea/> , <select/> 가 있다.

이들은 사용자 입력을 기반으로 자신의 state를 관리하고 업데이트하며, 각각의 value Attribute를 통해 값에 접근할 수 있다.

즉, 사용자가 입력한 값은 value Attribute에 저장되고, 이 속성은 DOM에 있으므로 결과적으로 사용자 입력값은 DOM에 저장된다고 볼 수 있다.

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

하나의 상태는 한 곳에만 있어야 한다.

input 태그는 사용자 입력값에 대해 value Attribute가 실시간으로 갱신된다.

value 속성은 최신값을 가지고 있어 신뢰할 수 있으며, 단 하나이기 때문에 유일하다.

따라서 value Attribute는 신뢰 가능한 단일 출처이다.

단일 출처가 중요한 이유

const form = document.querySelector('form');

let inputValue = '';
let textareaValue = '';
let selectValue = '';

const onSubmit = (e) => {
	e.preventDefault();
	
	inputValue = e.target.elements['input-elem'].value;
	textareaValue = e.target.elements['textarea-elem'].value;
	selectValue = e.target.elements['select-elem'].value;
};

form.addEventListener('submit', onSubmit);

위 코드는 사용자의 입력값이라는 상태를 value Attribute와 let 변수라는 두 가지의 출처로 나누어 가진다.

만약 오른쪽 그림과 같이 어떤 이유로 value 속성과 변수 간의 연관관계가 깨진다면, let 변수의 값은 더 이상 갱신되지 않아 데이터 불일치가 발생할 수 있다.

그래서 신뢰 가능한 단일 출처를 가지는 것이 중요하다.

React의 Form 처리 방식

리액트는 제어 컴포넌트를 퉁해 이러한 문제를 해결할 수 있다.

제어 컴포넌트(Controlled Component)

React 상태(state)를 통해 입력값을 제어하는 컴포넌트

import { useState } from 'react';

export default function App() {
	const [name, setName] = setState('');
	
	return (
		<form>
			<label>name : </label>
			<input
				value={name}
				onChange={(e) => {
					setName(e.target.value);
				}}
				placeholder="이름을 입력하세요."
			/>
		</form>
	)
}

제어 컴포넌트는 value 속성과 state를 결합해 name state를 신뢰 가능한 단일 출처로 만든다.

즉, Form의 사용자 입력값을 React가 직접 제어한다.

제어 컴포넌트의 특징

  • React state가 신뢰 가능한 단일 출처
  • 실시간 값 변경 감지 및 처리
  • 입력값 검증, 형식 변환 등 즉각적인 처리 가능
  • 상태 변경마다 리렌더링 발생

비제어 컴포넌트(Uncontrolled Component)

React의 상태가 아닌, DOM 자체가 입력값을 제어하는 방식

import { useRef } from 'react';

export default function App() {
	const nameRef = useRef(null);
	
	const submitName = (e) => {
		e.preventDefault();
		
		console.log(nameRef.current.value);
	};
	
	return (
		<form onSubmit={submitName}>
			<label>name : </label>
			<input ref={nameRef} placeholder="이름을 입력하세요." />
		</form>
	)
}

비제어 컴포넌트는 ref를 사용하여 input 태그에 접근한다. ref는 순수 자바스크립트 객체이며, current 프로퍼티를 통해 input 태그에 접근할 수 있다.

ref는 직접 변화가 되어도 리렌더링이 발생하지 않는 특성이 있다.

비제어 컴포넌트에서는 React가 크게 관여하지 않으며, HTML Form Elements와 유사하게 동작한다.

따라서 value Attribute가 신뢰 가능한 단일 출처가 된다.

비제어 컴포넌트의 특징

  • DOM의 value Attribute가 신뢰 가능한 단일 출처
  • 필요한 시점에만 값 참조
  • 불필요한 리렌더링 없음
  • React의 제어 최소화

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

주요 차이점

제어 컴포넌트비제어 컴포넌트
데이터 관리 주체ReactDOM
데이터 갱신 시점사용자가 값을 입력할 때마다 갱신특정 시점에서 DOM에서 pull하여 갱신
리렌더링 여부값을 입력할 때마다 발생값을 입력할 때는 발생하지 않음

상황에 따른 비교

제어 컴포넌트비제어 컴포넌트
Submit과 같은 일회성 정보 검색OO
Submit 시 유효성 검사OO
조건에 따른 Submit 버튼 (비)활성화OX
즉각적인 필드 유효성 검사OX
특정 입력 형식 적용OX
동적 입력OX

사용 기준

제어 컴포넌트 선택 시점

  • 실시간 입력 값 검증이 필요할 때
  • 조건부 제출 버튼 활성화
  • 동적 입력 형식 적용
  • 입력값에 따른 UI 즉시 변경

비제어 컴포넌트 선택 시점

  • 단순한 폼 제출
  • 성능 최적화가 필요할 때
  • 기존 non-React 코드와 통합
  • 파일 입력 처리 시

정리

  • 실시간 처리가 필요 없는 간단한 폼은 비제어 방식을 고려한다.
  • 파일 업로드는 항상 비제어 컴포넌트로 구현한다.
  • 성능이 중요할 시 비제어 방식을 우선 검토한다.
  • 복잡한 폼은 Formik, React Hook Form 등의 라이브러리를 활용한다.

Reference

profile
어제보다 더 나은

0개의 댓글