let formData = new FormData();
/* new FormData 해당 폼 요소의 필드가 전체 자동 반영이 된다.
key와 value 값을 통해 데이터들을 생성할 수 있다. */
const previewImg = (e: React.ChangeEvent<HTMLInputElement>) => {
let file = e.target.files![0];
const sizeCheck = 5 * 1024 * 1024; //선택한 이미지의 파일 크기 체크
if (file && file.size > sizeCheck) {
alert("5MB 이하의 크기의 파일을 선택해주세요.");
} else {
setImageUrl(URL.createObjectURL(file)); //blob파일을 임시 URL 생성
setImgFile(file);
}
};
const addPreview = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
const previews = [imageUrl, previewText]; //이미지와 캡션을 배열에 추가
if (imageUrl === "") alert("이미지를 등록해주세요.");
if (previewText === "") alert("설명을 등록해주세요.");
if (imageUrl && previewText) {
setPreviewText("");
setPreviewList([...previewList, previews]);
setContent([...content, previewText]);
setImgFiles([...imgFiles, imgFile]);
}
};
🖐️ URL.createObjectURL 사용 구조
이미지 blob 파일을
URL로 변환하여 이미지를 해당 윈도우에서 렌더 할 수 있도록 만들었다. 해당 URL은 사용자의 Window에서만 작동이 되고 Window를 종료시 자동으로 사라지는 구조이다. 하지만 createObjectURL를 통해 만들어진 url는 해당 브라우저가 존재한 상태에서 revokeObjectURL 메소드로 URL을 무효화 시키지 않으면 js 엔진에서 자동삭제를 시키지 않고 계속 변수가 남아 메모리 누수가 된다. 그렇기 때문에 url 사용을 종료하면 revokeObjectURL 메소드를 사용하여 브라우저가 더이상 이 객체를 메모리에 들고 있지 않아도 된다고 알려야 한다.
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
if (title === "") {
alert("제목을 입력해주세요");
} else if (imgFiles.length === 0) alert("이미지를 등록해주세요.");
else {
const formData = new FormData();
formData.append("postTitle", title);
tags.forEach((tag) => {
formData.append("postHashTags", tag);
});
imgFiles.forEach((img) => {
formData.append("postImageFiles", img);
});
content.forEach((text) => {
formData.append("postContents", text);
});
axios
.post(`/posts/register/${id}`, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((res) => {
navigate(`/posts/detail/${res.data.data.postId}`);
})
.catch((err) => console.error(err));
}
};
key
와 value
값을 객체 형태로 만들어 서버로 전달한다.string
,number
,file
타입 등의 단일 값만 전송이 되므로 배열에 담긴 값들은 forEach문을 이용하여 최종적으로 서버로 전달한다.