← 전체 글로 돌아가기

Next.js

React 폼 상태를 한 객체로 묶었다가 검증을 나눈 이유

체크박스의 false 값이 서버에 전달되지 않던 폼 오류를 상태와 검증 규칙으로 분리한 회고입니다.

저장했는데 알림 설정이 돌아왔다

프로필에서 닉네임을 바꾸고 알림을 끄면 닉네임만 저장됐다. 화면에는 두 값이 모두 바뀌었지만, value || undefined로 만든 요청 데이터가 false를 누락 값으로 바꾸고 있었다. false와 아직 입력하지 않은 undefined를 구분하지 않은 것이 원인이었다.

화면 상태는 입력을 그대로 담는다

const [form, setForm] = useState({ nickname: initial.nickname ?? '', marketing: !!initial.marketing });
const update = (name, value) => setForm((current) => ({ ...current, [name]: value }));
<input value={form.nickname} onChange={(e) => update('nickname', e.target.value)} />
<input type="checkbox" checked={form.marketing} onChange={(e) => update('marketing', e.target.checked)} />

입력 상태에는 빈 문자열, false, 0도 남겨야 한다. 전송 직전 변환은 별도의 검증 뒤에 실행한다.

function validateProfile(value) {
  const errors = {};
  if (value.nickname.trim().length < 2) errors.nickname = '두 글자 이상 입력하세요.';
  return errors;
}
const errors = validateProfile(form);
if (Object.keys(errors).length === 0) {
  await fetch('/api/profile', { method: 'PATCH', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ nickname: form.nickname.trim(), marketing: form.marketing }) });
}

남긴 테스트 기준

  • 체크박스를 켰다 끄면 본문에 false가 있는가
  • 공백 닉네임이 요청 전에 막히는가
  • 오류가 다른 입력값을 지우지 않는가
  • 실패 후 사용자의 입력이 보존되는가

폼 상태와 API 계약을 분리하니 조건부 필드를 추가해도 값의 의미가 흔들리지 않았다.