☁️충북대 구름톤 유니브 4기
1. React의 Form
1.1 Controlled Components
값이 React의 state에 의해 제어되는 폼 요소를 말합니다.

1.1.1 예시
// input 태그
<input type="text" value={value} onChange={handleChange} />
// textarea 태그
<textarea value={value} onChange={handleChange} />
// select 태그
<select value={value} onChange={handleChange}>
<option value="apple">사과</option>
<option value="banana">바나나</option>
<option value="grape">포도</option>
<option value="watermelon">수박</option>
</select>
1.2 textarea 태그
긴 텍스트 입력을 받기 위한 태그입니다.
import React, { useState } from 'react';
function RequestForm() {
const [value, setValue] = useState('요청사항을 입력하세요.');
const handleChange = (event) => {
setValue(event.target.value);
};
const handleSubmit = (event) => {
alert('입력한 요청사항: ' + value);
event.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
<label>
요청사항:
<textarea value={value} onChange={handleChange} />
</label>
<button type="submit">제출</button>
</form>
);
}
1.3 select 태그
드롭다운 형태로 옵션을 선택할 수 있는 태그입니다.
import React, { useState } from 'react';
function FruitSelect() {
const [selectedFruit, setSelectedFruit] = useState('grape');
const handleChange = (event) => {
setSelectedFruit(event.target.value);
};
return (
<form>
<label>
과일 선택:
<select value={selectedFruit} onChange={handleChange}>
<option value="apple">사과</option>
<option value="banana">바나나</option>
<option value="grape">포도</option>
<option value="watermelon">수박</option>
</select>
</label>
<p>선택한 과일: {selectedFruit}</p>
</form>
);
}
1.3.1 다중 선택 예시
<select multiple={true} value={selectedOptions} onChange={handleChange} />
const selected = Array.from(event.target.selectedOptions, (option) => option.value);
1.4 file input 태그
사용자가 파일을 선택할 수 있도록 하는 태그입니다.
- 파일 입력은 읽기 전용으로, uncontrolled component입니다.
import React, { useState } from 'react';
function FileUploadExample() {
const [fileName, setFileName] = useState('');
const handleFileChange = (event) => {
const file = event.target.files[0];
if (file) {
setFileName(file.name);
}
};
return (
<form>
<label>
파일 업로드:
<input type="file" onChange={handleFileChange} />
</label>
<p>선택된 파일: {fileName}</p>
</form>
);
}
1.5 여러 개의 상태 선언 및 입력 처리
여러 입력 필드가 있을 경우, 각각의 useState를 사용하여 상태를 관리합니다.
import React, { useState } from 'react';
function Reservation() {
const [haveBreakfast, setHaveBreakfast] = useState(true);
const [numberOfGuest, setNumberOfGuest] = useState(2);
const handleSubmit = (event) => {
alert(`아침식사 여부: ${haveBreakfast}, 방문객 수: ${numberOfGuest}`);
event.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
<label>
아침식사 여부:
<input
type="checkbox"
checked={haveBreakfast}
onChange={(e) => setHaveBreakfast(e.target.checked)}
/>
</label>
<br />
<label>
방문객 수:
<input
type="number"
value={numberOfGuest}
onChange={(e) => setNumberOfGuest(e.target.value)}
/>
</label>
<br />
<button type="submit">제출</button>
</form>
);
}
1.6 input에 null을 넘기면?
<input value={null} />
- value={null}을 설정하면 React는 해당 input을 uncontrolled component로 간주합니다.
- 이후에는 사용자가 자유롭게 입력할 수 있게 됩니다.
2. Lifting State Up
여러 컴포넌트가 같은 상태를 공유해야 할 경우, 상태를 공통 부모 컴포넌트로 끌어올립니다.

function Parent() {
const [value, setValue] = useState('');
return (
<>
<ChildA value={value} onChange={setValue} />
<ChildB value={value} />
</>
);
}
function ChildA({ value, onChange }) {
return (
<input value={value} onChange={(e) => onChange(e.target.value)} />
);
}
function ChildB({ value }) {
return <p>입력값: {value}</p>;
}
2.1 언제 써야 할까?
- 여러 컴포넌트가 동일한 데이터를 기반으로 렌더링될 때
- 자식 컴포넌트 간 상태 동기화가 필요할 때
- 데이터 흐름을 명확히 유지하고 싶을 때
3. Composition vs Inheritance

React는 상속보다 합성(Composition)을 권장합니다.
3.1 Composition - Containment
하위 컴포넌트를 포함하는 형태의 합성 방법
- sidebar, dialog 같은 box형태의 컴포넌트는 자신의 하위 컴포넌트를 미리 알 수 없다.
- childen 이라는 props를 사용해서 조합.
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">{props.left}</div>
<div className="SplitPane-right">{props.right}</div>
</div>
);
}
function App() {
return (
<SplitPane left={<Contacts />} right={<Chat />} />
);
}
3.2 Composition - Specialization
범용적인 개념을 구별이 되도록 구체화하는 것
- 객체 지향 언어에서는 상속으로 구현. 여기서는 합성으로 구현.
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">{props.title}</h1>
<p className="Dialog-message">{props.message}</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="어서 오세요"
message="우리 사이트에 방문하신 것을 환영합니다!"
/>
);
}
3.3 상속보다 합성을 추천하는 이유
- 컴포넌트를 더 작게 쪼개고,
- 필요한 컴포넌트들을 조합해서 유연하게 UI를 구성할 수 있기 때문입니다.
'FrontEnd > React' 카테고리의 다른 글
| [React] Context API (0) | 2025.05.20 |
|---|---|
| [React] useState와 useEffect (0) | 2025.04.10 |
| [React] REACT란? / JSX란? / Element란? (0) | 2025.04.03 |