[Problem]
첫 주특기 프로젝트. 현재 작업하고 있는 프로젝트는 요즘 유행하고 있는 카카오톡 오픈 채팅 '거지방'을 게시글로 올리는 형식으로 바꾸는 프로젝트이다. 거지방은 최근 고금리 고물가에 청년세대를 중심으로 극단적 절약을 하는 모습을 올리는 오픈 채팅 방이다. 프로젝트 명은 '왕초', 형태는 게시판이다.
게시글을 작성해서 post할 때 title, content, image를 올려야 하는데 이때 image를 파일 형태로 올릴 때 body로 받아서 올리는 것은 한계가 있다는 것을 깨달았다. 따라서 오늘의 문제점은 image를 정상적으로 구현이 가능하게 작업하는 것이다.
[Try]
sequelize를 이용하고 있기에 sequelize를 이용해서 image를 정상적으로 올릴 수 있는 형태가 무엇이 있을 까 웹 서칭을 통해 찾아보았다. 찾은 결과 multer이라는 모듈을 사용하면 구현이 가능하다는 것을 알게 되었다. 기본적인 사용 방법은 다음과 같다.
- npm install multer, path (multer과 path 모듈 설치)
- image를 받아 올 폴더를 설정 및 파일을 읽어 올 수 있게 이름을 재설정
- 파일을 받아 올 때 확장자 필터링
- 현재 작업한 부분을 다시 불러 올 수 있게 미들웨어 작업
위와 같은 방법으로 실행해보자.
- image를 받아 올 폴더를 설정 및 파일을 읽어 올 수 있게 이름을 재설정
const fileStorage = multer.diskStorage({
// 저장 방식
destination: (req, file, cb) => {
// 저장되는 곳 지정
cb(null, path.join(__dirname, "../uploads/"));
},
filename: (req, file, cb) => {
// 저장되는 이름 지정
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
multer.diskStorage는 함수를 사용하여 파일 저장 방식을 설정한다. destination은 파일이 저장될 경로를 지정한다. __dirname는 현재 실행 중인 JS 파일의 디렉토리 경로를 나타낸다. ../uploads/는 현재 디렉토리의 상위 디렉토리에 있는 폴더를 의미한다. 따라서 현재 작업 중인 폴더 안에 image파일을 받아 올 수 있는 폴더를 하나 생성한다. 폴더 이름은 자유롭게 작성하지만 상위 디렉토리에 있는 폴더 명에 동일하게 작성해준다. filename은 저장될 팔일의 이름을 지정한다. 업로드된 파일의 원래 이름과 업로드 시간을 조합하여 고유한 피일 이름을 생성해준다.
- 파일을 받아 올 때 확장자 필터링
const fileFilter = (req, file, cb) => {
// 확장자 필터링
const allowedFileTypes = [
"image/png",
"image/jpg",
"image/jpeg",
"image/gif",
"image/bmp",
];
if (allowedFileTypes.includes(file.mimetype)) {
cb(null, true); // 해당 mimetype만 받겠다는 의미
} else {
// 다른 mimetype은 저장되지 않음
cb(null, false);
}
};
allowedFileTypes 배열에 허용된 파일 유형을 정의한다. 현재 작성된 부분을 보면 png, jpg, jpeg, gif, bmp만 허용한다. file.mimetype은 업로드된 파일의 MIME 유형을 나타낸다. cb(null, true)는 허용된 MIME 유형의 파일을 허용한다는 의미, cb(null, false)는 허용되지 않은 MIME 유형의 파일을 거부한다는 의미.
- 미들웨어 작업
const upload = multer({ storage: fileStorage, fileFilter: fileFilter }).single("image");
storage, fileFilter는 multer의 속성이다. storage는 파일 저장 방식, fileFilter는 파일 필터링이다. 뒤에 single("image")는 하나의 파일만 업로드할 수 있음을 의미한다. image는 해당 파일의 필드 이름이다.
[Solution]
위에 작업들을 따로 토큰 미들웨어 처럼 따로 파일을 만들어도 된다. 현재 나는 posts.js에 같이 넣었다.
중요한 건 사용할 때 router에 미들웨어를 꼭 넣어줘야 한다.
router.post("/api/posts", auth, upload, async (req, res) => {
//....중간 생략
}
이렇게 토큰 미들웨어처럼 multer 미들웨어를 넣어줘야 한다.
또 하나 중요한 부분은
const image = req.file
이렇게 router안에서 image부분을 file형식으로 요청해야 한다. Thunder Client로 검사를 진행할 때도 form에서 files로 설정하고 검사를 진행해야 한다.
기능 구현은 했고 정삭적으로 들어가는 것도 확인했다.
정상적으로 들어가는 것을 확인할 수 있다.
But 현재 게시글에는 title, content, image를 받아와야 하는데 Thunder Client로는 동시에 검사를 할 수 없기에 FE와 검사를 진행할 때 제대로 동작을 하는 지 확인할 수 있을 것으로 예상된다.
[Conclusion]
multer의 장점
- 다중 파일 업로드 지원: 클라이언트가 여러 개의 파일을 동시에 업로드할 수 있다. 대량의 파일을 한 번에 처리할 수 있다.
- 파일 유형 및 크기 제한: 특정 파일 형식이나 크기를 제한할 수 있다. 악의적인 사용자로부터의 업로드를 방지하거나, 서버 리소스를 보호할 수 있다.
- 보안 강화: 파일 업로드 시 보안을 강화할 수 있다. 파일 업로드 시 허용된 파일 형식만 허용하거나, 파일 이름을 변조하여 다른 경로에 저장되는 것을 방지할 수 있다.
- 비동기 처리: 비동기적으로 파일 업로드를 처리하므로, 블로킹되지 않고 다른 작업을 게속할 수 있다. 서버의 성능을 향상시키는 데 도움이 된다.
- 커스터마이징 가능: 다양한 설정 옵션과 미들웨어 체인과 함께 사용될 수 있다. 이를 통해 개발자는 필요에 따라 파일 업로드 처리를 커스터마이징할 수 있다.
현재 진행 중인 프로젝트에 multer을 사용해서 image를 받아올 수 있다는 부분을 깨달았다.
image를 받아 올 수 있는 방법은 다양할 것이다. 분명 multer 모듈을 적절하게 사용하면 좋을 것이라 생각된다.
But 분명 multer의 단점이 존재할 것이다.
multer의 단점에 대해서 알아보자
- 파일 크기 제한이 있다. 서버 측에서 처리 가능한 파일 크기를 초과하는 대용량 파일의 업로드를 방지하기 위해 설정이 필요하다. 따라서 대용량 이미지 파일을 업로드해야 할 경우에는 제한에 맞게 파일을 조정해야 한다.
- 디스크 공간을 사용한다. 이미지를 서버에 저장하는 효과적인 방법이지만, 많은 사용자가 많은 크기의 파일을 업로드할 경우 디스클 공간을 많이 차지할 수 있다. 따라서 서버의 디스크 용량에 주의해야 한다.
- 악성 코드나 악의적인 파일이 업로드될 수 있다. 따라서 업로드된 파일을 검증하고 처리하는 추가적인 보안 검사가 필요하다.
- 이미지 업로드는 일반적으로 대량의 데이터 전소을 필요로 한다. 많은 사용자가 동시에 업로드하는 경우 서버의 네트워크 대역폭을 소비할 수 있다. 이는 서버의 성능에 양향을 줄 수 있다. 트래픽 관리와 대역폭 용량을 고려해야 한다.
- Multer은 이미지를 업로드하고 저장하는 데에 초점을 맞춘 라이브러리이다. 따라서 이미지의 크기 조정, 형식 변환, 썸네일 생성 등과 같은 고급 이미지 처리 작업을 수행하려면 별도의 이미지 처리 라이브러리를 추가로 사용해야 한다.
이런 부분을 고려했을 때 괜찮다고 생각했을 때 multer을 사용하는 것을 추천한다.
'Self Dev. > TIL' 카테고리의 다른 글
2023.05.30 TIL - 토큰에서 사용되는 Bearer는 무엇인가? (0) | 2023.05.30 |
---|---|
2023.05.21 TIL - JWT를 header로 받는 이유.... (1) | 2023.05.21 |
2023.05.11 TIL - Sequelize (timestamp) (0) | 2023.05.11 |
2023.05.07 TIL - MySQL 데이터베이스 (Sequelize를 이용하여 Drop하기) (0) | 2023.05.07 |
2023.04.28 TIL - mongoose ObjectId (0) | 2023.04.28 |