NestJS와 AWS S3를 사용해 파일 저장 및 삭제하기 💼

Cherry·2022년 8월 10일
0
post-thumbnail
post-custom-banner

파일 관리 방법

💡 blob 사용

파일 데이터를 저장해야할 때 가장 단순한 방법은 다른 타입의 데이터들과 마찬가지로 파일도 데이터를 그대로 DB에 저장하는 방법일 것이다.

이럴 때에는 blob을 사용할 수 있다.

blob (Binary Large Object, 블랍)은 이미지, 사운드, 비디오와 같은 멀티미디어 데이터를 다룰 때 사용할 수 있는 JavaScript 타입으로 이름에서 알 수 있듯이 바이너리 데이터를 저장할 수 있다.

blob에 대한 자세한 내용은 아래의 글을 참고하면 좋을 것 같다.
Blob(블랍) 이해하기

나는 blob 타입으로 직접 저장 후 프론트에 전달하는 것보다는 클라우드 스토리지에 이미지를 올리고 프론트에서 직접 접근할 수 있는 url을 전달해주는 것이 더 편할 것이라고 판단하여 클라우드 스토리지를 사용하였다.

(클라우드 스토리지 설정 다 하고 알게된 사실은 blob도 직접 데이터를 저장하는 것이 아니라 위치 포인터값을 저장한다고 한다...!)

🛢 클라우드 스토리지 사용

클라우드 스토리지를 사용하는 방법은 파일을 클라우드 스토리지에 저장하고 파일 접근이 가능한 url을 DB에 저장하는 것이다.

이번 프로젝트에서는 AWS S3를 사용하여 파일을 저장하였다. NestJS로 구성한 서버에서 AWS S3를 어떻게 사용할 수 있는지 알아보자.

1. AWS S3 홈페이지 로그인

aws s3 홈페이지
위의 링크로 이동하여 로그인을 하자.

2. 버킷 생성

로그인 후에는 파일을 저장할 Bucket을 생성해야 한다.
해당 Bucket 안에 전송한 파일들이 모여서 저장된다.

(1) 버킷 이름 지정

원하는 버킷 이름을 지정해준다.

(2) 액세스 차단 해제

외부에서 url로 접근할 예정이기 때문에 모든 퍼블릭 액세스 차단해제해준다.

(3) 버킷 만들기

다른 설정은 그대로 유지한 채 버킷 만들기 버튼을 누르면 버킷이 만들어진다.

3. 정책 설정

위에서 퍼블릭 액세스 차단을 해제해줬지만 기본적인 AWS의 정책은 Denied이기 때문에 따로 정책을 정의해줘야 url을 통한 직접 접근이 가능하다.

아까 만들어준 버킷에 들어가 권한 메뉴의 버킷 정책을 아래와 같이 정의해주자. (버킷에 저장된 object에 대한 외부 접근을 Allow 로 설정해주는 정책이다.)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[버킷 이름]/*"
        }
    ]
}

4. NestJs에서 파일 업로드하고 삭제하기

이제 NestJs 서버에서 앞서 만들어준 버킷에 파일을 업로드하고 삭제하는 코드를 작성해보자.

(1) aws-sdk 설치

우선 aws-sdk를 사용할 것이기 때문에 npm을 통해 설치해준다.

npm i aws-sdk

(2) AWS S3 객체 생성

설치가 완료되면 import 후 자신의 AWS accessKeysecretAccessKey를 이용하여 사용할 객체를 생성할 수 있다.

import * as AWS from 'aws-sdk';

const s3 = new AWS.S3({
  accessKeyId: 'your_aws_access_key',
  secretAccessKey: 'your_aws_secret_key',
  region: 'your_region',
});

생성한 객체를 사용하여 원하는 파일을 버킷에 업로드하고 삭제할 수 있다.

(3) 파일 업로드

const key = `${Date.now() + '파일 데이터 이름'}`;
const params = { Bucket: 'your_bucket_name', Key: key };

await s3
  .putObject(
  {
    Key: key,
    Body: '파일 데이터',
    Bucket: 'your_bucket_name',
  },
  (err) => {
    if (err) {
      throw err;
    }
  },
).promise();

putObject 함수를 사용하여 원하는 버킷에 파일을 업로드할 수 있다.
업로드하고 싶은 파일을 Body 부분에 넣어주면 된다.

key 값은 오브젝트마다 고유한 값을 가져야하기 때문에 현재 시간 데이터를 앞에 넣어주었다. (나중에 url 받아오거나 삭제할 때 key 값을 사용해서 오브젝트에 접근한다.)

(4) URL 받아오기

업로드한 파일은 각자 고유의 url이 생성된다.

const params = { Bucket: 'your_bucket_name', Key: key };

const imageUrl: string = await new Promise((r) => 
  	s3.getSignedUrl('getObject', params, async (err, url) => {
        if (err) {
          throw err;
        }
        r(url.split('?')[0]); //  return object url
      }),
    );

getSignedUrl 함수를 사용하면 버킷에 있는 오브젝트의 url을 받아올 수 있다.
이제 이 url을 DB에 저장하고 프론트에게 그대로 전달하면 프론트에서 url로 직접 접근하여 파일을 가져올 수 있다.

(5) 업로드한 파일 삭제하기

const deleteParams = {
      Bucket: 'your_bucket_name',
      Key: key,
    };

await s3.deleteObject(deleteParams).promise();

deleteObject함수를 사용하면 앞서 지정해줬던 key 값을 통해 오브젝트에 접근하여 해당 오브젝트를 버킷에서 삭제한다.

참고 자료
https://docs.aws.amazon.com/AmazonS3/latest/API/API_Operations_Amazon_Simple_Storage_Service.html
https://sangjuntech.tistory.com/20
https://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%EB%84%88%EB%A6%AC_%EB%9D%BC%EC%A7%80_%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8
https://heropy.blog/2019/02/28/blob/

profile
호기심 많은 백엔드 개발자입니다 😝
post-custom-banner

0개의 댓글