개발이야기

[TIL]29. Node 환경에서 AWS S3에 이미지 업로드

무서운승태 2023. 11. 29. 09:55
728x90

이번 팀 프로젝트를 진행하던 중 영화 리뷰를 적어서 소통하는 사이트를 개발하기로 했다. 영화 리뷰를 작성할 때 사진을 넣는 기능이 필수라고 생각이 들어서 이미지 업로드 방법에 대하여 검색하였다.

 

내가 과거에 자바를 공부할때 진행했던 방식은 물리적인 파일을 내 프로젝트에 보관하고 모든 파일 정보를 DB에 저장을 했었다.

그러나 이런 방식은 파일 자체를 우리 서버에 보관하기 때문에 상당히 많은 리소스를 차지한다는 것을 알았고 보통 물리적인 파일과 같은 데이터들은 외부 스토리지를 이용하여 저장하고 그 경로만 DB에 저장하는 식으로 사용한다고 한다. 그래서 그 원격 스토리지인 S3에 이미지를 업로드하는 방법을 알아보겠다.

 

1.AWS S3 버킷 생성

버킷을 만들면 다음과 같이 나온다.

 

2.AWS IAM 계정 만들기

AWS IAM -> 사용자 -> 사용자 생성 

생성을 진행하다보면 권한에 대하여 설정할 수 있는 화면이 나온다. 여기서 우리는 S3만 사용할 것이기 때문에 해당 권한을 선택한다.

생성완료하면 액세스키와 시크릿키를 받을수 있는데 바로 사용해야 하니 메모해 두자

 

3.Node에서 Multer와 AWS-SDK 패키지 준비하기

multer는 node에서 파일업로드를 할 수 있게 하는 미들웨어이고 AWS-SDK는 AWS서비스를 프로그래밍에서 제어할 수 있도록 만든 패키지이다. 다음과 같이 npm을 이용하여 설치한다.

npm i multer aws-sdk

 

4.Multer 와 AWS-SDK의 초기 세팅을 해준다.

multer는 body데이터와 file데이터를 reqeust객체에 추가해 주는데 그 옵션을 지정할 수 있다. 자세한 API와 옵션들은 아래에서 확인할 수 있다.

https://github.com/expressjs/multer/blob/master/doc/README-ko.md

const storage = multer.memoryStorage();
const filefilter = (req, file, cb) => {
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
        cb(null, true);
    } else {
        cb(null, false);
    }
};

export const upload = multer({
    storage,
    filefilter,
});

storage, filefilter옵션을 줘서 upload라는 변수에 담아주었고 export로 외부에서 사용할 것이기 때문에 내보내주었다.

 

s3객체를 생성해 주는데 아까 발급받은 액세스키와 시크릿키를 기입해 주고 내가 만든 버킷리전을 입력해 준다. 이것도 외부에서 사용해야 하기 때문에 export 해준다.

export const s3 = new AWS.S3({
    region: process.env.REGION_KEY,
    accessKeyId: process.env.ACCESS_KEY,
    secretAccessKey: process.env.SECRET_ACCESS_KEY,
});

5. 실제 클라이언트 요청에서 처리해 주기

// 게시글 작성 API
postsRouter.post('/', upload.single('file'), async (req, res) => {
   const file = req.file // 파일객체를 받을수 있게 된다.
   
   //파일 객체를 바탕으로 params라는 객체를 생성해준다.
    const params = {
        Bucket: 'my-kimbuket', // s3 버킷 이름
        Key: v4(), // 저장될 파일 이름 나는 랜덤으로 파일이름을 바꿨다.
        Body: file.buffer,
        ContentType: file.mimetype,
        ACL: 'public-read',// 해당 옵션을 주어야 외부에서 접근이 가능하다.
    };
    
    // 실제 s3에 저장
    const result = await s3.upload(params).promise();
});