HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🐣
프론트엔드 데브코스 4기 교육생
/
😃
이동근팀
/
react@18.2.0
react@18.2.0
/
<input>

<input>

브라우저 빌트인 <input> 컴포넌트로 다양한 form input을 렌더링할 수 있습니다.
<input />
  • 참조
    • <input>
  • 사용법
    • 다양한 유형의 input 표시하기
    • input에 대한 label 제공하기
    • input에 대한 초기값 제공하기
    • form 제출 시 input 값 읽기
    • state 변수로 input 제어하기
    • 모든 키 입력 리렌더링 최적화하기
  • 문제 해결
    • 텍스트 input에 타이핑해도 업데이트되지 않습니다
    • 체크박스를 클릭해도 업데이트되지 않습니다
    • 키를 누를 때마다 커서가 처음으로 이동합니다
    • “컴포넌트가 비제어 입력을 제어하도록 변경하고 있습니다.” 라는 오류가 발생합니다

참조

<input>

input을 표시하려면 브라우저 빌트인 <input> 컴포넌트를 렌더링 하세요.
<input name="myInput" />
아래에서 더 많은 예시를 확인하세요.

Props

<input>은 모든 공통 엘리먼트 prop을 지원합니다.
다음 props 중 하나를 전달하여 input을 제어할 수 있습니다:
  • checked: 불리언. 체크박스 input 또는 라디오 버튼의 선택 여부를 제어합니다.
  • value: 문자열. 텍스트 input의 텍스트를 제어합니다. (라디오 버튼의 경우 해당 form data를 지정합니다).
위 둘 중 하나를 전달할 때, 전달된 값을 업데이트하는 onChange 핸들러도 함께 전달해야 합니다.
다음 <input> props는 비제어 input에만 관련이 있습니다:
  • defaultChecked: 불리언. type="checkbox" 및 type="radio"의 기본값을 특정합니다.
  • defaultValue: 문자열. 텍스트 input의 기본값을 특정합니다.
다음 <input> props는 비제어 및 제어 input 모두에 해당합니다:
  • accept: 문자열. type="file" input에 허용되는 파일 형식을 지정합니다.
  • alt: 문자열. type="image" input의 대체 이미지 텍스트를 지정합니다.
  • capture: 문자열. type="file" input으로 캡쳐할 미디어(마이크, 비디오, 카메라)를 지정합니다.
  • autoComplete: 문자열. 가능한 자동완성 동작을 지정합니다.
  • autoFocus: 불리언. true이면 엘리먼트가 마운트될 때 초점을 맞춥니다.
  • dirname: 문자열. 엘리먼트의 방향성에 대한 폼 필드 이름을 지정합니다.
  • disabled: 불리언. true이면 해당 input은 상호작용할 수 없으며 흐릿하게 보여집니다.
  • children: <input>은 자식을 받지 않습니다.
  • form: 문자열. 이 input이 속한 <form>의 id를 지정합니다. 이 prop이 없으면 상위의 가장 가까운 form이 됩니다.
  • formAction: 문자열. type="submit" 및 type="image"에 대해 상위 <form action>을 덮습니다.
  • formEnctype: 문자열. type="submit" 및 type="image"에 대해 상위 <form enctype>을 덮습니다.
  • formMethod: 문자열. type="submit" 및 type="image"에 대해 상위 <form method>을 덮습니다.
  • formNoValidate: 문자열. type="submit" 및 type="image"에 대해 상위 <form noValidate>을 덮습니다.
  • formTarget: 문자열. type="submit" 및 type="image"에 대해 상위 <form target>을 덮습니다.
  • height: 문자열. type="image"의 이미지 높이를 지정합니다.
  • list: 문자열. autocomplete 옵션들과 함께 <datalist>의 id를 지정합니다.
  • max: 숫자. 숫자타입 및 날짜시간 input의 최대값을 지정합니다.
  • maxLength: 숫자. 텍스트 및 기타 input의 최대 길이를 지정합니다.
  • min: 숫자. 숫자타입 및 날짜시간 input의 최솟값을 지정합니다.
  • minLength: 숫자. 텍스트 및 기타 input의 최소 길이를 지정합니다.
  • multiple: 불리언. type="file" 및 type="email"에 대해 여러 값을 허용할지 여부를 지정합니다.
  • name: 문자열. 폼에 제출되는 input의 이름을 지정합니다.
  • onChange: Event 핸들러 함수. 제어 input에서 필수입니다. 사용자가 input의 값을 변경하면 즉시 호출됩니다(예: 키 입력시마다 발생). 브라우저 input 이벤트처럼 동작합니다.
  • onChangeCapture: 캡쳐 단계에서 실행되는 버전의 onChange 입니다.
  • onInput: Event 핸들러 함수. 사용자가 값을 변경하면 즉시 호출됩니다. 역사적인 이유로 React에서는 비슷한 방식으로 작동하는 onChange를 대신 사용하는 것이 일반적입니다.
  • onInputCapture: 캡쳐 단계에서 실행되는 버전의 onInput 입니다.
  • onInvalid: Event 핸들러 함수. 폼 제출시 input이 유효성 검사에 실패하면 호출됩니다. 빌트인 invalid 이벤트와 달리, React의 onInvalid 이벤트는 버블을 발생시킵니다.
  • onInvalidCapture: 캡쳐 단계에서 실행되는 버전의 onInvalid 입니다.
  • onSelect: Event 핸들러 함수. <input> 내부의 선택이 변경되면 호출됩니다. React는 선택이 빈 경우와 (선택에 영향을 미칠 수 있는) 편집에 대해서도 onSelect 이벤트가 호출되도록 확장합니다.
  • onSelectCapture:캡쳐 단계에서 실행되는 버전의 onSelect 입니다.
  • pattern: 문자열. value가 일치해야 하는 패턴을 지정합니다.
  • placeholder: 문자열. input 값이 비어있을 때 희미한 색상으로 표시되는 텍스트입니다.
  • readOnly: 불리언. true이면 이 input은 사용자가 편집할 수 없습니다.
  • required: 불리언. true이면 값을 입력해야만 폼을 제출할 수 있습니다.
  • size: 숫자. 너비 설정과 유사하지만, 단위는 컨트롤에 따라 다릅니다.
  • src: 문자열. type="image" input의 이미지 소스를 지정합니다.
  • step: 양수 또는 문자열 'any'. 유효한 값 사이의 거리를 지정합니다.
  • type: 문자열. input type 중 하나.
  • width: 문자열. type="image" input의 이미지 너비를 지정합니다.

주의사항

  • 체크박스는 value(또는 defaultValue)가 아닌 checked(또는 defaultChecked)가 필요합니다.
  • 텍스트 input이 문자열 value prop을 받으면 제어된 것으로 처리됩니다.
  • 체크박스나 라디오 버튼이 불리언 checked prop을 받으면 제어된 것으로 처리됩니다.
  • input은 동시에 제어되거나 제어되지 않을 수 없습니다.
  • input은 수명 동안 제어되거나 제어되지 않는 상태로 전환될 수 없습니다.
  • 제어되는 모든 입력에는 onChange 이벤트 핸들러가 필요하며, 이 핸들러는 지원 값을 동기적으로 업데이트합니다.

사용법

다양한 유형의 input 표시하기

input을 표시하려면 <input> 컴포넌트를 렌더링합니다. 기본적으로 텍스트 input이 됩니다. 체크박스의 경우 type="checkbox", 라디오 버튼의 경우 type="radio" 또는 다른 input 유형 중 하나를 전달할 수 있습니다.
예시

input에 대한 label 제공하기

일반적으로 모든 <input>은 <label> 태그 안에 배치됩니다. 이는 이 label이 해당 input과 연결되어 있음을 브라우저에 알려줍니다. 사용자가 label을 클릭하면 브라우저가 자동으로 input에 초점을 맞춥니다. 이는 접근성 측면에서도 필수적입니다: 사용자가 관련 input에 초점을 맞추면 스크린 리더가 label 캡션을 알립니다.<input>을 <label>에 중첩할 수 없는 경우 동일한 ID를 <input id> 및 <label htmlFor>.에 전달하여 연결합니다. 한 컴포넌트의 여러 인스턴스 간에 충돌을 피하려면 useId를 사용하여 이러한 ID를 생성하십시오.

input에 대한 초기값 제공하기

선택적으로 모든 input의 초기값을 지정할 수 있습니다. 텍스트 input의 경우 defaultValue 문자열로 전달합니다. 체크박스와 라디오 버튼은 불리언 타입인 defaultChecked으로 초기값을 대신 지정해야 합니다.

form 제출 시 input 값 읽기

input 주위에 <form>을 추가하고 그 안에 <button type="submit">을 추가합니다. 그러면 <form onSubmit> 이벤트 핸들러가 호출됩니다. 기본적으로 브라우저는 form 데이터를 현재 URL로 전송하고 페이지를 새로 고칩니다. e.preventDefault()를 호출하여 이 동작을 재정의할 수 있습니다. new FormData(e.target)로 form 데이터를 읽습니다.

Note

모든 <input>에 name을 지정하세요(예: <input name="firstName" defaultValue="Taylor" />). 지정한 name은 form 데이터에서 키로 사용됩니다(예: { firstName: "Taylor" }).

Pitfall | 함정

기본적으로 <form>안에 있는 모든 <button>은 제출됩니다. 의외일 수 있습니다! 커스텀 Button React 컴포넌트가 있는 경우 <button> 대신 <button type="button">을 반환하는 것을 고려하세요. 그런 다음 form을 제출해야 하는 버튼에 <button type="submit">을 사용하세요.

state 변수로 input 제어하기

<input />과 같은 input은 제어되지 않습니다. <input defaultValue="Initial text" />와 같이 초기값을 전달하더라도 JSX는 초기값만 지정합니다. 현재 값이 무엇이어야 하는지는 제어하지 않습니다.제어된 input을 렌더링하려면 value prop을 전달하세요(체크박스와 라디오의 경우 checked). React는 입력이 항상 전달한 value를 갖도록 강제합니다. 보통은 state 변수를 선언하여 이를 수행합니다.
function Form() { const [firstName, setFirstName] = useState(''); // Declare a state variable... // state 변수 정의... // ... return ( <input value={firstName} // ...force the input's value to match the state variable... // ...input값이 state 변수와 일치하도록 강제... onChange={e => setFirstName(e.target.value)} // ... and update the state variable on any edits! // ... 그리고 수정할 때마다 state 변수를 업데이트하세요! /> ); }
어차피 state가 필요한 경우(예: 편집할 때마다 UI를 다시 렌더링해야 하는 경우) 제어 input이 적합합니다:
function Form() { const [firstName, setFirstName] = useState(''); return ( <> <label> First name: <input value={firstName} onChange={e => setFirstName(e.target.value)} /> </label> {firstName !== '' && <p>Your name is {firstName}.</p>} ...
다양한 방법으로 input state를 조정하는 기능을 제공하려는 경우(예: 버튼을 클릭하는 등)에도 유용합니다:
function Form() { // ... const [age, setAge] = useState(''); const ageAsNumber = Number(age); return ( <> <label> Age: <input value={age} onChange={e => setAge(e.target.value)} type="number" /> <button onClick={() => setAge(ageAsNumber + 10)}> Add 10 years </button>
제어 컴포넌트에 전달하는 value는 undefined 또는 null이어서는 안됩니다. 초기값을 비워야 하는 경우(아래의 firstName 필드와 같이) state 변수를 빈 문자열('')로 초기화하세요.

Pitfall | 함정

onChange 없이 value를 전달하면 input에 입력이 불가능합니다. 어떤 value를 전달해서 input을 제어하면 항상 전달한 값을 갖도록 강제하게 됩니다. 따라서 state 변수를 value로 전달했지만 onChange 이벤트 핸들러에서 해당 state 변수를 동기적으로 업데이트하는 것을 잊어버린 경우, React는 모든 키 입력 후 input을 사용자가 지정한 value로 되돌립니다.

모든 키 입력 리렌더링 최적화하기

제어 input을 사용할 때는 모든 키 입력에 state를 설정합니다. state가 포함된 컴포넌트가 큰 트리를 다시 렌더링하면 속도가 느려질 수 있습니다. 리렌더링 성능을 최적화할 수 있는 몇 가지 방법이 있습니다. 예를 들어, 모든 키 입력 시 모든 페이지 콘텐츠를 다시 렌더링하는 form으로 시작한다고 가정해 보겠습니다:
function App() { const [firstName, setFirstName] = useState(''); return ( <> <form> <input value={firstName} onChange={e => setFirstName(e.target.value)} /> </form> <PageContent /> </> ); }
PageContent />는 input state에 의존하지 않으므로 input state를 자체 컴포넌트로 이동할 수 있습니다:
function App() { return ( <> <SignupForm /> <PageContent /> </> ); } function SignupForm() { const [firstName, setFirstName] = useState(''); return ( <form> <input value={firstName} onChange={e => setFirstName(e.target.value)} /> </form> ); }
이제 모든 키 입력에 대해 SignupForm만 리렌더링하므로 성능이 크게 향상됩니다. 리렌더링을 피할 방법이 없는 경우(예: PageContent가 검색 input 값에 의존하는 경우), useDeferredValue를 사용하면 대규모 리렌더링 중에도 제어된 input의 반응성을 유지할 수 있습니다.

문제 해결

텍스트 input에 타이핑해도 업데이트되지 않습니다

input에 onChange 없이 value만 지정하여 렌더링하면 콘솔에 에러가 표시됩니다:
// 🔴 Bug: controlled text input with no onChange handler // 🔴 버그: 제어 텍스트 input에 onChange 핸들러가 없습니다 <input value={something} />
폼 필드에 onChange 핸들러가 없이 value prop만 제공했습니다. 이러면 읽기 전용 필드가 렌더링됩니다. 필드가 변경되어야 하는 경우 defaultValue를 사용하세요. 그렇지 않으면 onChange 또는 readOnly를 설정하세요.
오류메시지에서 알 수 있듯이, 초기값만 지정하려면 대신 defaultValue를 전달하세요:
// ✅ Good: uncontrolled input with an initial value // ✅ 좋음: 초기값을 제공한 비제어 input <input defaultValue={something} />
이 input을 state 변수로 제어하고 싶다면 onChange 핸들러를 지정하세요:
// ✅ Good: controlled input with onChange // ✅ 좋음: onChange가 있는 제어 input <input value={something} onChange={e => setSomething(e.target.value)} />
의도적으로 값을 읽기전용으로 하려는 경우, readOnly prop을 추가하여 오류를 억제하세요:
// ✅ Good: readonly controlled input without onChange // ✅ 좋음: onChange가 없는 읽기 전용 제어 input <input value={something} readOnly={true} />

체크박스를 클릭해도 업데이트되지 않습니다

체크박스에 onChange 없이 checked만 지정하여 렌더링하면 콘솔에 에러가 표시됩니다:
// 🔴 Bug: controlled checkbox with no onChange handler // 🔴 버그: 제어 체크박스에 onChange 핸들러가 없습니다 <input type="checkbox" checked={something} />
폼 필드에 onChange 핸들러가 없이 checked prop만 제공했습니다. 이러면 읽기 전용 필드가 렌더링됩니다. 필드가 변경되어야 하는 경우 defaultChecked를 사용하세요. 그렇지 않으면 onChange 또는 readOnly를 설정하세요.
오류메시지에서 알 수 있듯이, 초기값만 지정하려면 대신 defaultChecked를 전달하세요:
// ✅ Good: uncontrolled checkbox with an initial value // ✅ 좋음: 초기값을 제공한 비제어 체크박스 <input type="checkbox" defaultChecked={something} />
이 체크박스를 state 변수로 제어하고 싶다면 onChange 핸들러를 지정하세요:
// ✅ Good: controlled checkbox with onChange// ✅ 좋음: onChange가 있는 제어 체크박스<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />

Pitfall | 함정

체크박스의 경우 e.target.value가 아닌 e.target.checked를 읽어야 합니다.
의도적으로 값을 읽기전용으로 하려는 경우, readOnly prop을 추가하여 오류를 억제하세요:
// ✅ Good: readonly controlled checkbox without on change // ✅ 좋음: onChange가 없는 읽기 전용 제어 체크박스 <input type="checkbox" checked={something} readOnly={true} />

키를 누를 때마다 커서가 처음으로 이동합니다

제어 input의 경우 onChange 중에 state 변수를 DOM의 값으로 업데이트해야 합니다.
e.target.value(체크박스의 경우 e.target.checked)가 아닌 다른 값으로 업데이트할 수 없습니다:
function handleChange(e) { // 🔴 Bug: updating an input to something other than e.target.value // 🔴 버그: e.target.value가 아닌 다른 값으로 업데이트 시도 setFirstName(e.target.value.toUpperCase()); }
또한 비동기적으로 업데이트할 수 없습니다:
function handleChange(e) { // 🔴 Bug: updating an input asynchronously // 🔴 버그: 비동기적으로 업데이트 시도 setTimeout(() => { setFirstName(e.target.value); }, 100); }
이를 수정하려면, e.target.value를 동기적으로 업데이트하세요:
function handleChange(e) { // ✅ Updating a controlled input to e.target.value synchronously // ✅ 제어 input을 e.target.value로부터 동기적으로 업데이트 setFirstName(e.target.value); }
이렇게 해도 문제가 해결되지 않는다면, 키 입력 시마다 input이 DOM에서 제거되었다가 다시 추가되는 상황일 수 있습니다. 렌더링할 때마다 실수로 state를 재설정하는 경우 이런 문제가 발생할 수 있습니다. 예를 들어, input 또는 그 부모 중 하나가 항상 다른 key 속성을 받거나, 컴포넌트 정의를 중첩하는 경우(React에서는 허용되지 않으며, 렌더링할 때마다 “내부” 컴포넌트가 다시 마운트됩니다), 이런 일이 발생할 수 있습니다.

“컴포넌트가 비제어 입력을 제어하도록 변경하고 있습니다.” 라는 오류가 발생합니다

컴포넌트에 value 를 제공하는 경우, 그 값은 생명주기 동안 계속 문자열로 유지되어야 합니다.
React는 컴포넌트를 비제어 상태로 둘지 제어 상태로 둘지 알 수 없기 때문에, value={undefined}를 먼저 전달하고 나중에 value="some string"을 전달할 수 없습니다. 제어 컴포넌트는 항상 null이나 undefined가 아닌 문자열 value를 받아야 합니다.
value를 API나 state 변수에서 가져오는 경우, null 또는 undefined으로 초기화될 수 있습니다. 이 경우 처음에 빈 문자열('')로 설정하거나 value={someValue ?? ''}를 전달하여 value에 문자열이 오도록 보장하세요.
마찬가지로, 체크박스에 checked를 전달할 때는 항상 불리언인지를 확인하세요.