🎯 React 제어 컴포넌트 vs 비제어 컴포넌트
React에서 폼을 다룰 때 가장 먼저 부딪히는 개념 중 하나가 바로 제어(Controlled) 컴포넌트와 비제어(Uncontrolled) 컴포넌트입니다. 이 두 방식은 입력값을 어떻게 관리하느냐에 따라 나뉘며, 각각 장단점과 사용 목적이 다릅니다.
이번 포스팅에서는 이 두 가지 개념을 정의, 차이점, 코드 예시를 통해 쉽게 이해해보겠습니다.
✅ 제어 컴포넌트 (Controlled Component)
정의: 입력 요소의 상태(value)를 React 컴포넌트의 state로 관리하는 방식입니다. 즉, 입력값의 소유권이 React에 있습니다.
특징
- 모든 값은 useState나 this.state로 관리됨
- onChange 이벤트 핸들러를 통해 state를 업데이트
- React가 폼의 상태를 전적으로 제어
예제
import React, { useState } from 'react';
function ControlledForm() {
  const [name, setName] = useState('');
  const handleChange = (e) => {
    setName(e.target.value);
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`입력한 이름: ${name}`);
  };
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={name} onChange={handleChange} />
      <button type="submit">제출</button>
    </form>
  );
}
❎ 비제어 컴포넌트 (Uncontrolled Component)
정의: 입력 요소의 상태를 DOM이 직접 관리하는 방식입니다. 즉, 입력값의 소유권이 실제 HTML 요소에 있습니다.
특징
- ref를 사용해 DOM 요소에 직접 접근
- 상태를 직접 추적하지 않아 코드가 간단할 수 있음
- 외부 라이브러리 또는 레거시 코드와 호환성이 좋음
예제
import React, { useRef } from 'react';
function UncontrolledForm() {
  const nameRef = useRef(null);
  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`입력한 이름: ${nameRef.current.value}`);
  };
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={nameRef} />
      <button type="submit">제출</button>
    </form>
  );
}
Summary
| 항목 | 제어 컴포넌트 | 비제어 컴포넌트 | 
|---|---|---|
| 상태 관리 | React state | DOM 자체 | 
| 접근 방식 | value와onChange사용 | ref를 통한 DOM 접근 | 
| 폼 동기화 | 가능 (일관된 상태 유지) | 어려움 | 
| 초기 값 설정 | useState로 직접 설정 | defaultValue속성 사용 | 
| 적합한 상황 | 복잡한 폼, 유효성 검사 | 간단한 입력, 빠른 프로토타이핑 | 
📝 어떤 걸 써야 할까?
- 제어 컴포넌트: 대부분의 경우 추천. 특히 유효성 검사, 조건부 렌더링, 실시간 폼 제어가 필요할 때.
- 비제어 컴포넌트: 간단한 입력, 퍼포먼스에 민감하거나 외부 라이브러리 연동 시 유용.
💬 마무리
React에서 폼 데이터를 다루는 방법은 다양하지만, 그 핵심은 제어와 비제어의 차이를 이해하는 데 있습니다. 어떤 방식이 더 좋다고 단정할 수는 없으며, 상황에 맞는 선택이 중요합니다.
여러분은 어떤 방식이 더 익숙한가요? 댓글로 여러분의 경험을 공유해주세요! 😊
