현재 MERN 프로젝트에서는 Image를 multer를 이용해서 local에 직접 이미지를 저장해서 사용하고 있었습니다. 하지만 이렇게 하다보니까 문제가 생겼습니다. 배포된 서버에서 이미지를 처음에 올리고 나서는 괜찮았지만 다음번에 접속하면 해당 이미지파일이 사라졌는지 모르겠지만 제대로 이미지를 보내주지 않더군요.
그리고 제가 알기로는 이상적으로 이미지를 관리하려면 따로 이미지만 다루는 스토리지를 구축하고 DB에서는 해당 이미지에 대한 full path를 제공하는거라고 알고 있습니다.
일단 S3 Bucket을 만들어야합니다.
이와 같이 체크할 거 체크해주고, 버킷만들어줍니다.
IAM 에서 사용자 추가를 해줍니다.
접근을 하기위해서 엑세스 ID랑 비밀 엑세스 ID를 가져야하거든요.
S3 Bucket으로 가서 정책을 수정해줘야합니다.
편집을 누르고 아래 정책을 넣어줍니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicListGet",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::{bucket name}/*"
}
]
}
그리고 이제 아까 IAM 사용자 추가하면서 받았던 엑세스 아이디와 비밀 엑세스아이디, 그리고 서버 지역까지 awsconfig.json에 담아서 밑에 코드 처럼하셔도 되지만,
// file-upload.js
const AWS = require('aws-sdk');
const here = path.join(__dirname, '..', '/awsconfig.json')
AWS.config.loadFromPath(here);
// awsconfig.json
{
"accessKeyId": "AKIAUEDLWK3XXIP2ES7E",
"secretAccessKey": "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",
"region": "ap-northeast-2"
}
환경 변수에 추가해서 편하게 이렇게 하셔도 됩니다.
const creds = new AWS.Credentials({
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY
});
const myAWS = new AWS.Config({
credentials: creds,
region: process.env.S3_REGION,
})
AWS.config.update(myAWS);
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Credentials.html#constructor-property
그리고 나서 이제 controller에서 응답 보내줄때 image를 s3 bucket에 담겨있는 key값으로 보내주고, 프론트쪽에서는 bucket 링크만 환경변수로 지정하고 image src에다가 넣어주면 정상 동작이 됩니다.
file-upload 최종 코드
const multer = require('multer')
const multerS3 = require('multer-s3');
const AWS = require('aws-sdk');
require('dotenv').config();
// 환경 변수에서 엑세스 키 가져와 새로운 AWS.Credentials 객체 생성
const creds = new AWS.Credentials({
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY
});
// 환경 변수에서 Region과 기존 Credentials 객체를 가져와
// 나만의 configuration 새로 설정합니다.
const myAWS = new AWS.Config({
credentials: creds,
region: process.env.S3_REGION,
})
// 새로 설정된 configuration을 업데이트 해줍니다.
AWS.config.update(myAWS);
// 업로드할 수 있는 이미지 타입 설정
const MIME_TYPE_MAP = {
'image/png': 'png',
'image/jpg': 'jpg',
'image/jpeg': 'jpeg',
}
const fileUpload = multer({
limits: { fileSize: 500000 },
storage: multerS3({
s3: new AWS.S3(),
bucket: 'place-ive-been',
acl: 'public-read',
contentType: multerS3.AUTO_CONTENT_TYPE,
key: function(req, file, cb) {
cb(null, `${Date.now().toString()}${file.originalname}`);
},
fileFilter: (req, file, cb) => {
const isValid = !!MIME_TYPE_MAP[file.mimetype]
let error = isValid ? null : new Error('Invalid mime type!')
cb(error, isValid);
}
}),
});
module.exports = fileUpload;
'Project > MERN' 카테고리의 다른 글
Google Maps 관련 API 사용기 (0) | 2023.01.10 |
---|---|
에러 - validateDOMNesting(...): <button> cannot appear as a descendant of <button>. (0) | 2023.01.02 |
에러 - Do not use 'new' for side effects. (0) | 2022.12.22 |
에러 - Visible, non-interactive elements with click handlers must have at least one keyboard listener. (1) | 2022.12.20 |
에러 - Type null is not assignable to type T.ts(2345) (0) | 2022.12.16 |