Express + Multer, 어렵지 않게 사용하기 - S3

2020. 6. 3. 21:35BACKEND/Node

반응형

안녕하세요 ❗️

오늘은 Express 를 사용해서 서버를 구축할 때, 이미지를 다루는 방법에 대해 알아볼 예정입니다.

지난 포스팅에서 이미지를 프로젝트 내부에 저장하는 방법을 배워 보았는데, 프로젝트 내부에 저장하게 되면 많은 불편함들이 있겠죠?

관리부터 배포, 권한까지 생각할 것들이 적지않아요 🤣

그래서, 오늘은 S3 를 사용해서 이미지를 public 하게 접근하는 방법을 알아볼게요 ❗️ 

 

솝트 서버파트✨분들은 솝커톤이나, 앱잼할 때 필요하실 수 있으니 집중 ~.~

코드는 깃 허브에 올려둘테니, 필요하신 분들은 보시면서 읽으면 좋을 것 같아요 〰️

 

⚠️ 해당 포스팅은 Express + Multer, 어렵지 않게 사용하기 에 이은 두 번째 게시글입니다. 

 

 

*****************  INDEX  *****************

 

🚀 S3 ❓ 

🌃 multer module with S3

 

******************************************** 

 


 

S3 ❓ 

S3가 무엇이길래, 이미지를 다룰 때 사용한다는 것일까요?

S3는 Simple Storage Service의 약자입니다. 이름이 직관적이라서 바로 와닿지 않나요~.~

AWS에서 제공해주는 파일 서버에 대한 역할을 해줍니다.

그래서 오늘 다룰 이미지뿐만 아니라, 다양한 형식의 파일들을 저장 및 보관해주죠 〰️ 

 

그럼 왜 S3를 사용하는 것일까요?

일단, 가장 큰 장점으로는 많은 사용자가 접속을 해도 이를 감당하기 위해서 시스템적인 작업을 하지 않아도 된다는 점입니다.

뿐만아니라 저장할 파일의 수에 제한이 없고, 파일에 인증을 붙여서 무단으로 엑세스 하지 못하도록 할 수도 있습니다.

사실 굉장히 많은 장점들이 있는데요.

이 포스터에서 S3를 다루는 큰 이유는 저장용량 5GB까지는 무료로 사용할 수 있다는 점입니다.

 

S3에서는 버킷이라는 개념을 사용하는데요.

일단, S3에서는 각각의 파일을 '객체'로 다루는데 이 객체들을 모아둔 최상위 디렉토리가 바로 버킷입니다.

 

자, 이제 직접 사용해보도록 하겠습니다.

 

 

 

Multer module with S3  🌃

 

지난 포스팅에서 아래와 같은 설정을 해두었습니다.

dest에 설정해둔 곳으로 전달된 파일들을 저장한다고 설정했습니다.

실제로, 이미지를 저장을 요청하면 /uploads/image_name 으로 파일이 저장되었죠.

 

이제는 uploads/ 가 아닌 S3가 우리의 dest이기 때문에 이 부분을 수정하면 되겠죠❓ 

다음과 같은 순서로 진행해보도록 하겠습니다.

 

1. multer-s3, aws-sdk module 설치

2. multer 설정 변경

    2.1 modules/multer.js 생성

    2.2 routes/user.js 

    2.3 controllers/user.js

    2.4 config/s3.js - S3 설정 파일 생성

3. .gitignore

 

 

1. multer-s3, aws-sdk 설치

프로젝트는 지난 시간에 생성한 것을 베이스로 사용하겠습니다.

잘모르시겠다면, 깃허브 소스를 참고하세요.

 

$ npm install --save aws-sdk multer-s3

 

터미널에서 위와 같이 입력해주세요.

multer모듈은 설치가 되어있다고 가정합니다.

 

 

 

2.1 modules/multer.js 생성

먼저, express 프로젝트에서 modules/ 디렉터리를 생성한 후, 그 아래에 multer.js 를 생성해주었습니다.

프로젝트 구조는 작성자 취향이니 굳이 안따라하셔도 됩니다.

 

const multer = require('multer');
const multerS3 = require('multer-s3');
const aws = require('aws-sdk');
aws.config.loadFromPath(__dirname + '/../config/s3.json');

const s3 = new aws.S3();
const upload = multer({
    storage: multerS3({
        s3: s3,
        bucket: '<s3-bucket-name>',
        acl: 'public-read',
        key: function(req, file, cb){
            cb(null, Date.now() + '.' + file.originalname.split('.').pop()); // 이름 설정
        }
    })
});
module.exports = upload;

 

modules/multer.js 에는 위와 같은 코드를 작성해주었습니다.

조오금 복잡해보이나요❓ 

걱정하지 마세요...! 같이 살펴볼게요❗️ 

 

가장 먼저 볼 것은 upload 상수입니다. upload는 multer에 대한 설정값들을 넣어줍니다.

s3 키에 넣어준 데이터를 보면 aws.S3()인 것을 확인할 수 있습니다.

aws에 대한 비밀 액세스 키와 비밀코드를 담아 정보를 넣어줍니다. 이 설정파일인 config/s3.json은 잠시 후에 생성하겠습니다.

이건 S3에서 버킷을 생성하면 설정을 통해 키와 비밀코드를 발급받을 수 있습니다.

 

두 번째로 bucket키에는 생성한 버킷의 이름을 적으면 됩니다.

acl 키는 Access control for the file 을 의미합니다. 

key는 주석과 동일하게 파일 이름을 설정해줍니다. 버킷 내의 파일 이름이 절대 겹치면 안되니 이름을 바꿔주어야 합니다 〰️ 

 

설정 값들을 정리해보면 아래와 같습니다.

 

key Description
size Size of the file in bytes
bucket The bucket used to store the file
key The name of the file
acl Access control for the file
contentType The mimetype used to upload the file
metadata The metadata object to be sent to S3
location The S3 url to access the file
etag The etagof the uploaded file in S3
contentDisposition The contentDisposition used to upload the file
storageClass The storageClass to be used for the uploaded file in S3
versionId The versionId is an optional param returned by S3 for versioned buckets

 

 

 

 

 

2.2 controllers/user.js 

이 번에는 routes/를 살펴보겠습니다.

 

var express = require('express');
var router = express.Router();
const UserController = require('../controllers/user');
// const multer = require('multer');
// const upload = multer({
//   dest: 'uploads/'
// });

const upload = require('../module/multer');

// POST METHOD - {{url}}/user/profile
router.post('/profile', upload.single('image'), UserController.uploadImage);

// POST METHOD - {{url}}/user/selfies
router.post('/selfies', upload.array('image', 4), UserController.uploadImages);

module.exports = router;

 

보면 4~7번 째 줄은 지난 포스팅에서 설정한 것인데, 이젠 modules/로 따로 빼두었기 때문에 지우시면 됩니다 〰️ 

지우는 대신 9번 째줄과 같이 upload를 정의해주셔야 합니다 〰️ 

 


2.3 config/s3.js - S3 설정 파일 생성

지난 번엔 req.file.path를 통해 이미지의 위치를 가져왔어요.

그런데 이번에는 path가 아니고 location으로 접근해야합니다.

다시 한 번 req.file 내부 데이터를 살펴볼까요? 

 

프로젝트 내부에 저장했을 때와는 다르게 데이터가 많이 늘어났네요!

지금 보셔야 할 건, path 키가 사라지고 location 키가 생성되었다는 점입니다.

 

그럼, 다시 controllers/user.js를 볼까요❓ 

 

const util = require('../modules/util');

module.exports = {
    uploadImage: async (req, res) => {
        console.log(req.file);
        const image = req.file.location;
        if (image === undefined) {
            return res.status(400).send(util.fail(400, "이미지가 존재하지 않습니다."));
        }
        res.status(200).send(util.success(200, "요청 성공 〰️ ", image));
    },
    uploadImages : async (req, res) => {
        const image = req.files;
        const path = image.map(img => img.location);
        if (image === undefined) {
            return res.status(400).send(util.fail(400, "이미지가 존재하지 않습니다."));
        }
        res.status(200).send(util.success(200, "요청 성공 〰️ ", path));
    }
}

 

위와 같이 수정하면 되겠죠 〰️ 

 

 

2.3 config/s3.js - S3 설정 파일 생성

자 이제 마지막 단계인 비밀 액세스 정보에 대한 파일을 생성하겠습니다.

벌써 마지막이에요. 생각보다 간단하지 않나요...?

 

이번에는 config/ 라는 설정모음 폴더를 하나 생성합니다. 

그리고 그 아래에 s3.json 을 생성합니다.

 

{
    "accessKeyId": "비밀 액세스 키 ID",
    "secretAccessKey": "비밀 액세스 키",
    "region": "ap-northeast-2"
}

 

json 파일이니, json 객체 하나만 있으면 완성 ~.~

아이디와 키 값을 적어주시면 됩니다.

 

🚨 주의사항 - 해당 파일은 절대 Github와 같은 공유 코드 저장소에 올리면 안됩니다.

 

 

3. .gitignore 

.gitgnore 에 config/ 를 꼭꼭 추가해주셔야 합니다.

 

//.gitignore

config/

 

반드시 최상위 폴더에 생성해주세요❗️ 

 

자, 그럼 이제 테스트를 해볼까요❓ 

테스트는 postman을 사용해보겠습니다. 

 

파일을 보낼 때에는 form-data 탭에서 보내는 거, 잊지 않으셨죠❓ 

 

 

이미지가 잘 저장되었네요 👏🏻👏🏻👏🏻

 

그럼 여기까지 이미지 다루기를 해보았습니다 〰️ 

개발하실 때 도움이 되었으면 좋겠네요 🙏🏻

반응형

Backend Software Engineer

Gyeongsun Park