본문으로 건너뛰기
프론트엔드 기초집LESSON 10

폼과 Controlled Component

난이도초급
예상 시간35분
선수지식이전 강의

10강. 폼과 Controlled Component

1. 이번 강의에서 해결할 문제

입력 요소가 늘어나면 각 DOM 값과 React state가 어긋나기 쉽습니다. 검색 조건을 예측 가능하게 관리하고 폼 제출 시 페이지가 새로고침되지 않게 해야 합니다.

2. 학습 목표

  • controlled input의 value와 onChange를 연결한다.
  • submit 이벤트의 기본 동작을 제어한다.
  • 여러 폼 값을 하나의 상태 객체로 갱신한다.

3. 핵심 개념

Controlled Component는 입력값의 원본을 React state에 두는 방식입니다. input의 value는 state에서 받고 onChange로 state를 갱신합니다. 따라서 버튼으로 초기화하거나 여러 조건을 한 번에 적용하기 쉽습니다.

객체 state를 바꿀 때는 기존 객체를 직접 수정하지 않고 펼침 문법으로 새 객체를 만듭니다.

4. 단계별 코드 예시

파일 경로: game-release-dashboard/src/components/FilterForm.tsx

import { useState, type FormEvent } from 'react';

type Filters = { query: string; platform: string };
type FilterFormProps = { onApply: (filters: Filters) => void };

export function FilterForm({ onApply }: FilterFormProps) {
const [draft, setDraft] = useState<Filters>({
query: '',
platform: 'all',
});

function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
onApply(draft);
}

function resetFilters() {
const empty = { query: '', platform: 'all' };
setDraft(empty);
onApply(empty);
}

return (
<form onSubmit={handleSubmit}>
<label>
게임 제목
<input
value={draft.query}
onChange={(event) =>
setDraft({ ...draft, query: event.target.value })
}
/>
</label>
<label>
플랫폼
<select
value={draft.platform}
onChange={(event) =>
setDraft({ ...draft, platform: event.target.value })
}
>
<option value="all">전체</option>
<option value="PC">PC</option>
<option value="Console">Console</option>
</select>
</label>
<button type="submit">적용</button>
<button type="button" onClick={resetFilters}>초기화</button>
</form>
);
}

5. 코드가 동작하는 이유

브라우저의 submit은 기본적으로 페이지를 이동시키므로 preventDefault로 막습니다. 입력할 때마다 새 draft 객체가 만들어지고, 적용 버튼은 현재 초안을 부모 콜백에 전달합니다. 초기화 버튼은 submit이 아니므로 type을 명시합니다.

6. 자주 하는 실수와 해결법

  • value만 지정하고 onChange 누락: 입력이 읽기 전용이 됩니다. 둘을 함께 연결합니다.
  • draft.query = ...로 직접 수정: 새 객체를 setter에 전달합니다.
  • 모든 버튼이 폼을 제출: 보조 버튼은 type="button"을 사용합니다.
  • label 없는 입력: 보이는 label 또는 명확한 aria-label을 제공합니다.

7. 직접 실습

최소 랭킹 점수를 입력하는 number input을 추가하세요. 빈 문자열은 허용하고 제출할 때 0~100 범위인지 검사해 오류 문구를 표시하세요.

8. 이해 점검 질문 3개

  1. controlled input의 데이터 원본은 어디인가요?
  2. 폼 submit에서 preventDefault가 필요한 이유는 무엇인가요?
  3. 객체 state를 직접 수정하면 왜 문제가 되나요?

9. 핵심 요약

제어 폼은 입력값을 state와 동기화합니다. 제출, 검증, 초기화를 React 흐름 안에서 일관되게 처리할 수 있습니다.

MINI QUIZ

폼과 Controlled Component 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“폼과 Controlled Component” 내용을 실제 작업에 적용한 설명으로 가장 알맞은 것은 무엇인가요?
  2. 문제 2‘label 없는 입력’ 실수를 판단할 때 “폼과 Controlled Component” 강의가 제시한 기준은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

10강. 폼과 Controlled Component 미완료 상태