2026. 7. 17.
React uncontrolled input 경고 없이 입력하려면, 첫 value 타입부터 고정하세요
React 입력값이 undefined에서 문자열로 바뀔 때 뜨는 경고를 재현하고, text와 checkbox 초기값을 일관되게 고치는 순서다.

개발 콘솔에 A component is changing an uncontrolled input to be controlled가 뜨면 폼 전체를 다시 만들 필요는 없다. 첫 렌더의 value가 undefined인지부터 확인한다. 이후 API 응답이 문자열을 넣으면서 입력의 제어 주체가 바뀐 것이 흔한 원인이다.
text input을 React state로 관리한다면 초기값을 ''로 두고, checkbox라면 false로 둔다. 이 두 값을 고친 뒤 경고가 사라졌는지, 입력이 실제로 바뀌는지, API 값이 다시 표시되는지를 같은 순서로 확인한다.
첫 렌더에서 value와 checked의 타입을 확인한다
React 공식 <input> 문서는 문자열 value를 받은 text input을 controlled input으로 설명한다. controlled input은 생애 동안 문자열 값을 유지해야 한다. 첫 렌더에 undefined를 주고 다음 렌더에 "민지"를 주면 uncontrolled에서 controlled로 바뀐다.
경고가 난 컴포넌트에서 state 선언과 JSX를 같이 본다. 아래 코드는 사용자 정보가 도착하기 전 name이 undefined다.
const [name, setName] = useState<string>();
console.log('name on render:', name, typeof name);
return (
<input
value={name}
onChange={(event) => setName(event.target.value)}
/>
);
콘솔 첫 출력이 undefined "undefined"이고 데이터 로드 뒤 "민지" "string"으로 바뀐다면 경고의 전환 지점을 찾은 것이다. 입력이 아예 써지지 않는 증상까지 있다면 React 입력칸의 value와 onChange를 분리하는 점검도 함께 확인한다.
입력 유형에 맞춰 처음부터 같은 타입을 보낸다
수정 기준은 단순하다. 현재 값을 React state로 계속 관리할 입력이라면 첫 렌더부터 controlled로 만든다. text 계열은 문자열, checkbox와 radio는 boolean을 유지한다.
text input은 빈 문자열로 시작한다
const [name, setName] = useState('');
<input
value={name}
onChange={(event) => setName(event.target.value)}
/>
API 객체를 그대로 state에 넣는 구조에서는 JSX 경계에서 fallback을 둘 수 있다.
const safeName =
typeof profile.name === 'string' ? profile.name : '';
<input
value={safeName}
onChange={(event) =>
setProfile((current) => ({
...current,
name: event.target.value,
}))
}
/>
typeof 검사로 문자열만 통과시키면 null과 undefined뿐 아니라 예상하지 못한 객체까지 입력에 들어오는 일을 막는다. 숫자를 문자열로 보여 줘야 하는 필드라면 API 매핑 단계에서 String(value)로 변환한다.
checkbox는 false로 시작한다
checkbox는 value가 아니라 checked가 제어 상태를 결정한다. 첫 값도 boolean이어야 한다.
const [agreed, setAgreed] = useState(false);
<input
type="checkbox"
checked={agreed}
onChange={(event) => setAgreed(event.target.checked)}
/>
체크가 화면에서 따라오지 않는다면 React 체크박스의 checked와 onChange 점검 순서로 이벤트 값까지 추적한다.
초기값만 필요하면 defaultValue를 쓴다
defaultValue는 첫 값만 지정하고 이후 입력값을 DOM이 관리하도록 할 때 쓴다. API 응답 뒤 현재 값을 계속 바꾸거나 저장 버튼 상태를 React에서 계산해야 한다면 value와 onChange를 유지한다. 경고를 없애려는 이유만으로 controlled input을 uncontrolled로 바꾸면 데이터 흐름이 더 불분명해진다.
경고를 숨기지 말고 세 가지 동작을 다시 확인한다
console.error를 가로채거나 경고 필터를 켜면 원인은 남는다. optional chaining으로 입력 자체를 늦게 렌더하는 방법도 로딩 UI가 필요한 설계가 아니라면 문제를 옮길 뿐이다.
수정 뒤에는 다음 세 가지를 같은 화면에서 확인한다.
- 새로고침 직후 Console에 uncontrolled-to-controlled 경고가 없다.
- API 응답 전에는 text input이 빈 문자열, checkbox가
false로 렌더된다. - 입력과 체크를 바꾸면 state가 즉시 갱신되고, API 응답 뒤에도 값이 유지된다.
React 개발 모드에서 페이지를 새로고침하고 첫 렌더 로그를 남긴다. 그다음 값을 한 글자 입력하고 checkbox를 한 번 바꾼다. 경고 0건, 입력 가능, 응답 값 표시가 모두 맞아야 수정이 끝난다.
공식 기준과 다음 행동
지금 경고가 열린 화면에서 state 선언 한 줄과 JSX의 value 또는 checked를 나란히 놓는다. 첫 렌더 타입이 text는 string, checkbox는 boolean인지 확인한 뒤 새로고침으로 다시 검증한다.
이 글은 AI 코딩과 개발 학습의 일반 정보 제공 목적입니다. 도구, 모델, 커리큘럼, 요금은 버전과 시점에 따라 달라질 수 있으므로 실습이나 도입 전 공식 문서와 최신 릴리스 노트를 확인하세요.
다음으로 읽을 기사
같은 흐름으로 이어 읽기 좋은 기사만 추려 보여줍니다.
첫 번째 댓글을 남겨보세요
여러분의 생각이 다른 독자에게 도움이 됩니다.
댓글 0
이 글을 읽은 독자들의 생각을 나눠보세요.