피드관리 - Part 1 피드작성 (3) 여러 장의 이미지 입력
ㆍProject Diary/React + MariaDB (PicShare WebApp)
사용자가 피드 작성 시 여러 이미지를 업로드하고 미리보기 할 수 있는 기능을 구현합니다. 이 글에서는 이미지 업로드 핸들러, 이미지 미리보기 UI, 서버 측 이미지 저장 로직, 그리고 데이터베이스 설계를 다룹니다.
데이터베이스
- posts 테이블 - postId : 게시물 ID (Primary Key, Auto Increment)
- images 테이블 - imageId : 이미지 ID (Primary Key, Auto Increment)
- images 테이블 - postId : 게시물 ID (Foreign Key)
설계 이유
- 게시물-이미지 관계 관리
- postId를 외래 키로 사용하여 각 이미지가 어떤 게시물에 속하는지 명확하게 관리할 수 있습니다. - 데이터 무결성
- 외래 키 제약 조건 : 게시물이 삭제되면 관련된 이미지도 자동으로 삭제됩니다.
> 외래키 제약 조건
CONSTRAINT `images_ibfk_1` FOREIGN KEY (`postId`) REFERENCES `posts` (`postId`) ON DELETE CASCADE
프론트
1. 이미지 여러 개 업로드 기능
1-1 이미지 업로드 핸들러
// 이미지 업로드 핸들러
const handleImageUpload = (e) => {
const files = Array.from(e.target.files); // 업로드된 파일 배열 생성
setImages(files); // 파일 배열을 상태로 설정
};
- handleImageUpload: 사용자가 업로드한 이미지를 상태로 설정합니다.
- Array.from(e.target.files): 업로드된 파일들을 배열로 변환합니다.
- setImages: 파일 배열을 상태로 설정합니다.
1-2 이미지 업로드 UI
미리보기 이미지를 보여주며, 더 많은 이미지가 있을 경우 추가 이미지를 표시합니다.
<div className="image-upload-section">
{images.length > 0 ? (
<div className="images">
{images.slice(0, 3).map((file, idx) => (
<img
key={idx}
src={URL.createObjectURL(file)}
alt="upload preview"
/>
))}
{images.length > 3 && <span>+{images.length - 3} more</span>}
</div>
) : (
<div
className="images"
style={{ border: "1px solid #ccc", borderRadius: "5px" }}
>
<p>photo</p>
</div>
)}
<input
type="file"
multiple
accept="image/*"
onChange={handleImageUpload}
/>
</div>
- 업로드된 이미지가 있을 경우, 최대 3개의 미리보기 이미지를 보여줍니다.
- 3개 이상의 이미지가 있을 경우, 추가 이미지 수를 표시합니다.
백엔드
1. 이미지 저장
// images 테이블에 이미지 저장
const imageInsert = files.map((file) => {
const imageUrl = file.filename;
return new Promise((imageres, imagedata) => {
db.query(
`INSERT INTO images (postId, imageUrl) VALUES (?, ?)`,
[postId, imageUrl],
(err, result) => {
if (err) {
console.error("image 인서트 오류:", err);
return imagedata(err);
}
imageres(result);
}
);
});
});