피드관리 - 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)

설계 이유

  1. 게시물-이미지 관계 관리
    - postId를 외래 키로 사용하여 각 이미지가 어떤 게시물에 속하는지 명확하게 관리할 수 있습니다.
  2. 데이터 무결성
    - 외래 키 제약 조건 : 게시물이 삭제되면 관련된 이미지도 자동으로 삭제됩니다.

> 외래키 제약 조건

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);
      }
    );
  });
});