당신은 uncontrolled를 정확히 모른다
controlled, uncontrolled 에 대해 들어본 적이 있는가? 알고있다면, 무슨 차이인지 정확히 알고 있는가?
나도 얼마전까진 내가 정확히 알고있는줄 알았다.
최근 React19 공식문서를 보면서 또 한번 오만함이었다는 것을 느낀다.
React 에서의 uncontrolled 라는 용어가 에전엔 어땠고, 지금은 어떻게 변했는지에 대해 기록하려 한다.

A JavaScript library for building user interfaces
기존에 내가그리고 여러분이 알고있던 uncontrolled 는 예전 레거시 공식문서에 잘 명시되어있다.

deprecated 문서라 언제 닫힐지 모르기에 캡처로 나의 억울함(?) 을 남겨 놓아야겠다.

중요한 부분은 다음과 같다.
The alternative is uncontrolled components, where form data is handled by the DOM itself. → (controlled components 설명 후) 반면, 비제어 컴포넌트는 form 데이터를 DOM 자체에서 다룹니다. you can use a ref to get form values from the DOM. → ref 를 사용해 DOM에서 form 값을 가져올 수 있습니다.


그 외에는 컴포넌트가 mount 된 후로는 DOM이 업데이트 되지 않는 defaultValue, file input은 언제나 uncontrolled components 라는 부분을 알려주고 문서는 끝이 난다.
React에서의 uncontrolled components는 주로 <form> 태그의 관련 부분에서만 국한된 용어라고 알고 있었고, 실제로 많은 커뮤니티/아티클에서도 그렇게 설명하고 있다.
레거시 공식문서에서조차 그렇게 말한다.
그렇게만 알고 있던 와중, 새롭게 단장된 react.dev 공식문서에서 새로운 내용을 봐버렸다.

The library for web and native user interfaces
It is common to call a component with some local state “uncontrolled”. For example, the originalPanelcomponent with anisActivestate variable is uncontrolled because its parent cannot influence whether the panel is active or not.
최신 문서에서는 명확히 local state 즉, ref를 사용해 DOM을 직접 변경하는 경우 뿐만 아니라 부모 컴포넌트가 자식들의 (isolated 하고 private한) local state 에 영향을 줄 수 없다면 uncontrolled components 로 부를 수 있다고 말한다.
예시를 보자.
function Panel({ title, children }) {
const [isActive, setIsActive] = useState(false);
return (
<section className="panel">
<h3>{title}</h3>
{isActive ? (
<p>{children}</p>
) : (
<button onClick={() => setIsActive(true)}>
Show
</button>
)}
</section>
);
}
export default function App() {
return (
<>
<h2>Almaty, Kazakhstan</h2>
<Panel title="About">
With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
</Panel>
<Panel title="Etymology">
The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
</Panel>
</>
);
}위 코드의 경우에서, Panel 컴포넌트는 uncontrolled components 라고 불릴 수 있다.
내부의 isActive state는 local state 이기 때문이다.
이 글을 읽고 있는 당신. uncontrolled component 가 뭔지 알고 있었는가? ㅎㅎ..
물론 같은 페이지에서 명확히 규정될 필요가 없다고 당부하고 있긴 하다.
In practice, “controlled” and “uncontrolled” aren’t strict technical terms—each component usually has some mix of both local state and props. However, this is a useful way to talk about how components are designed and what capabilities they offer.
→ controlled 와 uncontrolled 는 기술적 용어가 아니다. (역주: 소통을 원활히 하기위한 개념에 가깝다.)
이렇게 엄근진하게 받아들일 필요까진 없지만, 레거시 공식문서에서 설명한 것과 대조되는것은 사실이다.
React 팀에서 어떤 생각을 가지고 uncontrolled 라는 개념을 이정도로 포괄적인 용어로 사용할 수 있게 공식문서를 작성했는지, 관련된 discussion 이나 stackoverflow를 찾아봤지만, 아직 유명해지지 않아서인지(?) 잘 나오지 않았다.
오늘 내가 새롭게 알게된 개념을 동료분들과 개발 커뮤니티에 공유하고, 이 미세한 영향력을 통해 관련된 자료를 찾아내는것을 목표로 설정하며, 이 글을 마친다.