โ ์์์ ์๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐ์์๋ ์๋ค. โ
- ๊ฐ๋ฐ์ ์๋ด(Programmerโs Proverbs)

์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์์ ๊ฐ์ ๊ฒฝ์ฐ CPU์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ก์ปฌ ์๋ฒ์์ ์์ ์ ๋๋ ค๋ฒ๋ฆฌ๋ฉด ๋ค๋ฅธ ์ฌ์ฉ์์ ์์ฒญ์ ๋ชป๋ฐ๋ ํ์์ด ์๊ธธ์ ์๋ค.
ํนํ๋ ์ฑ๊ธ ์ค๋ ๋ ๊ธฐ๋ฐ์ผ๋ก ๋์๊ฐ๋ ๋ ธ๋ ์๋ฒ์ผ ๊ฒจ์ฐ ์ฑ๋ฅ ๊ฐ์์ ํฐ ์์ธ์ด ๋๋ค. ๋ ธ๋๋ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฐ์ผ๋ก I/O์์ ์ ์ ๋ฆฌํ๊ณ CPU ์์ ์ ๋ถ๋ฆฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ ๋ค๊ณ ๋ฐ๋ก ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์ ์ฉ ๋ก์ปฌ ์๋ฒ๋ฅผ ๋ง๋ค์ด ์ฌ๋ฆฐ๋ค ํด๋, ๋ชจ๋ ์ฌ์ฉ์๊ฐ ํญ์ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์์ ๊ธฐ๋ฅ์ ์ด์ฉํ๋ ๊ฒ๋ ์๋๊ธฐ์ ์๋ฒ๋ฅผ ๊ณ์ ๋๋ฆฐ๋ค๋ ๊ฒ์ ์์ ๋ญ๋น์ผ์ ์๋ค.
๋ฐ๋ก ์ด๋ฌํ ์ํฉ์์ ์๋ฒ๋ฆฌ์ค์ ์๋น์ค๋ ํ์ ๋ฐํํ๋ค.
๋๋ค๋ ํน์ ํ ๋์์ ์ํํ๋ ๋ก์ง์ ์ ์ฅํ๊ณ ์์ฒญ์ด ๋ค์ด์ฌ ๋ ๋ก์ง์ ์คํํ๋ ์๋น์ค๋ค. ๋ง์น ํจ์์ฒ๋ผ ํธ์ถํ ๋ ์คํํ์ฌ FaaS๋ผ๊ณ ๋ถ๋ฆฐ๋ค.
์ด์ฒ๋ผ ๋๋ค๋ฅผ ์ด์ฉํด ๋ ๋ฆฝ์ ์ธ ์๋ฒ์์ ํจ์๋ฅผ ์คํ ์์ผ, ๋ก์ปฌ ์๋ฒ์ ๋ถ๋ด์ ์ค์ผ์ ์์ ๋ฟ๋ง ์๋๋ผ ์จ๋๋ฉ๋(on-demand) ํ์์ด๋ผ ์ด๋งํผ ์๊ธ์ ์ง๋ถํ๋ฉด ๋์ ํญ์ ์ปดํจํ ์ ์คํ์ํค๋ ์์ ๋ญ๋น๋ฅผ ์ค์ผ์ ์๋ค.
์ด ํฌ์คํ ์์ Node.js ๊ธฐ๋ฐ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ํจํค์ง์ธ shap ๋ชจ๋์ ์ด์ฉํ์ฌ ๊ตฌํํด๋ณผ ์์ ์ด๋ค.
์๋ ํฌ์คํ ์์ shap๋ฅผ ์ด์ฉํ์ฌ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง API ๋ก์ปฌ ์๋น์ค๋ฅผ ๊ตฌํํ ๋ฐ ์๋ค.
์ด api ์๋น์ค๋ฅผ ๋๋ค์ ์ด์์ํค๊ณ , S3์ API Gateway ํธ๋ฆฌ๊ฑฐ๊ฐ ๋ฐ์ํ ๋ ๋๋ค๋ฅผ ์คํ์ํค๋ ์ค์ง์ ์ด๊ณ ์ค์ฉ์ ์ธ ์๋น์ค๋ฅผ ๊ตฌํํด๋ณด์.
์ฃผ์ํ ์ ์ shap ๋ชจ๋์ ์ค์นํ ๋ ๋ฆฌ๋ ์ค ๋ฐ์ด๋๋ฆฌ ๋ฒ์ ์ผ๋ก ์ค์นํด์ผ ๋๋ค๋ ์ ์ด๋ค. (๋๋ค๋ Amazon Linux ๊ธฐ๋ฐ์ผ๋ก ๋์๊ฐ)
> npm install --platform=linux sharpโ
[NODE] ๐ Sharp ๋ชจ๋ ์ฌ์ฉ๋ฒ - ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง / ์ํฐ๋งํฌ ๋ฃ๊ธฐ
Sharp ๋ชจ๋ ๋ ธ๋ ์ง์์๋ ๋ง์ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ํจํค์ง๋ค์ด ์์์ง๋ง, ๋๊น์ง ์ด์๋จ์ ๋ชจ๋์ด shap ์ด๋ค. ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ๋์ ์์ฒด๊ฐ cpu์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ก์๋จน๋ ์ฃผ๋ฒ์ด๋ผ, ๊ฐ๋ out of memory๋ก node
inpa.tistory.com
Lambda ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ํธ๋ฆฌ๊ฑฐ (S3)
๋๋ค S3 ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์ํคํ ์ณ ์คํ ์์๋ฅผ ์์ฝํ์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.

- ์ฌ์ฉ์๊ฐ ์นํ์ด์ง์์ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋
- ๋ก์ปฌ ์๋ฒ์์ ์ด๋ฏธ์ง ์์ฒญ์ ๋ฐ๊ณ S3 ๋ฒํท original/ ๊ฒฝ๋ก์ ์ ๋ก๋
- S3์ ์ค๋ธ์ ํธ ์ ๋ก๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์
- S3 ํธ๋ฆฌ๊ฑฐ๊ฐ ๋ฐ์๋์ด ๋๋ค ํจ์ ์คํ
- ๋๋ค์์ ๋ฒํท original/ ์ ์๋ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์์ ํ๋ค ๋ค์ ๋ฒํท thumb/ ๊ฒฝ๋ก์ ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง ์ ๋ก๋
- ๋ก์ปฌ ์๋ฒ๋ ์๋ณธ๊ณผ ๋ฆฌ์ฌ์ด์ง ์ด๋ฏธ์ง url์ ํด๋ผ์ด์ธํธ์ ์๋ต
์ด์ ์ค์ง์ ์ผ๋ก ์ ๋์์ด ๋๋๋ก ๊ตฌํํด๋ณด์.
1. S3 ์์ฑ ๋ฐ ๋ฒํท ์ ์ฑ ๋ฑ๋ก
์ผ๋จ ๊ฐ์ฅ ๋จผ์ ์ ์ฅํ S3 ๋ฒํท์ ๋ง๋ค๊ณ , ๋ฒํท ์ ์ฑ ์ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ฒด๋ฅผ PUT, GET, DELETE ๋์์ ํ์ฉํ๋๋ก ํ์.


{
"Version": "2012-10-17",
"Id": "Policy1657542910526",
"Statement": [
{
"Sid": "Stmt1657542907707",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::<๋ฒํท๋ช
>/*"
}
]
}
2. ๋ก์ปฌ ์๋ฒ์์ ์์ฒญ ์ด๋ฏธ์ง๋ฅผ S3๋ก ๋ณด๋ด๋ ๋ก์ง ๊ตฌํ
Node.js ์๋ฒ์์ multer-s3 ํจํค์ง๋ฅผ ์ด์ฉํ์ฌ, ํผ ์ ์ก๋ ์ด๋ฏธ์ง ํ์ผ์ S3๋ก ์๋์ผ๋ก ์ ๋ก๋ ํ๊ฒ ํ๋ค.
๋ณด๋ค ์์ธํ ๊ตฌํ ์ค๋ช ์ด ํ์ํ๋ฉด ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
[AWS-SDK] ๐จ๐ปโ๐ป Node - Multer S3 ์ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ ์ ๋ฆฌ
multer-s3 ์ฌ์ฉ๋ฒ ์ ์๊ฐ์ Node.js ์์ AWS SDK S3๋ฅผ ๋ค๋ฃจ๋ ๋ฒ์ ๋ํด์ ์์๋ณด์๋ค. ๊ทธ๋ผ ๋ง์ฝ ๊ฒ์๊ธ ์ด๋ฏธ์ง๋ฅผ S3์ ์ ์ฅํ๋๋ก ๊ตฌ์ฑํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํ ๊น? ๋ณดํต ๋ ธ๋ ํ๋ก์ ํธ์์ ํ์ผ ์ ๋ก๋
inpa.tistory.com
const express = require('express');
const multer = require('multer');
const path = require('path');
const AWS = require("aws-sdk");
const multerS3 = require('multer-s3');
const dotenv = require('dotenv');
dotenv.config();
const router = express.Router();
//* aws region ๋ฐ ์๊ฒฉ์ฆ๋ช
์ค์
AWS.config.update({
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: 'ap-northeast-2',
});
//* AWS S3 multer ์ค์
const upload = multer({
//* ์ ์ฅ๊ณต๊ฐ
// s3์ ์ ์ฅ
storage: multerS3({
// ์ ์ฅ ์์น
s3: new AWS.S3(),
bucket: 'test-bucket-inpa',
acl: "public-read",
contentType: multerS3.AUTO_CONTENT_TYPE,
key(req, file, cb) {
cb(null, `${Date.now()}_${path.basename(file.originalname)}`) // original ํด๋์์๋ค ํ์ผ์ ์ ์ฅ
},
}),
//* ์ฉ๋ ์ ํ
limits: { fileSize: 5 * 1024 * 1024 },
});
//* ์ฑ๊ธ ์ด๋ฏธ์ง ํ์ผ ์
๋ก๋ -> uploads/ ๋๋ ํ ๋ฆฌ์ ์ด๋ฏธ์ง๋ฅผ ์ฌ๋ฆฐ๋ค.
router.post('/img', isLoggedIn, upload.single('img'), (req, res) => {
console.log(req.file);
const originalUrl = req.file.location; //? s3 ์ฉ : multer s3์์ ๋ฒํท ๊ฐ์ฒด ๊ฒฝ๋ก๋ฅผ ๋ฐํํจ
const url = originalUrl.replace(/\/original\//, '/thumb/');
// ๋๋ค์์ ๋ฆฌ์ฌ์ด์ง ์ฒ๋ฆฌํ๊ณ ์๋ก ๋ฒํท์ ์์ถ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํ๋, ์์ถ๋ ์ด๋ฏธ์ง ๋ฒํท๊ฒฝ๋ก๋ก ์ด๋ฏธ์งurl์ ๋ณ๊ฒฝํ์ฌ ํด๋ผ์ด์ธํธ์ ์ ๊ณต
// ๋ค๋ง, ๋ฆฌ์ฌ์ด์ง์ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง๊ฐ ์ผ์ ๊ธฐ๊ฐ ๋์ ํ์๋์ง ์์ ์ ์์ผ๋ฏ๋ก, ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ๋ก๋ฉํ๋๋ฐ ์คํจ์ ์๋ณธ ์ด๋ฏธ์ง๋ฅผ ๋์ฐ๊ธฐ ์ํด originalUrl๋ ๊ฐ์ด ์ ์ก
res.json({ url, originalUrl });
});
module.exports = router;
์ถ๊ฐ์ ์ผ๋ก ํ๋ก ํธ์ชฝ๋ ์๋ฌ ์ฒ๋ฆฌ ์์ ์ ํด์ค๋ค.
ํ์ฌ ๋ก์ง์์ ์๋ณธ ์ด๋ฏธ์ง๋ original/ ๋ฒํท ๊ฒฝ๋ก์ ์ ์ฅํ๊ณ , ๋ฆฌ์ฌ์ด์ง ๋ ์ด๋ฏธ์ง๋ฅผ thumb/ ๊ฒฝ๋ก์ ์ ์ฅํ๊ฒ ๋๊ณ , ํด๋ผ์ด์ธํธ์์ ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง url์ ๋ฐ์์ ํ๋ฉด์ ๋์์ฃผ๊ฒ ๊ตฌ์ฑ๋์ด ์๋๋ฐ, ๋ง์ผ์ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์์ ์ด ์ด๋ ํ ์๋ฌ๊ฐ ์๊ฒจ ์ทจ์๊ฐ ๋์๋ค๋ฉด thumb/ ์ด๋ฏธ์ง url์ด ์กด์ฌํ์ง ์์ผ๋, onerror ์ด๋ฒคํธ๊ฐ ๋ฐ์๋๋ฉด original/ ์ด๋ฏธ์ง ์๋ณธ url์ ๊ฐ์ ธ์ค๋ ์์ ์ด๋ค. (์ด๋ ๊ผญ ๋ฆฌ์ฌ์ด์ง ๋ฟ๋ง์๋๋ผ ๋ค๋ฅธ ๋ ธ๋ ํ๋ก์ ํธ ๊ธฐ๋ฒ์์ ์์ฃผ ์ฐ์ด๋ ๋ก์ง์ด๋ ๊ผญ ์์งํด์ฃผ์)
<img src="{{ twit.img }}" alt="์ฌ๋ค์ผ" onerror="this.src = this.src.replace(/\/thumb\//, '/original/');" />

3. ๋๋ค ํจ์ ๊ตฌํ
์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ํ๋ ์์ ์ฝ๋๋ฅผ ๋๋ค ํจ์ ์์์ ๋ง์ถฐ ๊ตฌํํ๋ค.
์ด๋ ๋ก์ปฌ ์๋ฒ์์ ํ์ผ์ ์ถ๊ฐํ์ฌ ๊ตฌํํ๋๊ฒ ์๋ ๋ ๋ฆฝ๋ ํ๋ก์ ํธ๋ก ์๋ก ์์ฑํด์ index.js ํ์ผ์ ๊ตฌํ์ ํด์ผํ๋ค.
์๋ํ๋ฉด ํ๋ก์ ํธ ์์ฒด๋ฅผ zip์ผ๋ก ์์ถํ๋ค ๊ทธ๋๋ก ๋๋ค์ ์ ๋ก๋ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊นํ์๋ ํด๋น ํ๋ก์ ํธ ๋ฅผ ์ฌ๋ ค๋์๋ค. (๋งํฌ)

> npm install aws-sdk
> npm install --platform=linux sharp
const AWS = require('aws-sdk');
const sharp = require('sharp');
//? ๋๋ค์์ ๋์๊ฐ๊ธฐ ๋๋ฌธ์, ๋ฐ๋ก ๋๋ค iam ์ค์ ํด์ฃผ์ง ์๋ ํ ๊ธฐ๋ณธ์ผ๋ก CLI ์ธ์ฆ์์ด ๋ฐ๋ก ๋์๊ฐ
const s3 = new AWS.S3();
exports.handler = async (event, context, callback) => {
const Bucket = event.Records[0].s3.bucket.name; // ๋ฒ์ผ๋ช
const Key = event.Records[0].s3.object.key; // ์
๋ก๋๋ ํค๋ช
const s3obj = { Bucket, Key };
const filename = Key.split('/')[Key.split('/').length - 1]; // ๊ฒฝ๋ก ์์ ๊ณ ๋ค์ ํ์ผ๋ช
๋ง
const ext = Key.split('.')[Key.split('.').length - 1].toLowerCase(); // ํ์ผ ํ์ฅ์๋ง
const requiredFormat = ext === 'jpg' ? 'jpeg' : ext; // sharp์์๋ jpg ๋์ jpeg ์ฌ์ฉ
console.log('name', filename, 'ext', ext);
try {
//* ๊ฐ์ฒด ๋ถ๋ฌ์ค๊ธฐ
const s3Object = await s3.getObject(s3obj).promise(); // ๋ฒํผ๋ก ๊ฐ์ ธ์ค๊ธฐ
console.log('original size', s3Object.Body.length);
//* ๋ฆฌ์ฌ์ด์ง
const resizedImage = await sharp(s3Object.Body)
.resize(400, 400, { fit: 'inside' }) // 400x400 ๊ฝ ์ฐจ๊ฒ
.toFormat(requiredFormat)
.toBuffer();
//* ๊ฐ์ฒด ๋ฃ๊ธฐ
await s3
.putObject({
Bucket,
Key: `thumb/${filename}`, // ๋ฆฌ์ฌ์ด์ง ๋ ์ด๋ฏธ์ง๋ฅผ thumb ํด๋์ ์๋ก์ ์ฅ
Body: resizedImage,
})
.promise();
console.log('put', resizedImage.length);
// Lambda ํจ์ ๋ด๋ถ์์ ๋ชจ๋ ์์
์ ์ํํ ํ์๋ ๊ทธ์ ๋ํ ๊ฒฐ๊ณผ(๋๋ ์ค๋ฅ)์ ํจ๊ป callback ํจ์๋ฅผ ํธ์ถํ๊ณ ์ด๋ฅผ AWS๊ฐ HTTP ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก ์ฒ๋ฆฌํ๋ค.
return callback(null, `thumb/${filename}`);
} catch (error) {
console.error(error);
return callback(error);
}
};
4. ์์ค๋ฅผ ๋๋ค์ ์ ๋ก๋
์์ ํ๋ก์ ํธ๋ฅผ zip์ผ๋ก ์์ถํ๊ณ ๋๋ค์ ์ ๋ก๋ํ๋ค.
์ ๋ก๋ ๋ฐฉ๋ฒ์ ๋ก์ปฌ์์ ๋ฐ๋ก ์ ๋ก๋ ํ๋ ๋ฐฉ๋ฒ๊ณผ S3์ ์๋ ํ์ผ์ ์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ด ์๋๋ฐ ์ ์ฅ์๊ฐ ๋ก์ปฌ์ด๋ ํด๋ผ์ฐ๋๋ ์ฐจ์ด๊ฐ ์์๋ฟ์ด๋ผ์ ์์ด ๊ฐ๋๋๋ก ํ๋ฉด ๋๋ค.


5. ๋๋ค ์คํ & ๊ถํ ์ค์
์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง์ CPU๋ฅผ ๋ง์ด ๋จน๋ ์์ ์ด๊ธฐ์ ๋๋ค์ ๊ธฐ๋ณธ ์คํ์ ๋์ฌ์ค๋ค.
S3์ ๋ฒํท ์ ์ฑ ์ ๋ฑ๋กํ์ด๋, ๊ธฐ๋ณธ์ ์ผ๋ก S3 ์์ ์ ์์ธ์ค ํ ์ ์๊ฒ ๋๋ค ์์ฒด์์๋ IAM ๊ถํ์ ๋ฑ๋กํด์ฃผ์ด์ผ ํ๋ค.


6. ๋๋ค โ S3 ํธ๋ฆฌ๊ฑฐ ๊ตฌํ


์ด๋ ๊ฒ ๋๋ค ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ด์ฉํ S3 ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ํ๋ก์ ํธ๋ฅผ ์์ฑํด๋ณด์๋ค.
์ง์ ์๋ฒ๋ฅผ ๋์๋ณด๊ณ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํด๋ณด์.
Lambda ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ํธ๋ฆฌ๊ฑฐ (API Gateway)
์ด๋ฒ์๋ S3 ์๋น์ค์ ํ์ ๋ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์๋น์ค๊ฐ ์๋, ์ธ๋ถ ์ ์ ๋ ๋ธ๋ผ์ฐ์ ์์ url์ ์ ๋ ฅํ๋ฉด ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํด์ฃผ๋ ์ค์ง์ ์ธ ์๋น์ค๋ฅผ API Gateway๋ฅผ ์ด์ฉํด ๊ตฌํํด๋ณด์.
๋ค์ url์ ๋ธ๋ผ์ฐ์ ์ ์์ฒญํ๋ค๋ฉด, ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ํ๋ฉด์ ๋์ฐ๋ ์๋น์ค๋ฅผ ๋ง๋ค์ด ๋ณผ ๊ฒ์ด๋ค.
- http://localhost:8081/thumb/500x700?fname=[์ด๋ฏธ์งurl]

- ๋ธ๋ผ์ฐ์ ์์ api gateway url๋ก ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ฅผ ๋ณด๋ธ๋ค
- api gateway๋ ์์ฒญ ๋ฐ์ดํฐ๋ฅผ ๋๋ค์๊ฒ ๋ณด๋ธ๋ค
- ๋๋ค์์ event ์ธ์๋ฅผ ์์ฒญ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ณ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง์ ํ๊ณ ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ api gateway์ ์๋ตํ๋ค
- api gateway๋ ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋์ด ์ฒ๋ฆฌํ๊ณ , ๋ธ๋ผ์ฐ์ ์๊ฒ ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ์๋ตํ๋ค
1. ๋๋ค โ API Gateway ํธ๋ฆฌ๊ฑฐ ์ฐ๊ฒฐ
์ ๋๋ค ํจ์๋ฅผ ๋ง๋ค๊ณ ํธ๋ฆฌ๊ฑฐ ์ถ๊ฐ ๋ฒํผ์ ๋๋ฅธ๋ค.


2. API Gateway ๋ผ์ฐํ ์ค์ ํ๊ธฐ










3. API Gateway ์์ฒญ ํ๋ผ๋ฏธํฐ ์ค์ ํ๊ธฐ
๋ฐฑ์๋(๋๋ค) ๋ก ๋ณด๋ผ ์์ฒญ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ API ๊ฒ์ดํธ์จ์ด์์ ์ง์ ์ง์ ํ ์ ์๋ค.


4. API ์ด์ง ๋ฏธ๋์ด ํ์ ์ค์ ํ๊ธฐ
์ฐ๋ฆฌ๊ฐ ๋ค๋ฃฐ ๋ฐ์ดํฐ๋ ์ด๋ฏธ์ง ๊ฐ์ ๋ฏธ๋์ด ๋ฐ์์ด๊ธฐ ๋๋ฌธ์ ์ด์ง ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ API ๊ฒ์ดํธ์จ์ด๋ฅผ ์ค์ ํด์ฃผ์ด์ผ ํ๋ค.

5. API ๋ฐฐํฌํ๊ธฐ



5. ๋๋ค ํ๋ก์ ํธ ์์ฑ & ์ ๋ก๋

> npm i --platform=linux sharp
> npm i axios
const sharp = require('sharp');
const axios = require('axios');
//? http://localhost:8081/thumb/500x700?fname=์ด๋ฏธ์งurl
exports.handler = async (event, context, callback) => {
console.log('event : ', event);
const imgUrl = event.queryStringParameters.fname; // ์ด๋ฏธ์ง url ํ๋ผ๋ฏธํฐ
//* ๋ฆฌ์ฌ์ด์ง ์ค์
const quality = 100; // ์ด๋ฏธ์ง ํ๋ฆฌํฐ (๊ธฐ๋ณธ 80)
const [size1, size2] = event.pathParameters.size.split('x'); // size ๊ฒฝ๋ก๋ณ์ ๊ฐ : [500, 700]
const ext = imgUrl.split('.')[imgUrl.split('.').length - 1]; // ํ์ผ ํฌ๋งท
const requiredFormat = ext === 'jpg' ? 'jpeg' : ext; // sharp ์์๋ jpg ๋ง๊ณ jpeg๋ฅผ ์ฌ์ฉํ๊ธฐ์ ์กฐ์น
// //* ์ด๋ฏธ์ง๋ฅผ ์๋ฒ๋จ์ผ๋ก ajax๋ก ๊ฐ์ ธ์ค๊ธฐ
const img = await axios.get(imgUrl, { responseType: 'arraybuffer' }).then((response) => Buffer.from(response.data));
//* ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง
const imgCompress = await sharp(img)
.resize(parseInt(size1), parseInt(size2), { fit: 'contain' }) // fit : contain ๊ฐ๋ก ์ธ๋ก ๋น์จ์ ๊ฐ์ ์ ์ง
.withMetadata() // ์๋ณธ ์ด๋ฏธ์ง์ ๋ฉํ๋ฐ์ดํฐ ํฌํจ
.toFormat(requiredFormat, { quality }) // ํฌ๋งท / ํ๋ฆฌํฐ ์ง์
.toFile(`resizeIMG.${requiredFormat}`, (err, info) => {
// ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ๋ก์ปฌ์ ์ ์ฅ
console.log(`๋ฆฌ์ฌ์ด์ง ์ด๋ฏธ์ง info : ${JSON.stringify(info, null, 2)}`);
})
.toBuffer(); // ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ๋
ธ๋์์ ์ฝ์์ ์๊ฒ buffer๋ก ๋ณํ
//* ์๋ต ๋ฉ์๋ ์ค์
const response = {
statusCode: 200,
headers: {
'Content-Type': `image/${requiredFormat}`, // image/png ํํ
},
body: imgCompress.toString('base64'), // base64 ํํ๋ก ๋ณํ
isBase64Encoded: true,
};
callback(null, response); // ๋ฆฌ์ฌ์ด์ง๋ ์ด๋ฏธ์ง๋ฅผ ๋ธ๋ผ์ฐ์ ์ ๋จ๊ฒ ์๋ต
};

์ด๋ ๊ฒ ๋๋ค์ API ๊ฒ์ดํธ์จ์ด ์ฐ๊ฒฐ์ ํ์ฌ ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ง ์๋น์ค๋ฅผ ์์ฑํ์๋ค.
๋ธ๋ผ์ฐ์ ์์ ์ค์ ๋ก API ์๋ํฌ์ธํธ url๋ก size๊ฐ๊ณผ ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ฅผ ์ฃผ๊ฒ ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฆฌ์ฌ์ด์ง ๋ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ก ์๋ต ๋ฐ๊ฒ ๋๋ค.
- API-๊ฒ์ดํธ์จ์ด-์๋ํฌ์ธํธ/thumb/300x300?fname=[์ด๋ฏธ์งurl]

์ด ๊ธ์ด ์ข์ผ์ จ๋ค๋ฉด ๊ตฌ๋ & ์ข์์
์ฌ๋ฌ๋ถ์ ๊ตฌ๋
๊ณผ ์ข์์๋
์ ์์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค.