[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