- 같이 보면 좋은 글
2023.05.16 TIL - express에 multer 모듈을 이용해 image 업로드...
[Problem] 첫 주특기 프로젝트. 현재 작업하고 있는 프로젝트는 요즘 유행하고 있는 카카오톡 오픈 채팅 '거지방'을 게시글로 올리는 형식으로 바꾸는 프로젝트이다. 거지방은 최근 고금리 고물가
yoonsoo-space.tistory.com
[Problem]
실전 프로젝트에 추가 기능을 넣는 단계이다.
오늘의 문제는 추가 기능 중 하나인 프로필 수정 기능이다. 다른 프로젝트에서 사용하던 multer 라이브러리를 이용하여 서버에 이미지를 저장할 생각을 했다.
But 서버에 이미지를 저장하는 것은 서버의 디스크 공간을 직접 사용하게 되기 때문에 데이터 관리가 복잡해질 수 있다.
또한 서버의 용량 한계에 도달하면 이미지 저장에 문제가 발생할 수 있다.
하드웨어 고장, 손상 또는 데이터 손실에 대비하기 위해 서버는 별도의 백업 시스템을 구축해야 한다.
서버에 이미지를 저장하면 사용자들이 해당 서버에 직접 접근해 이미지를 다운로드해야 한다. 이는 서버에 대한 전송 대역폭을 소모하고 서버의 성능에 영향을 미칠 수 있다.
마지막으로 서버에 이미지를 저장하면 보안 측면에서 별도의 노력이 필요하다. 데이터 유출과 악의적인 접근을 막기 위해 강력한 보안 시스템을 구축해야 한다. 그리고 유저의 수가 늘어남에 따라 백업비용 등 추가로 더 비용이 많이 발생하게 된다.
따라서 이미지를 저장할 수 있는 공간을 따로 관리할 필요가 있다.
[Try]
생각한 방법은 두 가지가 있었다.
1. 데이터베이스를 이용한 이미지 저장
- 이미지 데이터를 저장하기 위한 별도의 테이블이나 컬렉션을 생성하여 이미지를 관리하는 방법이다. 이때 이미지는 바이너리 형태로 저장된다. 데이터 베이스 시스템의 백업과 보안 체계를 활용하여 이미지의 안전성을 유지할 수 있으며 이미지와 관련된 메타데이터를 함께 저장하여 이미지에 대한 추가 정보를 관리하기 용이하다. 마지막으로 복잡한 이미지 처리 작업이 필요할 경우, 이미지 데이터를 쿼리하여 데이터베이스 내에서 처리가 가능하다.
- But 데이터 베이스 내에서 이미지 처리가 복잡할 경우가 있다. 서버 용량 한계에 영향을 받을 수 있으며 유저가 늘어남에 따라 비용도 추가적으로 발생할 것이다. 따라서 데이터 베이스는 이미지를 관리하고 검색하는 용도로 사용하는 것이 적절하다.
2. S3를 이용한 이미지 저장
- 클라우드 기반이므로 필요에 따라 용량을 확장하거나 축소할 수 있다. S3는 전 세계에 분산된 서버에 이미지를 저장하고, CDN을 통해 사용자에게 이미지를 빠르게 전송할 수 있다. 비용적으로 클라우드 서비스는 사용한 만큼만 비용을 지불하므로 다른 방법보다 비용면에서 절약이 가능하다. 마지막으로 클라우드 제공 업체는 보안에 많은 노력을 기울이고 있으며, 백업과 복원 기능을 제공하여 데이터 손실 가능성이 줄어든다.
[Solution]
따라서 S3를 이용해 이미지 storage를 생성했다.
현재 프로젝트는 아마존 S3와 연결되어 있는 Lightsail을 이용하여 생성했다.
==> 생성할 때 주의 해야하는 부분은 생성과 함께 제공해주는 Access key의 ID와 Secret access key를 따로 기록해 놓아야 한다.
- 준비하기
npm i multer aws-sdk
==> multer과 access key를 사용이용하게 해주는 라이브러리 aws-sdk를 설치한다. 이때 aws-sdk의 버전을 알아둔다.
==> 본인은 2.1420.0버전을 사용 중
==> 이에 맞춰 multer-s3도 버전을 설치한다.
npm i multer-s3@2
- 사용하기
const { v4: uuid } = require("uuid");
const multer = require("multer");
const multerS3 = require("multer-s3");
const AWS = require("aws-sdk");
const path = require("path");
// s3 설정
require("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 설정
const upload = multer({
storage: multerS3({
s3: s3,
contentType: multerS3.AUTO_CONTENT_TYPE,
acl: "public-read",
bucket: process.env.AWS_BUCKET,
key: (req, file, callback) => {
const ext = path.extname(file.originalname);
callback(null, Date.now().toString() + uuid() + ext);
},
// 용량 제한
limits: { fileSize: 5 * 1024 * 1024 },
}),
});
// 기존 이미지를 S3에서 삭제하는 함수
const deleteOldImage = async (url) => {
if (!url) return; // URL이 제공되지 않으면 아무것도 삭제하지 않고 리턴
const key = url.split("/").pop();
const params = { Bucket: process.env.AWS_BUCKET, Key: key };
try {
await s3.deleteObject(params).promise();
} catch (error) {
console.error(
"기존 이미지를 S3에서 삭제하는데 오류가 발생했습니다:",
error
);
}
};
==> uuid를 이용한 것은 프로필 이미지에 각각의 고유 값을 부여하기 위해서다.
==> 위에 코드를 이용해서 프로젝트에 맞게 적용시키고 다음은 api부분에서 미들웨어로 이미지를 저장할 수 있게 만든다.
==> 또한 프론트 엔드에서 쉽게 사용할 수 있게 데이터 베이스에 파일 경로를 저장해준다.
[Conclusion]
이미지 저장을 성공한 모습이다.
다음 사이드 프로젝트에서도 쉽게 적용할 수 있어 너무 기분이 좋다.
'Self Dev. > TIL' 카테고리의 다른 글
2023.07.25 TIL - HTTPS를 이용한 쿠키 설정 (0) | 2023.07.26 |
---|---|
2023.05.30 TIL - 토큰에서 사용되는 Bearer는 무엇인가? (0) | 2023.05.30 |
2023.05.21 TIL - JWT를 header로 받는 이유.... (1) | 2023.05.21 |
2023.05.16 TIL - express에 multer 모듈을 이용해 image 업로드... (0) | 2023.05.16 |
2023.05.11 TIL - Sequelize (timestamp) (0) | 2023.05.11 |