[AWS] S3: Presigned URL
๊ณ ์ ์ ์ธ ํ์ผ ์ ์ฅ ๋ฐ ์๋น ์์คํ
์์๋ ๊ทธ๋ฅ ๋ฉ์ธ์๋ฒ๊ฐ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ์ง์ ๋ฐ์์ ์ฒ๋ฆฌํ๊ณค ํ๋ค.
ํ์ง๋ง ๊ทธ๋ฐ ๋ฐฉ์์๋ ๊ฝค๋ ํฐ ์ฑ๋ฅ ๋ถํ๊ฐ ๋ฐ๋ฅธ๋ค.
๊ต์ฅํ ์ผ๋ฐ์ ์ธ ๋น์ฆ๋์ค ๋ก์ง์์๋ ํ์ผ์๋ ์ต์ kb๋ mb๊น์ง๋ ๋ฐ์์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๊ฑธ ๊ทธ๋๋ก ๋ฐ์ผ๋ฉด ์๋ฒ ํธ๋ํฝ์ด๋ ์ ๋ฐ์ ์ธ ๋ถํ๋ฅผ ๊ฐ๋นํ๊ฑฐ๋ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์์ง๋ค.
๋คํํ AWS์์๋ ์ด๋ฐ ๊ณ ๋ฏผ์ ์ข ํด์์์ผ์ค ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. "์
๋ก๋๊ฐ ๊ฐ๋ฅํ" Presigned URL ์์ฑํ๊ณ ๊ทธ๊ฑธ ํตํด Frontend ์์ค์์ ์
๋ก๋๋ฅผ ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ด๋ค.
์ด ์
๋ก๋์ ๋ฐ๋ฅธ ๋ถํ๋ AWS ์๋ฒ๊ฐ ๊ฐ๋นํ๊ธฐ ๋๋ฌธ์ ์๋ฒ์ ๊ฐํด์ง๋ ๋ถ๋ด์ ์ฌ๋ผ์ง๋ค.
์ด์์ ์ธ ์ฌ์ฉ ํํ๋ ๋ค์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ๊ฒ์ด๋ค.
์ข ๋ณต์กํ๊ธด ํ์ง๋ง ํจ๊ณผ์ ์ด๋ค.
๋ณด์์ ์ผ๋ก๋ ํฐ ๊ฒฐํจ์ด ๋๊ธฐ๋ ์๋๋ค. URL ์์ฒด๊ฐ ์ถ์ธกํ๊ธฐ ์ด๋ ค์ด ํํ๋ก ์์ฑ๋๊ณ , ์ผ๋ง ์ง๋์ง ์์ ๋ง๋ฃ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๋น์ฉ์ ์ผ๋ก๋ ํ๋ฅญํ ์ ํ์ด๋ค. Presigned URL์ ์์ฑ์ด๋ ์ฌ์ฉ์ ๋น์ฉ์ ๋ถ๊ณผํ์ง ์๋๋ค. ์์ํ S3 ์ฌ์ฉ์ ๋ํด์๋ง ์๊ธ์ ๋ถ๊ณผํ๋ค.
์จ๋ณด๊ธฐ
์๋๋ ์ ๋ก๋์ฉ Presigned URL์ ์์ฑํ๋ ์์ ์ฝ๋๋ค. Lambda node.js์์ ๋์ํ๋ค.
const aws = require('aws-sdk');
exports.handler = async (event) => {
const s3 = new aws.S3({
signatureVersion: 'v4',
});
const params = {
Bucket: 'myyrakle-public', // ๋ฒํท ์ด๋ฆ
Key: `testimage.jpg`, // ์ ์ฅ๋ ํ์ผ ๊ฒฝ๋ก
ContentType: "image/jpeg", // ํ์
ACL: 'public-read', // ๊ณต๊ฐ๋ชจ๋๋ก ์
๋ก๋
};
const url = await new Promise(function (resolve, reject) {
s3.getSignedUrl('putObject', params, function (err, url) {
if (err) {
reject(err);
}
else {
resolve(url);
}
});
});
return {
statusCode: 200,
body: url,
}
};
์ด Presigned URL ์์ฑ๊ธฐ์ AWS Role์๋ ํญ์ ์ถฉ๋ถํ ๊ถํ์ ๋ฌ์ผ ํจ์ ์์ง ๋ง์.
getSignedUrl์ ํ ๋๋ ๊ถํ ์ค๋ฅ๊ฐ ๋์ง ์๊ณ , ์ค์ ๋ก ์ฌ์ฉํ ๋ lazyํ๊ฒ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. Acces Denied๋ค.
์๋ฌดํผ ์ธํ ํ๊ณ ์คํํด๋ณด๋ฉด
๊ฒ๋ ๊ธด url์ด ๋ฐํ๋ ๊ฒ์ด๋ค.
์ ๊ธฐ์ ๋ํด์ PUT method๋ก ํ์ผ์ ๋ ๋ฆฌ๋ฉด ๋๋ค.
์๋๋ node.js์์ ๋ก์ปฌ ํ์ผ์ ์ฝ์ด์ ์๋ ์์ ์ฝ๋๋ค.
const axios = require("axios");
const fs = require("fs");
async function main() {
const url =
"https://myyrakle-public.s3.ap-northeast-2.amazona...";
const file = fs.readFileSync("bonobono.jpg");
try {
const response = await axios.put(url, file);
console.log(response.status);
console.log(response.statusText);
console.log(response.data);
console.log("done");
} catch (err) {
console.log(err.response.status);
console.log(err.response.statusText);
console.log(err.response.data);
}
}
main();
์ด๋ ๊ฒ ์ฑ๊ณต์ด ๋จ๋ฉด
์ ์ฌ๋ผ๊ฐ์ ๊ฒ์ด๊ณ
๋ค์ ๋ค์ด๋ ์ ๋ ๊ฒ์ด๋ค.
์ฐธ์กฐ
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/PresignedUrlUploadObject.html
https://velog.io/@seeh_h/AWS-S3-presignedURL%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-image-Upload-%ED%95%98%EA%B8%B0-qvqo81gk