이미지 업로드 기능 만들기(AWS S3활용)

heyjk2212·2023년 11월 27일

TodayILearned

목록 보기
5/8
post-thumbnail

업로드한 이미지를 받기는 처음해보는데 너무 헷갈린다. 구글에서 많은 분들이 정리도 하셨지만 봐도 너무 어렵다. 서버쪽에서는 일단 확인이 불가능하니 내일 배포부터하고 맞춰보는 식으로 해야할 것 같다.

1. AWS S3 버킷 생성하기

비디오, 이미지 등의 파일을 저장해두는 기능을 제공하는 서비스이다.

2. aws-sdk 사용하여 s3 설정하기

yarn add aws-sdk

보안을 위해서 중요한 값은 env 파일에 설정해두어서 저렇게 process.env.{값}의 방식으로 사용한다.

import AWS from 'aws-sdk'

import dotenv from "dotenv";
dotenv.config();

AWS.config.update({
  region: process.env.AWS_REGION,
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
})

const s3 = new AWS.S3()

3. multer 이용하여 이미지 파일 받기

지금까지 s3에 접근이 가능하도록 만들었으니 기존의 json 형식이 아닌 이미지 파일(multipart/form-data)을 다룰 수 있도록 해야한다.

multer는 파일 업로드를 위해 사용되는 multipart/form-data를 다루기 위한 nodejs의 미들웨어이다. 즉, multer를 거치면 req.file로 내용을 넘겨주는 방식이다.

yarn add multer multer-s3

import AWS from 'aws-sdk'
import multer from "multer";
import multerS3 from "multer-s3";
import path from 'path';

import dotenv from "dotenv";
dotenv.config();

AWS.config.update({
  region: process.env.AWS_REGION,
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
})

const s3 = new AWS.S3()

// Multer-S3 설정에 대한 코드 
const upload = multer({
  storage: multerS3({
    s3: s3Client,
    bucket: "hanghae99-assets", // 생성한 버킷 이름을 넣어준다
    acl: "public-read",
    key: (req, file, callback) => {
      callback(null, `${Date.now().toString()}-${file.originalname}`);
    },
  }),
});

acl은 s3 생성할 때 권한 관련 설정이다.

업로드 기능(미들웨어 활용)

router.post('/image/add', upload.single("file"), (req, res)=>{
	res.send('success')
})

(수정)업데이트된 코드


import multer from "multer";
import fs from "fs";
import multerS3 from "multer-s3";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

import dotenv from "dotenv";
dotenv.config();

// AWS S3 클라이언트 설정
const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  },
});

const router = express.Router();

// Multer-S3 설정
const upload = multer({
  storage: multerS3({
    s3: s3Client,
    bucket: "hanghae99-assets",
    acl: "public-read",
    key: (req, file, cb) => {
      cb(null, `${Date.now().toString()}-${file.originalname}`);
    },
  }),
});

// 프로필 수정 API 엔드포인트 설정:
router.patch(
  "/users/:memberId/profile",
  authMiddleware,  // 사용자 인증 미들웨어
  upload.single("file"),  // 파일 업로드 미들웨어
  async (req, res, next) => {
    try {
      // const { memberId } = req.params;
      // const { mood, message, introduction } = req.body;
      // 클라이언트에서 받은 데이터의 유효성 검증
      const validation = await profileSchema.validateAsync(req.body);
      const validateParams = await profileSchema.validateAsync(req.params);
      const { memberId } = validateParams;
      const { mood, message, introduction } = validation;
      const user = req.user;  // 인증된 사용자 정보

      // 업로드된 이미지의 URL 가져오기
      const imageUrl = req.file.location; // S3에 업로드된 이미지의 URL

      // 프로필 주인이 로그인한 사용자와 일치하는지 확인
      if (user.memberId !== +memberId) {
        return res
          .status(403)
          .json({ errorMessage: "프로필을 업데이트 할 권한이 없습니다." });
      }

      // 파일 정보 확인을 위한 콘솔 로그
      console.log(req.file);

       // S3에 업로드된 파일의 URL을 사용하여 프로필 업데이트
      await prisma.profile.update({
        where: {
          MemberId: +memberId,
        },
        data: {
          mood,
          message,
          profileImage: imageUrl, // S3에 업로드된 파일의 URL
          introduction,
        },
      });

      return res.status(201).json({ message: "프로필이 수정되었습니다." });
    } catch (error) {
      console.error(error);

      return res.status(500).json({ error: "서버 에러" });
    }
  },
);

클라이언트가 이미지를 포함하여 요청을 보내면(/users/:memberId/profile 엔드포인트에 PATCH 메서드로 요청),
인증된 사용자인지 확인한 뒤, 이미지를 S3에 업로드하고 해당 URL을 프로필 정보와 함께 데이터베이스에 저장합니다.

여기서 Multer는 Node.js용 파일 업로드 미들웨어이며, Multer-S3는 Multer를 사용하여 AWS S3에 파일을 업로드하기 위한 설정을 제공합니다.

프로필 업데이트 로직은 데이터 유효성 검사, 사용자 권한 확인, 이미지 URL 저장, 데이터베이스 업데이트 등을 수행합니다.

profile
She can do it, He can do it, Why not me?

0개의 댓글