S3 버킷의 파일을 다운로드 할 수 있는 Dashboard 만들기

Singsoong·2023년 2월 22일
0

AWS

목록 보기
11/14
post-thumbnail

📌 목적

  • 사내 프로젝트 중에서 매 시간마다 보정정보를 버킷에 파일형식으로 저장하는데, 이 파일들을 Dashboard를 통하여 다운로드할 수 있는 시스템을 구현해야 한다.

📌 아이디어

내가 생각해낼 수 있는 아이디어는 3가지정도였다.

  • 첫번째 : 클라이언트가 dashboard를 통해 S3 버킷의 특정파일을 다운로드 요청을 하게되면, 서버가 S3 버킷의 파일을 다운받고 클라이언트에게 파일을 주는 방식.
    하지만 이 방식은 클라이언트가 요청이 있고 나서부터 서버에서 다운 받는 시간까지 써야하는 비효율적인 구조라고 생각했다.
  • 두번째 : 클라이언트가 다운로드 요청을 하면, 버킷 내 파일의 url을 전송하는 방식.
    이렇게 하게 되면 버킷을 일단 public으로 오픈해야하는 상황이고, url의 형식도 해쉬 값이 아닌 고정 값이라 마음만 먹으면 버킷 내 데이터를 다 털 수 있는 상황이었다.
  • 세번째 : S3 버킷의 pre-signed url을 클라이언트에게 전달하여 보안적인 측면과 효율적인 측면을 둘 다 잡았다.

📌 pre-signed url

  • 기본적으로 S3 객체는 모두 비공개이고, 객체 소유자만 액세스할 수 있다. 그러나 객체 소유자는 필요할 경우 자신의 보안 자격 증명을 사용하여 일정 기간 동안 객체 다운로드를 허가하는 미리 서명된 URL을 만들어 다른 사용자와 객체(파일)을 공유할 수 있다.
  • 객체에 대해 미리 서명된 URL을 만들 때 보안 자격 증명을 제공하고 버킷 이름, 객체 키, HTTP 메서드 및 만료 날짜와 시간을 지정해야 한다.
  • 설정한 만료시간이 지나면 URL도 만료된다.

📌 API

  • API 3개를 설계하였다.
    1) s3query : 클라이언트가 dashboard에 진입했을 때 버킷의 파일 리스트들을 리턴
    2) s3download : 클라이언트가 dashboard에 특정 파일의 다운로드를 요청했을 때 파일의 signed-url을 리턴
    3) s3search : 클라이언트가 특정 일자의 파일을 요청했을 때 특정 일자에 해당하는 파일 리스트를 리턴

  • 구현: s3.js

const AWS = require("aws-sdk");
const dotenv = require("dotenv");
dotenv.config();

AWS.config.update({
  accessKeyId: process.env.accessKey,
  secretAccessKey: process.env.secretKey,
  region: "ap-northeast-2",
});
const s3 = new AWS.S3();
  • 먼저 S3 서비스를 이용하기 위해 import 시키고 AWS 보안자격 증명인 액세스 키와, 시크릿 키를 config한다.
  • 액세스 키와 시크릿 키는 기밀 정보이기 때문에 환경변수로 관리한다.
 function s3query(req, res) {
  const params = {
    Bucket: "ssrg-log",
    Prefix: "23/", // prefix가 아닌 Prefix임
  };
  s3.listObjects(params, function (err, data) {
    if (err) {
      throw err;
    }
    res.json(data.Contents);
  });
}
  • 버킷의 모든 파일 리스트를 가져오는 함수이다. params에 버킷 이름과 Prefix를 입력한다. 나 같은 경우에는 버킷 내 구조가 맨 앞에 23이라는 상위 폴더가 있다.
  • 주의해야할 것이, params의 멤버 이름들은 대문자이다. (Bucket, Prefix)
  • MaxKeys를 지정하여 최대로 가져올 수 있는 파일의 수를 지정할 수 있다.
function s3download(req, res) {
  const fileName = req.query.fileName;
  try {
    const signedUrl = s3.getSignedUrl("getObject", {
      Bucket: "ssrg-log",
      Key: fileName,
      Expires: 15,
    });
    res.json(signedUrl);
  } catch (e) {
    throw e;
  }
}
  • signed-url을 리턴하는 함수이다.
  • Key에는 Prefix와 같은 경로를 주면 된다.
  • Expires에 만료 기간은 설정할 수 있다. 15로 입력하면 15초이다.

function s3search(req, res) {
  const year = req.query.year;
  let doy = req.query.doy;

  const params = {
    Bucket: "ssrg-log",
    Prefix: `${year}/SSRG${doy}`,
  };

  try {
    s3.listObjects(params, function (err, data) {
      if (err) {
        throw err;
      }
      res.json(data.Contents);
    });
  } catch (e) {
    throw e;
  }
}
  • 특정 날에 해당하는 파일들을 리턴하는 함수이다.

📌 에러

진행하다가 signaturedoesnotmatch 라는 에러를 마주했다.

  • 해결 방안 : AWS 보안 자격 증명에서 시크릿 키에 특수문자(+, -, /, % 등)가 들어가면 발생하는 에러이다. 해결할 수 있는 방안이 IAM에서 시크릿 키를 재발급하는 수밖에 없다고 한다.
  • 보안 자격 증명에 들어가서 밑에 액세스 키 라는 탭에서 한개를 더 발급하거나 (계정 당 최대 2개를 가질 수 있다.) 한개를 삭제하고 재발급하면 된다.
  • 주사위 돌리듯이 비밀 키에 특수문자가 안들어갈 때 멈추면 된다.

📌 구현완료

  • 다운로드를 누르면 파일을 가져온다

📌 요금



📌 참고한 사이트

https://aws.amazon.com/ko/s3/pricing/
https://velog.io/@daydream_03/SignatureDoesNotMatch-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%9C-%EC%8D%B0
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/API/Welcome.html

profile
Web Developer

0개의 댓글