자바스크립트에서 FormData 인터페이스를 사용할 때, 데이터가 키/값 쌍으로 추가되는데, 추가하는 키에 대한 타입 안전성을 강제하는 내장 방법이 없습니다. 이는 오타, 누락된 키 및 예기치 않은 런타임 오류로 이어질 수 있습니다. 그러나 TypeScript에서는 엄격한 키 유효성을 강제하여 이를 해결할 수 있습니다.
API에 폼 값을 보낼 때 스스로 이 솔루션이 필요했습니다. 후에 제가 페이로드에 추가하려고 시도한 여러 키/값 쌍에서 여러 오타를 발견했습니다. FormData는 키로 모든 문자열을 허용하기 때문에 잘못된 문자열을 전달하고 API 요청을 계속할 수 있었습니다.
이런 일이 일어난 후에는 TypeScript가 이러한 오류를 허용하지 않도록 하는 방법을 찾았습니다.
이 기사에서는 TypeScript를 사용하여 FormData
키를 타입 안전하게 만드는 방법을 보여줍니다.
전제 조건
이 기사를 최대한 활용하려면 다음에 대한 기본적인 이해가 있어야 합니다:
-
자바스크립트 프로그래밍
-
인터페이스, 타입 및
keyof
연산자가 작동하는 방법을 중점적으로 다루는 TypeScript 기본 사항 -
FormData 인터페이스
TypeScript나 FormData를 처음 접하는 경우, 진행하기 전에 TypeScript 공식 문서와 MDN의 FormData 가이드를 확인하는 것을 추천합니다.
1단계: 허용할 키 정의하기
구식 방법
FormData로 데이터를 추가하는 기본 방법은 일반 문자열을 사용하여 수동으로 하는 것입니다:
const payload = new FormData();
payload.append("id", "1122");
payload.append("name", "Clark Kent");
payload.append("agge", "36"); // 키에 오타가 허용됩니다
위의 코드 조각에서 age
키를 정의할 때 오타가 있음을 알 수 있습니다. 하지만 TypeScript는 이를 오류로 표시하지 않으며, 이 데이터가 API 요청과 함께 전송될 때 오류를 유발할 수 있습니다.
더 나은 방법
키를 수동으로 입력하는 대신, TypeScript 인터페이스를 사용하여 객체 스키마에서 정의하세요.
interface MyAllowedData {
id: number;
name: string;
age: number;
}
또는 타입으로 정의할 수도 있습니다:
type MyAllowedData = {
id: number;
name: string;
age: number;
}
타입이나 인터페이스 중 어떤 것을 사용해도 상관없으며, 이는 개인 취향의 문제입니다. 이 공식 TypeScript 문서 플레이그라운드에서 그 차이에 대해 더 알아볼 수 있습니다.
다음으로, 인터페이스의 각 키에서 유니온 타입을 정의하세요.
type MyFormDataKeys = keyof MyAllowedData
// 이는 `type MyFormDataKeys = 'id' | 'name' | 'age'`와 동일합니다
keyof
연산자는 객체 타입의 키들의 유니온 타입을 생성하는 데 도움을 주므로, 많은 키를 가진 큰 객체에 대해 수동으로 유니온 타입을 정의하고 싶지 않을 때 매우 유용합니다.
2단계: Append 헬퍼 함수 생성하기
엄격하게 타입이 정의된 키를 설정한 후, 다음 단계는 유효한 키만 FormData에 추가되도록 보장하는 헬퍼 함수를 생성하는 것입니다.
function appendToFormData (formData: FormData, key: MyFormDataKeys, value: string) {
formData.append(key, value);
};
appendToFormData
함수는 세 가지 인수를 받습니다. 작동 방식은 다음과 같습니다:
-
첫 번째 인수인
formData
는 FormData 객체의 인스턴스입니다. 여기서 키/값 쌍이 API 요청을 보내기 전에 추가됩니다. -
두 번째 인수인
key
는 추가하고자 하는 필드의 키 이름입니다. 그 타입은MyFormDataKeys
로, 우리가 정의한 키만 FormData에 추가되도록 보장하기 위해 생성한 유니온 타입입니다. -
세 번째 인수는 키와 함께 추가될 값을 나타내는 문자열
value
입니다.
다음에 유의하십시오 FormData는 string
및 Blob
타입만 각 키/값 쌍의 값으로 허용합니다. 이 가이드에서는 문자열 값만 사용하고 있지만, API 요청에 파일을 추가하기 위해 blob 값을 사용할 수 있다는 점을 기억하십시오.
이제 함수를 테스트해 보겠습니다:
const payload = new FormData();
appendToFormData(payload, "id", "19282"); // ✅ 허용됨
appendToFormData(payload, "name", "Lenny Brown"); // ✅ 허용됨
appendToFormData(payload, "age", "20"); // ✅ 허용됨
appendToFormData(payload, "someOtherKey", "89"); // ❌ TypeScript 오류: 'someOtherKey' 타입의 인수가 할당될 수 없습니다.
3단계: 양식 제출 후 도우미 함수 사용하기
이제 API에 전송하기 전에 FormData에 필드를 추가해 보겠습니다.
const handleSubmitForm = () => {
const payload = new FormData();
appendToFormData(payload, "id", "19282");
appendToFormData(payload, "name", "Lenny Brown");
appendToFormData(payload, "age", "20");
// API를 통해 페이로드 전송
fetch("/api/submit", { method: "POST", body: payload });
};
객체에서 필드 추가하기
또는 이미 전체 페이로드가 객체에 있는 경우, 다음과 같이 함수를 구현하여 각 필드를 하나씩 추가할 필요 없이 추가할 수 있습니다:
const handleSubmitForm = () => {
// 객체에 모든 필드
const formValues: MyAllowedData = {
id: 1123,
name: 'John Doe',
age: 56
}
const payload = new FormData();
Object.entries(formValues).forEach(([key, value]) => {
appendToFormData(payload, key as MyFormDataKeys, `${value}`); // 템플릿 리터럴을 사용하여 값을 전달합니다
});
// API를 통해 페이로드 전송
fetch("/api/submit", { method: "POST", body: payload });
};
위의 코드 조각에서는 Object.entries
를 사용하여 객체의 각 키/값 쌍을 반복하며 이를 FormData 객체에 추가합니다. 각 쌍의 값은 문자열이든 숫자든 템플릿 리터럴을 사용하여 문자열로 전달되어 TypeScript의 타입 불일치를 방지합니다.
결론
TypeScript의 keyof
연산자를 활용함으로써 FormData.append()
를 완전히 타입 안전하게 만들 수 있습니다. 이 간단한 기법은 키 불일치를 방지하고 API 요청을 더 신뢰할 수 있게 만듭니다.
이 기사에 대한 여러분의 생각을 알려주시고, 제 솔루션을 개선할 수 있는 제안이 있다면 자유롭게 말씀해 주세요.
읽어 주셔서 감사합니다!
Source:
https://www.freecodecamp.org/news/how-to-enforce-type-safety-in-formdata-with-typescript/