목차
폼(Form) 컨트롤
리액트에서 폼을 올바르게 다루는 것은 사용자 경험(UX)과 접근성을 높이는 데 매우 중요하다. HTML에서 <form> 요소는 Enter 키나 제출 버튼을 누르면 페이지를 새로고침하는 기본 작동을 가지고 있다. 하지만 리액트에서는 이벤트 핸들러에서 e.preventDefault()를 호출하여 이 기본 동작을 막고, 자바스크립트를 통해 폼 제출을 제어하는 것이 일반적이다.
폼 제출은 onClick 이벤트보다는 onSubmit 이벤트를 사용하는 것이 좋다. onSubmit은 버튼 클릭뿐만 아니라 Enter 키 입력까지 모두 처리하기 때문에 더 안전하고 편리하다.
입력 컨트롤: 제어된 vs. 제어되지 않은
리액트에서 폼 입력값을 관리하는 방식은 크게 두 가지로 나뉜다.
- 제어된(Controlled) 입력: value와 onChange 속성을 사용하여 입력값을 리액트 상태(state)로 관리하는 방식이다. 입력값이 바뀔 때마다 UI를 실시간으로 업데이트하거나, 여러 입력값을 동기화하는 등 복잡한 기능을 구현할 때 적합하다.
- 제어되지 않은(Uncontrolled) 입력: defaultValue 속성을 사용하며, 입력값은 DOM이 직접 관리한다. 리렌더링이 발생하지 않기 때문에 대규모 폼에서 성능에 유리하고, 폼 제출 시점에만 값이 필요할 때 유용하다.
입력 타입 | 제어된(Controlled) 방식 | 제어되지 않은(Uncontrolled) 방식 |
<input /> | value, onChange | defaultValue |
<input type="checkbox" /> | checked, onChange | defaultChecked |
<textarea> | value, onChange | defaultValue |
<select> | value, onChange | defaultValue |
<option> | selected |
단방향 데이터 흐름
리액트의 핵심 개념인 단방향 데이터 흐름을 이해하면 폼을 더욱 효과적으로 관리할 수 있다. 단방향 데이터 흐름 원칙에 따라 데이터는 항상 부모 컴포넌트에서 자식 컴포넌트로 전달된다. 자식 컴포넌트가 부모의 상태를 직접 변경할 수 없기 때문에, 입력값이 바뀔 때는 부모가 전달한 함수를 호출하여 부모의 상태 변경을 요청해야 한다. 이러한 구조는 데이터 흐름을 예측 가능하게 만들어 복잡한 앱도 관리하기 쉽게 만든다.
폼 라이브러리 활용
복잡한 폼은 직접 구현할 경우 작업량이 많고 유지보수가 어렵다. 이러한 문제를 해결하기 위해 많은 개발자가 React Hook Form, Formik, React Final Form과 같은 라이브러리를 사용한다. 폼 라이브러리를 활용하면 코드를 간결하게 만들고, 유효성 검증과 같은 작업을 효율적으로 처리할 수 있다.
폼 라이브러리는 빠르게 변화하기 때문에 항상 최신 문서를 참고하고 핵심 개념을 이해하는 것이 중요하다. 그러면 향후 변화에 쉽게 적응하고 대응할 수 있다.
오늘 하루를 돌아보며
폼을 관리할 때 단방향 데이터 흐름을 잘 이해해야겠다. 이 구조를 잘 지키면 앱이 커져도 예측 가능하고 유지보수하기 쉬운 코드를 만들 수 있다. 상태 관리 위치와 데이터 전달 방향을 명확히 하는 것도 중요하다. 그리고 무엇보다 접근성을 항상 염두에 두고 컴포넌트를 설계해야 한다! 내가 만든 앱을 나만 사용한다는 편견을 버리고, 누구라도 사용할 수 있고, 누구라도 불편함을 느끼지 않는 앱을 만들자!