현재 회사내에서 썸네일을 작업하는 방법으로는
1. 이미지가 올라온다.
2. 해당 이미지를 올리는 곳은 썸네일로 자를 것인지 확인한다.
3. 썸네일을 자르는 곳이라면, 지정된 이미지 사이즈로 썸네일을 자른다.
라는 방식을 통하여 썸네일을 생성하는 작업을 하였는데..
계속 이방식을 고수할수 없던 큰 문제점으로 보여지는 3가지 항목
1. 이미지의 썸네일을 지정해둔 크기로만 생성한다.
2. 이미지가 올라오면 썸네일을 자른다. 자른 썸네일은 S3어 업로드하여 저장
3. 사용하지 않더라도 이미진느 계속 자른다.
문제점을 해결하고자 이미지 리사이징 작업을 도입하기로 결정을합니다.
-----------------------------------------------------------------------------------
해당 부분의 작업은
https://heropy.blog/2019/07/21/resizing-images-cloudfrount-lambda/를 보고 참고하였습니다.
Lamda@edge를 위하여 IAM 쪽 작업을 진행합니다.
[ IAM ]
정책 생성 (IAM → 정책)
1. 정책 생성을 선택합니다.
2. JSON을 선택해 정책을 입력합니다.
정책 ↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "iam:CreateServiceLinkedRole", "lambda:GetFunction", "lambda:EnableReplication", "cloudfront:UpdateDistribution", "s3:GetObject", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeLogStreams" ], "Resource": "*" } ] } | cs |
정책내의 Version 은 수정하지 않습니다.
3. 정책의 이름(ResizingImages)과 설명을 작성합니다.
이름은 원하는걸로 해도 무방합니다,
4. 정책 생성을 마무리합니다.
역할 생성 (IAM → 역할)
1. 역할만들기를 선택합니다.
2. 사용사례선택으로 Lambda를 선택합니다.
3. 연결할 정책을 위에서 작성한 정책명을 입력하여 선택합니다.
4. 역할의 이름(ResizingImages)과 설명을 작성합니다.
이름은 원하는걸로 해도 무방합니다.
5. 역할 생성을 마무리합니다.
역할 신뢰관계 수정 (IAM → 역할 → 수정할 역할 상세)
1. 위에서 생성한 역할을 선택합니다.
2. 신뢰관계 → 신뢰관계편집을 선택합니다.
3. 신뢰관계를 하단의 내용으로 수정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "edgelambda.amazonaws.com", "lambda.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] } | cs |
4. 해당 정보로 신뢰관계를 수정을 마무리합니다.
[ S3 ]
테스트를 위한 버킷의 퍼블릭 액세스 권한이 필요할 수 있습니다.
버킷을 소유한 AWS 계정이 객체도 소유해야 합니다.
요청된 객체가 버킷에 존재해야 합니다.
버킷 Root 경로에 favicon.ico 파일을 업로드하지 않으면 S3 Favicon 에러가 발생할 수 있습니다.
→ 없다고 해서 문제가 생기는 건 아닙니다.
다만 저 아이콘이 각 브라우저의 기본 아이콘으로 노출 되어진다의 차이가 있습니다.
[ Cloud Front]
1. Create Distribution을 선택합니다.
2. Web에서 Get Started를 선택하고 다음과 같이 설정합니다.
Origin Domain Name: 웹 콘텐츠를 가져올 AWS S3 Bucket
Restrict Bucket Access: Yes(항상 CloudFront URL로 S3 액세스하도록 요구)
Origin Access Identity: Create a New Identity
Grant Read Permissions on Bucket: Yes, Update Bucket Policy(CloudFront가 S3의 버킷 정책에 액세스하여 업데이트)
Allowed HTTP Methods : GET, HEAD, OPTIONS (Http 요청 방식에 따라 각 설정필요)
Object Caching : Customize (설정한 시간을 기준으로 해당 캐시 유지, Customize가 필요한 경우 설정)
Minimum TTL : 0
Maximum TTL : 31536000
Default TTL : 1800
Query String Forwarding and Caching: Forward all, cache based on whitelist
Query String Whitelist: w, h, f, q(CloudFront가 사용할(캐싱 기반) 쿼리스트링 매개 변수 정의, 각 단어 입력후 엔터를 통하여 입력)
Compress Objects Automatically: Yes(Accept-Encoding: gzip 요청에 대한 콘텐츠 압축 여부)
Comment: ResizingImages(Distribution 구분을 위한 간략한 이름/설명)
Alternate Domain Names(CNAMEs) : s3의 객체가 보여지는 도메인 명
SSL Certificate : Custom SSL Certificate (example.com) → 위에서 작성된 도메인의 인증서 선택
3. Create Distribution을 마무리합니다.
생성한 Clound front는 람다 생성이후 수정을 하러 올 예정입니다.
[ Lambda ]
200326 Lambda@Edge의 리전이 서울을 지원하지 않습니다.
지원되는 미국 동부(버지니아 북부)(us-east-1)로 들어가서 함수를 생성합니다!
함수 생성 (Lambda → 함수)
1. 함수 생성을 선택합니다.
2. 함수 명(Resizing프로젝트명Images)을 입력합니다.
3. 런타임(Node.js 12.x)을 선택합니다.
4. 실행 역할 선택하거나 생성하여를 펼칩니다
실행 역할: 기존 역할 사용 → 위에서 생성한 IAM정책(ResizingImages)를 선택합니다.
5. 함수 생성을 마무리합니다.
함수 수정 (Lambda → 함수 → 수정하고자 하는 함수 )
1. 위에서 생성한 함수를 선택합니다.
2. 스크롤을 내리다 기본설정의 제한시간을 10초로 설정합니다.
3. 저장을 눌러서 수정을 완료합니다.
Cloud9을 통한 Lambda 함수 수정
위에서 작성한 Lambda의 Region과 동일한 곳에서 Cloud9을 생성합니다.
- Cloud9 생성
1. Create environment를 선택합니다.
2. Name environment의 Name(Resizing프로젝트명Images)과 Description을 입력합니다.
3. Configure settings를 아래와 같이 설정합니다.
Create a new instance for environment (EC2)
t2.micro (1 GiB RAM + 1 vCPU)
Amazon Linux
After 30 minutes (default)
4. Create environment를 마무리 합니다.
- Cloud9에 Lambda 불러오기
1. 화면 오른쪽 메뉴 중 AWS Resources를 선택합니다.
2. Lambda(us-east-1)/Remote Functions 목록의 위에서 생성한 Lambda함수(Resizing프로젝트명Images)를 우클릭하여 Import합니다.
3. 불러온 람다 함수로 접근하기 위해 터미널(Terminal)을 이용합니다.(package.json을 생성하고 Sharp 모듈을 설치합니다.)
1 2 3 | >> cd Resizing프로젝트명Images >> npm init -y >> npm i sharp | cs |
4. 설치이후 index.js을 아래 코드와 같이 수정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | 'use strict'; const querystring = require('querystring'); // Don't install. const AWS = require('aws-sdk'); // Don't install. const Sharp = require('sharp'); const S3 = new AWS.S3({ region: 'ap-northeast-2' //버킷 Region }); const BUCKET = '버킷명'; exports.handler = async (event, context, callback) => { const { request, response } = event.Records[0].cf; // Parameters are w, h, f, q and indicate width, height, format and quality. const params = querystring.parse(request.querystring); // Required width or height value. if (!params.w && !params.h) { return callback(null, response); } // Extract name and format. const { uri } = request; const [, imageName, extension] = uri.match(/\/?(.*)\.(.*)/); //이미지 파일이 아니라면 썸네일 굽지 않음 if (extension !=='jpg'&& extension !=='jpeg' && extension !=='webp' && extension !== 'bmp' && extension != 'png') { console.log('not image file requested!'); return callback(null, response); } // Init variables let width; let height; let format; let quality; // Sharp는 이미지 포맷에 따라서 품질(quality)의 기본값이 다릅니다. let s3Object; let resizedImage; // Init sizes. width = parseInt(params.w, 10) ? parseInt(params.w, 10) : null; height = parseInt(params.h, 10) ? parseInt(params.h, 10) : null; // Init quality. if (parseInt(params.q, 10)) { quality = parseInt(params.q, 10); } // Init format. format = params.f ? params.f : 'webp'; //따로 포맷형태를 주지않으면 webp로 변경 format = format === 'jpg' ? 'jpeg' : format; // For AWS CloudWatch. console.log(`parmas: ${JSON.stringify(params)}`); // Cannot convert object to primitive value. console.log(`name: ${imageName}.${extension}`); // Favicon error, if name is `favicon.ico`. try { s3Object = await S3.getObject({ Bucket: BUCKET, Key: decodeURI(imageName + '.' + extension) }).promise(); } catch (error) { console.log('S3.getObject: ', error); return callback(error); } try { resizedImage = await Sharp(s3Object.Body) .resize(width, height) .toFormat(format, { quality }) .toBuffer(); } catch (error) { console.log('Sharp: ', error); return callback(error); } const resizedImageByteLength = Buffer.byteLength(resizedImage, 'base64'); console.log('byteLength: ', resizedImageByteLength); // `response.body`가 변경된 경우 1MB까지만 허용됩니다. if (resizedImageByteLength >= 1 * 1024 * 1024) { return callback(null, response); } response.status = 200; response.body = resizedImage.toString('base64'); response.bodyEncoding = 'base64'; response.headers['content-type'] = [ { key: 'Content-Type', value: `image/${format}` }, ]; return callback(null, response); }; | cs |
5. 작성한 람다 함수를 $LATEST 버전으로 배포합니다.
( Lambda(us-east-1)/Local Functions 목록의 해당 Lambda함수를 우클릭한뒤 Deploy합니다.
만약 Local Function에서 안보이면 새로고침을 한번 합니다)
Lambda 버전 게시
1. 함수 목록에서 버전을 게시한 Lambda함수를 선택합니다.
2. 오른쪽 위 메뉴 중 ‘작업’의 새 버전 게시를 선택합니다.
3. ‘$LATEST의 새 버전 게시’의 ‘버전 설명’을 입력하고 새로운 버전을 게시합니다.
4. 게시된 새 버전의 ARN 복사(ARN - arn:aws:lambda~~~~~:1, 화면 오른쪽 위)하여 CloudFront에 연결해야 합니다.
CloudFront 수정
위에서 게시한 Lambda를 CloudFront에 연결하러갑니다.
1. s3와 연결된 cloudfront의 상세를 들어갑니다.
2. Behaviors 탭의 항목을 수정을 선택합니다.
3. Lambda Function Associations:
- CloudFront Event: Origin Response
- Lambda Function ARN: Lambda 함수에서 복사한 ARN 입력합니다
4. 수정을 마무리합니다.
추가적인 Lambda 수정 시
1. $LATEST 버전의 작업에서 Lambda@Edge 배포를 선택합니다.
2. 이 함수에 기존 CloudFront 트리거 사용을 선택합니다. 원하는 버전의 트리거를 선택합니다.
- 새로운 트리거를 선택시
배포 : 해당 Cloudfront ID를 검색하여 배포할 곳을 선택합니다.
CloudFront 이벤트 : 오리진응답
3. 배포합니다
----------------------------------------------------------
이렇게 이미지 리사이징이 완료되었습니다!!
cloudfront도메인명?w=500&f=jpg&q=90 을 입력하면 해당 이미지와 포맷에 맞게 이미지를 가져오는것을 확인 할 수 있습니다!!
'IT > AWS' 카테고리의 다른 글
AWS AMI 다른 계정과 공유하기 (0) | 2020.07.07 |
---|---|
AWS Aurora에서 Lambda 연결하기 (0) | 2020.07.07 |
Lambda Layer를 통하여 Python에 패키지 넣기 (0) | 2020.06.29 |
[AWS] EC2 비교 온디맨드/스팟/예약 (0) | 2020.03.25 |
[AWS] API Gateway를 통한 서버 API 제작기 -1 (0) | 2020.03.25 |