React

Controlled Input 패턴

1space 2025. 11. 29. 17:16

React에서 여러 input 필드를 다룰 때, 각 input마다 onChange를 따로 만들 필요 없이 하나의 handleChange 함수로 모든 입력을 처리할 수 있습니다.
핵심은 input의 name 속성과 상태 객체(state)를 연동하는 방법입니다.

 

코드 구조

const [formData, setFormData] = useState({
    userId: '',
    password: ''
  });

const handleChange = (e) => {
  const { name, value } = e.target; // ① 구조 분해 할당
  setFormData(prev => ({            // ② 상태 업데이트
    ...prev,                        // 이전 상태 복사
    [name]: value                   // 해당 input만 덮어쓰기
  }));
};

 

  • e: onChange 이벤트 객체
  • e.target: 이벤트가 발생한 실제 요소 (<input> 등)
  • name: input의 name 속성 (userId, password)
  • value: 사용자가 입력한 실제 값

 

동작

① e와 e.target

  • e는 이벤트 객체, onChange 이벤트가 발생하면 React가 전달합니다.
  • e.target은 실제 이벤트 발생 요소입니다. 예를 들어:
<input name="userId" onChange={handleChange} />
<input name="password" onChange={handleChange} />

 

  • 첫 번째 input에서 e.target → userId input
  • 두 번째 input에서 e.target → password input

② 구조 분해 할당

const { name, value } = e.target;
  • e.target.name → "userId" 또는 "password"
  • e.target.value → 사용자가 입력한 값
  • 예시:
    • 아이디 칸에 abc 입력 → name = "userId", value = "abc"
    • 비밀번호 칸에 1234 입력 → name = "password", value = "1234"

③ 상태 업데이트

setFormData(prev => ({
  ...prev,
  [name]: value
}));
  • prev → 이전 상태 객체
prev = { userId: 'oldId', password: 'oldPw' }
  • ...prev → 이전 상태를 그대로 복사
  • [name]: value → name에 해당하는 키만 새 값으로 덮어쓰기
  • 결과 예시:
    • 아이디 input 수정 → { userId: 'abc', password: 'oldPw' }
    • 비밀번호 input 수정 → { userId: 'abc', password: '1234' }

 

왜 이렇게 쓰는가?

  • 필드별로 onChange를 따로 만들 필요가 없음
  • input의 name만 다르게 주면, 하나의 handleChange로 모든 필드를 처리 가능
  • React Controlled Input 패턴:
<input value={formData.userId} onChange={handleChange} />
<input value={formData.password} onChange={handleChange} />

 

 

 

  • 상태가 화면을 제어하고, 화면이 상태를 반영
  • 화면과 상태가 항상 동기화됨

 

비교: 각각 따로 만드는 방식

const handleUserIdChange = (e) => setFormData(prev => ({ ...prev, userId: e.target.value }));
const handlePasswordChange = (e) => setFormData(prev => ({ ...prev, password: e.target.value }));
  • 장점: 단순, 이해하기 쉬움
  • 단점: input이 많아지면 함수도 늘어나고 반복 코드가 많아짐