카테고리 없음

aws S3로 파일서버 만들기 과정 - 2. S3 버킷에 파일 올리고 받아보기 (디자인 마켓플레이스 프로젝트)

designer DK 2024. 12. 10. 23:22
728x90

지난번 포스팅에서 이어지는 포스팅인데 aws에서 I AM 사용자 생성과 S3 버킷 생성이 되었으면

이제 실제로 파일을 올려보고 받는 연습이 필요했다.

 

제대로된 파일 다운로드 기능 구현은 유저 권한 및 상품과도 연계시켜야하는 복잡함이 있어서

일단은 S3를 이용한 다운로드가 잘 되는지 안되는지만 테스트해보기 위해

순전히 다운로드 테스트용 코드만 구성해서 테스트해보았다.

 

먼저 파일의 업로드가 필요한데 이것도 두가지로 나뉜다.

1. 코드를 통한 업로드

2. 직접 aws S3에서 업로드

 

1번의 경우 상당히 복잡한 과정을 거쳐야하기 때문에 나의 프로젝트 특성을 감안했을 때

2번의 방법 편하고 좋을 것 같아서 2번의 방식으로 하기로 결정했다.

 

실제로 직접 업로드 방식은 굉장히 편했다.

 

먼저 s3에 접속한다. 지난번에 만들어 둔 버킷이 보인다.

이런식으로 폴더도 만들어서 관리할 수 있음.

 

 

 

업로드를 누르면 여러가지 선택 항목들이 등장한다.

 

 

스토리지 클래스라는 부분이 있는데 미세하게 장단점이 있는 듯 했다. 나는 일단 스탠다드로 선택.

 

 

 

서버 측 암호화의 경우 키 지정을 해주면 좋다고 한다. SSE-S3 유형 선택. 

 

 

나머지 옵션들은 그대로 두고 업로드를 진행.

 

 

그럼 이렇게 업로드가 완료된다.

 

 

 

해당 파일 상세를 들어가보면 이렇게 객체 개요 정보들이 나온다.

여기서 객체 URL이라는 우측하단 링크가 실제 파일을 다운로드 시키는 URL이다.

 

 

해당 파일을 직접 눌러보면 이런식으로 액세스 거부가 나온다.

이건 정상적인 부분이며 함부로 이 링크로 다운로드 못하게 하기위해 이렇게 되는 것이다.

 

 

실질적인 다운로드가 이루어지게 하기 위해서는

내가 받은 액세스 키를 통한 api 호출로 해당 파일에 접근 시켜야한다.

 

먼저 aws-sdk를 설치해야한다.

 

 

.env 파일에 aws관련 키들을 설정해놓는다.

AWS_ACCESS_KEY_ID=액세스 키 ID
AWS_SECRET_ACCESS_KEY=시크릿 액세스 키
AWS_REGION=ap-southeast-2 (리전 값 입력)
AWS_BUCKET_NAME=내 버킷 이름

 

 

그리고 그 키들을 적용할 수 있는 util 파일인 s3Config.js라는 파일을 만들어 아래와 같이 정리.

const AWS = require('aws-sdk');

const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION
});

module.exports = s3;

 

 

aws 라우터도 따로 설정.

const express = require('express');
const downloadController = require('../controllers/downloadController');
const router = express.Router();

// 테스트용 단순 엔드포인트
router.get('/download/test', downloadController.getPresignedUrl);

module.exports = router;

 

 

그리고 아래와 같이 컨트롤러를 구성. (테스트용이라 최소화 했다)

const AWS = require('aws-sdk');
const s3Config = require('../utils/s3Config');

const downloadController = {};

downloadController.getPresignedUrl = async (req, res) => {
try {
const testFileKey = 'asset-test/aaa.zip';

const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: testFileKey,
Expires: 60 * 5
};

//URL 생성
const url = await s3Config.getSignedUrlPromise('getObject', params);
console.log('Generated URL:', url);

res.json({ downloadUrl: url });

} catch (error) {
console.error('Error in getPresignedUrl:', error);
console.error('Error stack:', error.stack);
res.status(500).json({
error: 'Download failed',
message: error.message,
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
});
}
};

module.exports = downloadController;

 

특이한 점은 presigned URL을 생성하는 것인데

이는 생성 후 시간이 정해져있는 URL이다. 한 번 받은 주소로 계속해서 받는 것을 방지하기 위함이다.

 

 

그리고 마지막으로 이 부분이 프론트엔드 요청 코드.

async function testDownload() {
try {
showLoading();
 
const response = await fetch(`${URI}/api/aws/download/test`);

if (!response.ok) {
const data = await response.json();
throw new Error(data.error || 'Download failed');
}

const { downloadUrl } = await response.json();
 
console.log('Received URL:', downloadUrl); // 테스트용 로그
 
// 새 탭에서 다운로드 URL 열기
window.open(downloadUrl, '_blank');

} catch (error) {
console.error('Download error:', error);
showError(error.message);
} finally {
hideLoading();
}
}

// 테스트 버튼에 이벤트 리스너 추가
document.getElementById('test-button').addEventListener('click', testDownload);

 

테스트 버튼을 누르면 다운로드를 요청한다.

 

다운로드 버튼을 눌러보면

 

이렇게 내가 올렸던 파일을 다운로드 받을 수 있다!!