목차
React에서 폼 처리는 사용자 입력을 관리하고 상호작용하는 중요한 부분이다.
폼 처리의 접근 방식에는 제어 컴포넌트
와 비제어 컴포넌트
가 있는데 오늘은 이 둘의 차이를 알아보려한다.
제어 컴포넌트 vs 비제어 컴포넌트
제어 컴포넌트 (Controlled Components)
제어 컴포넌트는 React의 useState를 통해 폼 데이터를 관리한다.
각 폼 요소의 값은 컴포넌트의 state에 저장되고, 변경 이벤트를 통해 업데이트된다.
특징
- 상태 관리: React의 state로 폼 데이터를 관리한다.
- 실시간 유효성 검사: 입력값이 변경될 때마다 즉시 검증할 수 있다.
- 조건부 렌더링: 입력값에 따라 UI를 동적으로 변경할 수 있다.
- 중앙화된 데이터 흐름: 단일 소스의 진실(Single Source of Truth)를 유지한다.
예시
import React, { useState, FormEvent, ChangeEvent } from 'react';
interface FormData {
username: string;
email: string;
password: string;
}
const ControlledSignUpForm: React.FC = () => {
const [formData, setFormData] = useState<FormData>({
username: '',
email: '',
password: ''
});
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prevData => ({
...prevData,
[name]: value
}));
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log('Submitted:', formData);
// API 호출 등의 로직
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
name="username"
value={formData.username}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</div>
<button type="submit">Sign Up</button>
</form>
);
};
export default ControlledSignUpForm;
비제어 컴포넌트 (Uncontrolled Components)
비제어 컴포넌트는 DOM 자체에 폼 데이터를 저장한다.
React의 useState 대신 ref를 사용하여 필요할 때 DOM에서 폼 값을 가져온다.
특징
- 간단한 구현: 적은 코드로 빠르게 구현할 수 있다.
- DOM 참조: ref를 사용하여 DOM에 직접 접근한다.
- 성능: 리렌더링이 적어 성능상 이점이 있을 수 있다.
- 외부 라이브러리 통합: 일부 서드파티 라이브러리와의 통합이 더 쉬울 수 있다.
예시
import React, { useRef, FormEvent } from 'react';
const UncontrolledSignUpForm: React.FC = () => {
const usernameRef = useRef<HTMLInputElement>(null);
const emailRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const username = usernameRef.current?.value;
const email = emailRef.current?.value;
const password = passwordRef.current?.value;
console.log('Submitted:', { username, email, password });
// API 호출 등의 로직
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username:</label>
<input type="text" id="username" ref={usernameRef} defaultValue="" />
</div>
<div>
<label htmlFor="email">Email:</label>
<input type="email" id="email" ref={emailRef} defaultValue="" />
</div>
<div>
<label htmlFor="password">Password:</label>
<input type="password" id="password" ref={passwordRef} defaultValue="" />
</div>
<button type="submit">Sign Up</button>
</form>
);
};
제어 vs 비제어 컴포넌트 비교
특성 | 제어 컴포넌트 | 비제어 컴포넌트 |
---|---|---|
데이터 관리 | React state | DOM |
값 접근 | 언제든지 state를 통해 | ref로 필요할 때만 |
실시간 검증 | 쉬움 | 어려움 |
조건부 렌더링 | 쉬움 | 어려움 |
구현 복잡도 | 상대적으로 높음 | 낮음 |
성능 | 많은 리렌더링(디바운싱, 쓰로틀링 필요) | 적은 리렌더링 |
초기값 설정 | state 초기값 | defaultValue 속성 |
외부 라이브러리 통합 | 때때로 어려움 | 대체로 쉬움 |
테스트 용이성 | 상대적으로 쉬움 | 상대적으로 어려움(DOM 조작으로 인해) |
사용시기
- 제어 컴포넌트:
- 실시간 입력 검증이 필요한 경우
- 조건부 렌더링이 필요한 복잡한 폼
- 폼 데이터를 다른 UI 요소와 즉시 동기화해야 하는 경우
- 비제어 컴포넌트:
- 간단한 폼이나 일회성 데이터 제출
- 파일 입력과 같은 비제어 요소를 다룰 때
- 레거시 코드나 비-React 라이브러리와 통합할 때
React에서 폼 처리는 사용자 입력을 관리하고 상호작용하는 중요한 부분이다.
폼 처리의 접근 방식에는 제어 컴포넌트
와 비제어 컴포넌트
가 있는데 오늘은 이 둘의 차이를 알아보려한다.
제어 컴포넌트 vs 비제어 컴포넌트
제어 컴포넌트 (Controlled Components)
제어 컴포넌트는 React의 useState를 통해 폼 데이터를 관리한다.
각 폼 요소의 값은 컴포넌트의 state에 저장되고, 변경 이벤트를 통해 업데이트된다.
특징
- 상태 관리: React의 state로 폼 데이터를 관리한다.
- 실시간 유효성 검사: 입력값이 변경될 때마다 즉시 검증할 수 있다.
- 조건부 렌더링: 입력값에 따라 UI를 동적으로 변경할 수 있다.
- 중앙화된 데이터 흐름: 단일 소스의 진실(Single Source of Truth)를 유지한다.
예시
import React, { useState, FormEvent, ChangeEvent } from 'react';
interface FormData {
username: string;
email: string;
password: string;
}
const ControlledSignUpForm: React.FC = () => {
const [formData, setFormData] = useState<FormData>({
username: '',
email: '',
password: ''
});
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prevData => ({
...prevData,
[name]: value
}));
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log('Submitted:', formData);
// API 호출 등의 로직
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
name="username"
value={formData.username}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</div>
<button type="submit">Sign Up</button>
</form>
);
};
export default ControlledSignUpForm;
비제어 컴포넌트 (Uncontrolled Components)
비제어 컴포넌트는 DOM 자체에 폼 데이터를 저장한다.
React의 useState 대신 ref를 사용하여 필요할 때 DOM에서 폼 값을 가져온다.
특징
- 간단한 구현: 적은 코드로 빠르게 구현할 수 있다.
- DOM 참조: ref를 사용하여 DOM에 직접 접근한다.
- 성능: 리렌더링이 적어 성능상 이점이 있을 수 있다.
- 외부 라이브러리 통합: 일부 서드파티 라이브러리와의 통합이 더 쉬울 수 있다.
예시
import React, { useRef, FormEvent } from 'react';
const UncontrolledSignUpForm: React.FC = () => {
const usernameRef = useRef<HTMLInputElement>(null);
const emailRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const username = usernameRef.current?.value;
const email = emailRef.current?.value;
const password = passwordRef.current?.value;
console.log('Submitted:', { username, email, password });
// API 호출 등의 로직
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username:</label>
<input type="text" id="username" ref={usernameRef} defaultValue="" />
</div>
<div>
<label htmlFor="email">Email:</label>
<input type="email" id="email" ref={emailRef} defaultValue="" />
</div>
<div>
<label htmlFor="password">Password:</label>
<input type="password" id="password" ref={passwordRef} defaultValue="" />
</div>
<button type="submit">Sign Up</button>
</form>
);
};
제어 vs 비제어 컴포넌트 비교
특성 | 제어 컴포넌트 | 비제어 컴포넌트 |
---|---|---|
데이터 관리 | React state | DOM |
값 접근 | 언제든지 state를 통해 | ref로 필요할 때만 |
실시간 검증 | 쉬움 | 어려움 |
조건부 렌더링 | 쉬움 | 어려움 |
구현 복잡도 | 상대적으로 높음 | 낮음 |
성능 | 많은 리렌더링(디바운싱, 쓰로틀링 필요) | 적은 리렌더링 |
초기값 설정 | state 초기값 | defaultValue 속성 |
외부 라이브러리 통합 | 때때로 어려움 | 대체로 쉬움 |
테스트 용이성 | 상대적으로 쉬움 | 상대적으로 어려움(DOM 조작으로 인해) |
사용시기
- 제어 컴포넌트:
- 실시간 입력 검증이 필요한 경우
- 조건부 렌더링이 필요한 복잡한 폼
- 폼 데이터를 다른 UI 요소와 즉시 동기화해야 하는 경우
- 비제어 컴포넌트:
- 간단한 폼이나 일회성 데이터 제출
- 파일 입력과 같은 비제어 요소를 다룰 때
- 레거시 코드나 비-React 라이브러리와 통합할 때