노트

제어·비제어 컴포넌트

Controlled and Uncontrolled Components

프런트엔드#react · 연결된 개념 2개

쉽게 말하면

제어 컴포넌트는 입력 칸에 글자를 칠 때마다 React가 장부에 옮겨 적는 방식이고, 비제어 컴포넌트는 칸에 그냥 두었다가 제출할 때 한 번 꺼내 보는 방식이에요. 실시간 검사가 필요하면 앞쪽, 칸이 많으면 뒤쪽이 편해요.

비유가 깨지는 곳 한 폼 안에서 둘을 섞으면 값이 어디 있는지 헷갈려요. 한 입력이 제어에서 비제어로 바뀌면 React가 경고하고, react-hook-form은 비제어로 렌더를 줄이면서 필요한 필드만 제어처럼 써요.

제어 컴포넌트(Controlled Component)는 입력값의 진실 원천(Single Source of Truth)이 React state이고, 비제어 컴포넌트(Uncontrolled Component)는 입력값을 DOM(Document Object Model)이 직접 들고 있어서 필요할 때 ref로 꺼내 읽는다.

// 제어: 키 입력마다 state → 렌더
const [email, setEmail] = useState('')
<input value={email} onChange={e => setEmail(e.target.value)} />
 
// 비제어: DOM이 보관, 제출 시 읽기
const ref = useRef(null)
<input defaultValue="" ref={ref} />
제어비제어
진실 원천stateDOM
렌더입력마다거의 없음
실시간 검증·포맷쉬움따로 처리
코드량많음적음, HTML(HyperText Markup Language) 폼과 잘 맞음
  • 제어 방식은 React의 단방향 데이터 흐름(One-Way Data Flow)에 맞아 예측하기 쉽다. 입력 중 검증, 마스킹, 다른 필드에 따른 조건부 렌더가 필요하면 이쪽이다(React 상태 갱신)
  • 비제어 방식은 리렌더가 적다. 필드가 많은 폼에서 성능이 낫다
  • react-hook-form이 비제어 기반인 이유도 이것이다. 입력할 때마다 렌더하지 않고, 필드 초기값을 state로 들 필요가 없으며, 네이티브 폼 동작을 활용한다. 필요하면 일부 필드만 제어 방식처럼 쓸 수 있다
  • 같은 폼 안에서 둘을 섞으면 값이 어디에 있는지 헷갈린다. 하나의 컴포넌트가 제어였다가 비제어로 바뀌면 React가 경고한다
  • 서버로 바로 제출하는 폼은 form action과 비제어 입력이 자연스럽게 맞는다

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • Vue 3와 React 대응표

    React에 익숙한 개발자가 Vue 3(Composition API, script setup)를 빠르게 읽을 수 있게 짝지어 본 표. 가장 큰 차이는 Vue는 반응성(Reactivity)을 자동으로 추적해서 의존성 배열(Dependency Array)이 없다는 점이다.

  • Redux 이후의 상태 관리 선택

    한때 React 앱의 기본값이던 Redux는 2025~2026년 기준으로 여러 선택지 중 하나가 됐다. 상태를 종류별로 나눠 각자에 맞는 도구를 고르는 방식이 자리 잡았기 때문이다.

  • 재조정(Reconciliation)

    재조정(Reconciliation)은 React가 이전 렌더의 엘리먼트 트리와 새 트리를 비교(Diffing)해, 실제 DOM(Document Object Model)에 필요한 최소한의 변경만 반영하는 과정이다. 두 트리를 완벽하게 비교하면 O(n³)이라, React는 두 가지 가정을 두어 O(n)으로 줄인다.

  • 내부 가변성과 메모이제이션

    내부 가변성(Interior Mutability)은 객체나 함수의 참조는 그대로인데 안에 숨은 상태가 바뀌는 성질이다. React의 메모이제이션은 "입력이 다른 참조인가"만 보기 때문에, 참조가 같으면 내용이 바뀌어도 바뀌지 않았다고 판단한다. React 공식 문서는 이를 "겉모습은 같은데 몰래 내용물을 바꾸는 상자"에 비유한다.

  • 선언형과 명령형 프로그래밍

    명령형(Imperative)·절차적(Procedural) 프로그래밍은 결과에 도달하는 방법(how)을 단계별로 지시하고, 선언형 프로그래밍(Declarative Programming)은 원하는 결과(what)만 기술하고 과정은 도구에 맡긴다. 길 안내로 치면 "직진하다 두 번째 신호에서 우회전"이 명령형, "강남역 가 주세요"가 선언형이다.

보기 옵션