Node.js와 express로 백엔드를 구축했다.
백엔드에서 aws-sdk를 이용하여 버킷과 객체에 접근할 것이다.
MY_AWS_ACCESS_KEY
: IAM 설정에서 발급받은 액세스 키
MY_AWS_SECRET_KEY
: IAM 설정에서 발급받은 시크릿 액세스 키
MY_AWS_S3_BUCKET
: 버킷 명
MY_AWS_S3_BUCKET_REGION
: AWS 리전 (서울이면 ap-northeast-2)
/src/util/aws.js
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3'); // 환경 변수를 .env 파일로 관리하게 해주는 라이브러리 require('dotenv').config(); const awsAccessKey = process.env.MY_AWS_ACCESS_KEY; const awsSecretKey = process.env.MY_AWS_SECRET_KEY; const awsS3Bucket = process.env.MY_AWS_S3_BUCKET; const awsS3BucketRegion = process.env.MY_AWS_S3_BUCKET_REGION; const s3 = new S3Client({ credentials: { accessKeyId: awsAccessKey, secretAccessKey: awsSecretKey, }, region: awsS3BucketRegion, }); const listObjectsBucketParams = () => { return { Bucket: awsS3Bucket, Prefix: ``, }; }; const deleteObjectBucketParams = fileName => { return { Bucket: awsS3Bucket, Key: fileName, }; }; // 객체를 S3에 업로드하는 함수 async function uploadFile(fileBuffer, fileName, mimetype) { const uploadParams = { Bucket: awsS3Bucket, Key: fileName, Body: fileBuffer, ContentType: mimetype, }; const res = await s3.send(new PutObjectCommand(uploadParams)); return res.$metadata.httpStatusCode; } module.exports = { s3, listObjectsBucketParams, deleteObjectBucketParams, uploadFile, };
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3'); // 환경 변수를 .env 파일로 관리하게 해주는 라이브러리 require('dotenv').config(); const awsAccessKey = process.env.MY_AWS_ACCESS_KEY; const awsSecretKey = process.env.MY_AWS_SECRET_KEY; const awsS3Bucket = process.env.MY_AWS_S3_BUCKET; const awsS3BucketRegion = process.env.MY_AWS_S3_BUCKET_REGION; const s3 = new S3Client({ credentials: { accessKeyId: awsAccessKey, secretAccessKey: awsSecretKey, }, region: awsS3BucketRegion, }); const listObjectsBucketParams = () => { return { Bucket: awsS3Bucket, Prefix: ``, }; }; const deleteObjectBucketParams = fileName => { return { Bucket: awsS3Bucket, Key: fileName, }; }; // 객체를 S3에 업로드하는 함수 async function uploadFile(fileBuffer, fileName, mimetype) { const uploadParams = { Bucket: awsS3Bucket, Key: fileName, Body: fileBuffer, ContentType: mimetype, }; const res = await s3.send(new PutObjectCommand(uploadParams)); return res.$metadata.httpStatusCode; } module.exports = { s3, listObjectsBucketParams, deleteObjectBucketParams, uploadFile, };
/src/routes/image.js
const express = require('express'); const formidable = require('formidable'); const { ListObjectsCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3'); const { s3, listObjectsBucketParams, deleteObjectBucketParams, uploadFile } = require('../util/aws'); const fs = require('fs'); const router = express.Router(); // GET: 객체들의 Key값들 반환 ex) [a.PNG, b.PNG] router.get('/', async (req, res) => { try { const data = await s3.send(new ListObjectsCommand(listObjectsBucketParams())); res.status(200).send(data.Contents.map(item => item.Key)); } catch (e) { res.status(400).send({ error: '이미지 Key 값 가져오기 실패' }); } }); // POST: 파일 업로드 router.post('/', async (req, res) => { try { const fileData = await new Promise((resolve, reject) => { const form = new formidable.IncomingForm(); // formidable로 폼 파싱 form.parse(req, (err, fields, files) => { if (err) return reject(err); return resolve({ fields, files }); }); }); const parsedFileData = fileData; Object.values(parsedFileData.files).forEach(async item => { // fs.createReadStream이용해 스트림 전환 후 올리기 const fileBuffer = fs.createReadStream(item[0].filepath); fileBuffer.on('error', err => console.log(err)); const fileName = item[0].originalFilename; await uploadFile(fileBuffer, fileName, item[0].mimetype); }); return res.status(201).json({ message: 's3 업로드 성공', }); } catch (e) { return res.status(500).json({ error: 's3 업로드 실패' }); } }); // DELETE: 객체 삭제 router.delete('/:id', async (req, res) => { try { await s3.send(new DeleteObjectCommand(deleteObjectBucketParams(req.params.id))); return res.status(200).send('이미지 삭제 완료'); } catch (e) { return res.status(500).json({ error: '이미지 삭제 실패' }); } }); module.exports = router;
const express = require('express'); const formidable = require('formidable'); const { ListObjectsCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3'); const { s3, listObjectsBucketParams, deleteObjectBucketParams, uploadFile } = require('../util/aws'); const fs = require('fs'); const router = express.Router(); // GET: 객체들의 Key값들 반환 ex) [a.PNG, b.PNG] router.get('/', async (req, res) => { try { const data = await s3.send(new ListObjectsCommand(listObjectsBucketParams())); res.status(200).send(data.Contents.map(item => item.Key)); } catch (e) { res.status(400).send({ error: '이미지 Key 값 가져오기 실패' }); } }); // POST: 파일 업로드 router.post('/', async (req, res) => { try { const fileData = await new Promise((resolve, reject) => { const form = new formidable.IncomingForm(); // formidable로 폼 파싱 form.parse(req, (err, fields, files) => { if (err) return reject(err); return resolve({ fields, files }); }); }); const parsedFileData = fileData; Object.values(parsedFileData.files).forEach(async item => { // fs.createReadStream이용해 스트림 전환 후 올리기 const fileBuffer = fs.createReadStream(item[0].filepath); fileBuffer.on('error', err => console.log(err)); const fileName = item[0].originalFilename; await uploadFile(fileBuffer, fileName, item[0].mimetype); }); return res.status(201).json({ message: 's3 업로드 성공', }); } catch (e) { return res.status(500).json({ error: 's3 업로드 실패' }); } }); // DELETE: 객체 삭제 router.delete('/:id', async (req, res) => { try { await s3.send(new DeleteObjectCommand(deleteObjectBucketParams(req.params.id))); return res.status(200).send('이미지 삭제 완료'); } catch (e) { return res.status(500).json({ error: '이미지 삭제 실패' }); } }); module.exports = router;
로컬 스토리지, 세션 스토리지, 쿠키의 차이점을 알기 쉽게 페이지 및 API를 따로 구현했다. 프론트엔드에서 fetch 요청 시 옵션으로 credentials: "include"를
2023-08-08퍼블릭화한 S3 버킷의 객체 URL은 https://[버킷명].s3.[버킷리전].awazonaws.com/[객체]로 되어있다. ex) https://doromo-example.s3
2023-07-27AWS S3의 모든 객체는 버킷에 저장되기 때문에 S3에 파일과 폴더를 업로드하려면, 먼저 객체가 저장될 버킷을 생성해야 한다. 또한 Node.js에서 @aws-sdk/client
2023-07-27Node.js는 @aws-sdk/client-s3 라이브러리를 이용하여 S3 버킷과 객체를 제어한다. 라이브러리를 사용하기 위해서는 일단 AWS S3에서 IAM 사용자를 만들어 액
2023-07-27# Contact : jyw966@naver.com
Copyright © doromo. All Rights Reserved.