thumbnail

여러분의 프로젝트에서 폼은 어떻게 관리되고 있나요?

생성일2023. 12. 22.
태그
작성자지한솔

여러분의 프로젝트에서 폼은 어떻게 관리되고 있나요?
개발자로서 폼 관리는 프로젝트에서 빈번히 마주치는 작업 중 하나입니다. 일반적으로 개발자들은 간단하고 접근하기 쉬운 방법으로, 컴포넌트의 상태(State)를 이용해 폼을 관리합니다. 이러한 접근 방식은 단순한 프로젝트에는 효과적이지만, 프로젝트의 규모가 커지면서 성능 개선에 대한 고려가 필요해집니다.
성능 개선과 관련하여 가장 중요한 요소 중 하나는 리렌더링입니다. 리렌더링은 사용자 경험(UX)과 직결되기 때문에, 이를 최적화하는 것은 프로젝트의 성공에 결정적인 영향을 미칠 수 있습니다.
이 글에서는 상태를 사용한 기본적인 폼 관리 방법부터, 성능에 더 초점을 맞춘 다른 기술까지 다루어보려 합니다. 소규모 프로젝트에서 큰 문제가 되지 않을 수 있지만, 더 큰 규모의 프로젝트에서는 이러한 기술들이 큰 차이를 만들어낼 수 있습니다.

상태(state)를 활용한 폼 사용법

프로젝트 개발에서 폼 관리는 일반적으로 컴포넌트의 상태(State)를 활용하는 방식으로 이루어집니다. 이 방법은 간단하고 직관적이며, 리액트의 기본 원칙을 충실히 따르는 방식입니다. 특히, 작은 규모의 프로젝트에서는 이 접근법이 매우 효과적입니다.

상태(State)를 활용한 폼 관리의 예시

StateForm.tsx는 상태를 활용한 기본적인 폼 관리 방법을 보여주는 예시입니다. 이 예제에서는 두 가지 입력 필드(아이디와 비밀번호)가 있으며, 각 필드는 상태를 통해 관리됩니다. 이러한 방식은 폼의 데이터를 쉽게 추적하고, 이벤트 핸들링을 통해 사용자 입력을 처리할 수 있게 해줍니다.
import { FormEvent, useState } from "react"; import Input from "./common/Input"; import Form from "./common/FormWrap"; import Button from "./common/Button"; const StateForm = () => { const [id, setId] = useState(""); const [password, setPassword] = useState(""); const handelSubmit = (e: FormEvent<HTMLFormElement>) => { e.preventDefault(); console.log(id, password); }; console.log("리랜더링"); return ( <> <h2>Component State 사용</h2> <Form onSubmit={handelSubmit}> <Input type="text" value={id} onChange={(e) => setId(e.target.value)} /> <Input type="password" value={password} onChange={(e) => setPassword(e.target.value)} /> <Button type="submit">제출</Button> </Form> </> ); };
이 코드에서는 두 개의 useState 훅을 사용하여 각 입력 필드의 상태를 관리합니다. 사용자가 입력을 하면 onChange 이벤트가 발생하고, 이에 따라 상태가 업데이트됩니다. handleSubmit 함수는 폼 제출을 처리하며, 이 과정에서 폼의 데이터가 콘솔에 출력됩니다. 또한, 컴포넌트의 렌더링을 추적하기 위해 console.log("리랜더링")를 사용합니다.

성능 고려

notion image
이러한 접근 방식의 단순함과 명확함에도 불구하고, 성능 관점에서는 몇 가지 고려사항이 있습니다. 특히, 대규모 프로젝트에서는 각 상태 변경이 리렌더링을 유발하고, 이는 성능 저하로 이어질 수 있습니다. 따라서, 리렌더링을 최적화하고 상태 관리를 보다 효율적으로 수행하는 방법을 고민해야 합니다.

폼 관리의 진화: ID 기반 데이터 수집

리액트에서 폼 관리는 다양한 방법으로 이루어질 수 있습니다. 상태(State) 기반 관리가 일반적인 방법 중 하나이지만, 때에 따라서는 폼 요소의 ID를 활용한 데이터 수집 방식도 유용할 수 있습니다. 이 방법은 특히 동적인 폼 요소 처리나 복잡한 폼 구조에서 강력한 효과를 발휘합니다.

ID를 활용한 폼 데이터 수집의 예시

IdForm.tsx는 폼 내의 각 입력 요소의 ID를 기반으로 데이터를 수집하는 방법을 보여줍니다. 이 방식은 폼 내부의 모든 입력 요소를 순회하며, 해당 요소의 ID와 값을 매핑하여 객체 형태로 데이터를 구성합니다.
const IdForm = () => { const handelSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const target = e.currentTarget; // 폼 내의 모든 입력 요소를 순회 const inputs = Array.from(target.elements).filter( (element) => element.tagName === "INPUT" && element.id ); // ID와 값으로 구성된 객체 생성 const formData = inputs.reduce((acc, input) => { const inputElement = input as HTMLInputElement; acc[inputElement.id] = inputElement.value; return acc; }, {} as { [id in string]: string }); console.log(formData); // 수집된 데이터 출력 }; console.log("리랜더링"); // 렌더링 추적 return ( <> <h2>Element id 사용</h2> <Form onSubmit={handelSubmit}> <Input type="text" id="id" /> <Input type="password" id="password" /> <Button type="submit">제출</Button> </Form> </> ); };
이 코드는 폼의 onSubmit 이벤트 핸들러에서 폼의 모든 요소를 순회합니다. Array.from을 사용하여 폼 요소의 컬렉션을 배열로 변환한 후, filter 메서드를 사용해 INPUT 태그이면서 ID를 가진 요소만 선택합니다. 이후 reduce 메서드를 이용해 각 입력 요소의 ID를 키로, 값을 값으로 하는 객체를 생성합니다.

성능 고려

notion image
위 이미지처럼 state는 입력값이 변할때마다 리랜더링을 수행하지만 돔 요소에 접근해서 ID와 값의 쌍을 만들게 되면 리랜더링이 발생하지 않는것을 확인할 수 있습니다.
이 접근법은 상태 기반의 폼 관리와는 다른 방식으로, 폼의 동적인 요소 처리에 더욱 적합할 수 있습니다. 각 입력 요소의 상태를 개별적으로 추적하는 대신, 폼 전체의 데이터를 한 번에 처리하므로, 복잡한 폼에서의 성능 최적화에 유리할 수 있습니다.

FormData를 활용해보자.

리액트 개발에서 폼 데이터 처리는 다양한 방식으로 이루어질 수 있으며, 그 중 FormData API의 사용은 현대적이고 효율적인 접근법으로 꼽힙니다. FormData는 특히 복잡한 폼의 데이터를 간소화하고 성능을 향상시키는 데 큰 이점을 제공합니다.

FormData 폼 데이터 처리의 트렌디한 접근

FormData 객체는 폼의 DOM 요소를 통해 데이터를 수집하고 관리하는 강력한 방법을 제공합니다. 이 객체를 활용하면 폼 요소의 상태 관리를 간소화하고 리렌더링을 줄여 성능을 개선할 수 있습니다. 이제 FormData가 폼 요소를 어떻게 처리하는지 자세히 살펴봅시다.

1. FormData 객체의 생성과 초기화
FormData 객체는 new FormData(target)를 통해 생성됩니다. 여기서 target은 이벤트 핸들러에 연결된 폼의 DOM 요소를 가리킵니다.(해당 프로젝트에서는 HTMLFormElement) 이 초기화 과정에서 폼의 모든 요소가 FormData 객체에 의해 순회되며 데이터가 수집됩니다.
2. 폼 요소 순회 및 데이터 추출
FormData 객체는 폼 내의 input, select, textarea 등의 요소를 순회합니다. 이 과정에서 각 요소의 name 속성과 value 속성을 확인하고 수집합니다. 여기서 중요한 점은 name 속성이 없거나 비어 있는 입력 요소는 FormData에 포함되지 않는다는 것입니다.
3. 키-값 쌍의 데이터 저장
각 요소의 namevalue가 확인되면, FormData 객체는 이를 내부적으로 키-값 쌍으로 저장합니다. 이 데이터 구조는 폼의 전체 데이터를 효율적으로 나타내며, 이후에 쉽게 접근하고 조작할 수 있습니다.
4. FormData 메서드를 통한 데이터 접근
완성된 FormData 객체는 다양한 메서드(get, set, append, delete, has 등)를 통해 조작될 수 있습니다. 이러한 메서드를 사용하면 폼 데이터를 효과적으로 관리할 수 있습니다.
이처럼 FormData API를 사용하는 방법은 현대적인 웹 개발에서 강력하고 효율적인 접근 방식 중 하나입니다. 특히, 복잡한 폼 데이터를 처리하거나 파일 업로드와 같은 고급 기능이 필요할 때 FormData의 사용은 매우 유용합니다.

FormData를 활용한 폼 데이터 처리의 예시

이제 실전코드를 작성해볼 것입니다. FormDataForm.tsxFormData API를 이용하여 폼 데이터를 처리하는 방법을 보여줄 것입니다. 이 접근 방식은 폼의 데이터를 쉽게 수집하고, 구조화된 형태로 변환하여 처리할 수 있게 해줍니다.
const FormDataForm = () => { const handelSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const target = e.currentTarget; // FormData 객체 생성 const data = new FormData(target); // 폼 데이터를 객체 형태로 변환 const jsonData = Object.fromEntries(data.entries()); console.log(jsonData); // 변환된 데이터 출력 }; console.log("리랜더링"); // 렌더링 추적 return ( <> <h2>FormData 사용</h2> <Form onSubmit={handelSubmit}> <Input type="text" name="id" /> <Input type="password" name="password" /> <Button type="submit">제출</Button> </Form> </> ); };
이 코드에서 FormData 객체는 폼의 DOM 요소를 기반으로 생성됩니다. data.entries()를 통해 폼 데이터의 키-값 쌍을 순회할 수 있으며, Object.fromEntries 메서드를 사용하여 이를 일반 객체로 변환합니다. 이 과정은 폼 데이터를 쉽게 처리하고 원하는 키-값 쌍을 만들 수 있습니다.

성능 고려

notion image
FormData를 사용하는 방법은 폼의 각 입력 요소에 대한 상태 관리를 간소화할 수 있습니다. 이는 리렌더링을 줄이고 성능을 개선하는 데 도움이 될 수 있습니다. 특히, 대규모 폼이나 동적인 요소가 많은 폼에서 이 방식은 상태 관리보다 더 효과적일 수 있습니다.
 
FormData 에 대한 내용은 링크드인의 Jorge MollerJorge Moller 님 포스팅을 참고하였습니다. 저도 포스팅을 보고 FormData를 파일 업로드에만 사용해봤지 이렇게 사용해본적이 없어서 정말 신기했습니다. Input 리랜더링에 따른 성능개선이 항상 숙제였는데.. 좀 더 트렌디하게 성능개선을 할 수 있는 방법을 알게되었으니 실 프로젝트에도 적용해보고 싶다는 생각을 하게되었습니다.
포스팅에 사용 예제도 다 나와있지만 동작 방법과 예시를 좀 더 많은 사람들에게 공유하고자 작성하였으니, 도움이 된다면 정말 좋을 것 같습니다!