React

[React] 제어 컴포넌트와 비제어 컴포넌트 (Controlled Component, Uncontrolled Component)

게로망 2026. 2. 2. 20:02

프로젝트 진행 중 특정 페이지에서 input값과 select값을 state로 관리할지 ref로 관리할지 고민이 되서

리액트 공식 홈페이지에 나와있는 가이드를 읽으며 얻은 정보를 정리해보았다.

 

https://ko.legacy.reactjs.org/docs/uncontrolled-components.html?utm_source

 

비제어 컴포넌트 – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

 

1. 제어 컴포넌트란(Controlled Component)?

값의 소유자가 state인 경우를 말한다. 구체적으로는, input태그나 select태그의 value속성을 state로 넣어주고 사용자가 입력값을 바꾸면 onChange로 setState를 실행하여 즉시 갱신하는 구조를 뜻한다.

 

이 구조의 특징은 값을 변경할시 리렌더링이 발생하고 값의 동기화가 명확하다(값이 바뀌는대로 바로바로 화면에 반영). 외부에서 전달받은 파라미터 값에 따라 input/select 값 변경(사용자 입력이 아닌 다른 이유로 state가 바뀌는 경우), 조건부 초기화 등에 강하므로 실무에서 권장되는 방식이다. 

 

[ 외부 이벤트 ]
     ↓
 setName("홍길동")
     ↓
리랜더링
     ↓
 input.value = "홍길동"

 

의외로 직관적이고 단순명료한 구조다.

 

예시)

import { useState } from "react";

export default function ControlledSelectExample() {
  const [city, setCity] = useState("");

  return (
    <select
      value={city}
      onChange={(e) => setCity(e.target.value)}
    >
      <option value="">선택</option>
      <option value="seoul">서울</option>
      <option value="busan">부산</option>
    </select>
  );
}

 

 

2. 비제어 컴포넌트란( Uncontrolled Component )?

값의 소유자가 DOM인 경우를 말한다. 구체적으로는, React는 값에 직접 관여하지 않고 defaultValue / ref 사용하는 경우를 뜻한다.

 

*DOM이란? 브라우저가 만든 “화면 설계도”이다. HTML을 그대로 쓰는 게 아니라 브라우저가 자바스크립트로 다룰 수 있게 바꾼 결과물.

 

예시)

const inputRef = useRef();

<input defaultValue="abc" ref={inputRef} />

 

 

값을 조회할 시

inputRef.current.value

 

최초 랜더링 시에만 defaultValue 적용하고 이후에 값이 변경되도 React는 알 수 없다.

이를 쉽게 설명하면,

예를들어 페이지에 메인그리드에서 행을 클릭했을 시 해당 행의 데이터가 파라미터로 전달되어 서브 테이블에 서 해당데이터로 api를 다시 호출하여 응답값을 뿌려주는 경우에

 

그 외부에서 주입받는 파라미터가 변경될 시 변경된 값이 자동반영이 안된다. 

고로 강제 remount가 필요한 경우가 생기게 된다. 

 

  제어 컴포넌트 비제어 컴포넌트
값 관리 React state DOM
외부 값 변경 반영 안 됨
defaultValue 안씀 핵심
리마운트 필요 거의 없음 종종 필요

 

 

 

3. 어떤 경우에 제어/비제어 컴포넌트를 사용하는가?

일단 실무적으로 90%이상은 제어 컴포넌트를 사용한다.

React에서는 DOM을 직접 만질수록 위험하기 때문이다. 

아래의 경우에 해당사항이 있다면 제어컴포넌트 구조를 따르는 것이 권장된다. 

 

- 외부값이 들어올 수 있다

- 그리드 select 변경이 있다

- api 조회결과를 세팅해야한다

- 수정가능한 요소가 있는 화면이다

- 입력값 검증이 필요하다

- 저장, 취소, 초기화 로직이 있다

- 권한에 따라 readonly / disabled가 필요하다

 

비제어 컴포넌트를 쓰는 경우는 아래에 해당사항이 있을 경우에만 사용한다.

 

-조회조건 폼(실시간 반응필요없음, 값은 조회버튼 누를 때만 필요)

-입력필드가 많고 단순함

-값 저장을 할 필요가 없음

 

 

그런데 제어컴포넌트를 사용할 때  크롬에서 React Developer Tools로 보면

input에 값을 입력하면 테이블에서 계속해서 리랜더링이 발생하는데 

초록색이었다가 주황색으로 점점바뀌는게 불안하다...

 

 

그렇다면 사용자가 입력값을 입력할 때마다 리랜더링이 발생해서 성능저하가 발생하는걸까???

-->에 대한 답은 "99%의 경우 문제 안 됨"이다.

리렌더링이라는것이 통상적으로 알려진 것 보다 성능저하를 유발하지 않는다.

 

단, 1%의 경우는 어떠한 경우냐면

 

한글자 입력할때마다 무거운 계산이 실행되거나 api호출로직이 걸려있는 경우,

state하나 변경됨으로써 대형 grid 리랜더링 

 

이런 경우에만 문제가 되어 아래 방법으로 해결할 수 있다. 

- debounce

- useMemo

- useCallback

- state 분리

 

 

 

GPT왈: “입력할 때마다 리렌더 일어나는 건 정상” → 이건 React 설계 철학 자체라서 문제 아님.

 

https://en.wikipedia.org/wiki/React_%28software%29?utm_source=chatgpt.com

위 링크에 보면

 

React의 주요 장점은 변경된 페이지 부분만 다시 렌더링하여 변경되지 않은 DOM 요소의 불필요한 재렌더링을 방지한다는 것이다.

 

라는 문구가 있는데, 핵심은 리액트는 '리렌더를 줄이는 것'이 목표가 아니라 ' 불필요한 리렌더를 줄이는 것'이라는 의미이다.

즉, 불필요한 컴포넌트까지 리렌더되는 상황이 문제인 것이고 그 외에는 문제가 되지 않는다는 것이다.