순서대로 해봅시다.

1) IAM 정책 및 역할 생성

1. IAM 정책 생성

  • 정책 선택
  • 정책 생성 선택
  • JSON 선택 및 아래 정책 입력
  • 정책 검토 선택
  • 정책 이름 ResizingImagePolicy 또는 원하는 이름 선택 (설명 옵션)
  • 정책 생성 선택
{
    "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": "*"
        }
    ]
}

2. IAM 역할 생성

  • 역할 선택
  • 역할 만들기 선택
  • 신뢰 할 수 있는 유형의 개체 선택 - AWS 서비스
  • 사용 사례 선택 - Lambda
  • 다음:권한 선택
  • 권한 정책 설정
  • 정책 필터에 1. 정책 생성을 통해 생성된 정책 검색 (ResizingImagePolicy) 후 선택
  • 다음:태그 선택 (skip)
  • 다음:검토 선택
  • 역할 이름 ResizingImageRole 또는 원하는 이름 선택 (설명 옵션)
  • 역할 만들기

3. 역할 신뢰 관계(정책) 수정

  • 역할에서 만든 ResizingImageRole 선택
  • 신뢰 관계 선택
  • 신뢰 관계 편집 선택
  • 아래 json 입력
  • 신뢰 정책 업데이트 선택
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "edgelambda.amazonaws.com",
          "lambda.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

2) S3 생성

1. 버킷 생성

  • 버킷 만들기 선택
  • 원하는 버켓 이름 입력
  • 리전은 상관 없음 (저는 seoul로 선택)
  • 생성 선택

3) Lambda 함수 생성

1. Lambda@Edge 로 생성

중요! 반드시 버지니아 북부(us-east-1)에서 생성할 것!!

  • 왼쪽 상단 지역 - 버지니아 북부 선택
  • Lambda - 함수 생성 선택
  • 새로 작성 선택
  • 함수이름 resize-image 또는 원하는 함수명 입력
  • 런타임 Node.js 12.x 선택
  • 권한 아래 실행 역할을 선택하거나 생성하여 클릭
  • 기존 역할 사용 선택
  • 전에 만든 ResizingImageRole 검색 후 선택
  • 함수 생성

2. 함수 제한 시간 수정

  • 생성된 함수 하단의 기본 설정 - 편집 선택
  • 제한 시간 3초 -> 10초 변경

4) Cloud9을 활용한 Lambda 함수 작성

Cloud9은 AWS에서 제공하는 유료IDE 서비스

1. Cloud9을 통한 인스턴스 생성

  • 왼쪽 상단 지역 - 버지니아 북부 선택
  • Cloud9 - Create environment 선택
  • Name에 resize-image 또는 원하는 이름 입력 (Description 은 옵션)
  • Next step 선택
  • Environment type - Create a new EC2 instance for environment 선택
  • Instance type - t2.micro 선택
  • Platform - Amazon Linux 선택
  • Cost-saving setting - After 30 minutes 선택
  • Next step 선택
  • Create environment 선택

2. 생성된 인스턴스를 통해 lambda 함수 수정

  • 우측에 사람인 모양 람다 클릭
  • Remote Functions - resize-image 더블 클릭
  • import 선택
  • 아래 터미널에서 명령어를 통한 npm init, 라이브러리 설치
  • cd resize-image
  • npm init -y
  • npm i sharp
  • 아래 코드 복사 붙여넣기

    아래 코드 S3 내 region, BUCKET 내 이름은 내가 설정한 지역, 이름으로 변경

  • command+s 또는 control+s 로 저장
  • 우측 상단에 새로고침 버튼 클릭
  • Local Functions 의 resize-image 우클릭
  • Deploy 선택
'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'
});
const BUCKET = 'resize-image';

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(/\/?(.*)\.(.*)/);

  // 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 : extension;
  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);
};

5) Lambda 함수 새 버전 게시

1. 람다 함수 새 버전 게시하기

  • 좌측 상단 버지니아 선택
  • Lambda - resize-image 선택
  • 구분자 - 버전 - $LATEST 선택
  • 작업 - 새 버전 발행 선택 (버전 설명은 옵션)
  • 게시 선택
  • 작업 선택
  • 새 버전 발행 선택 (버전 설명은 옵션임)

6) CloudFront 에 Lambda 연결하기

1. CloudFront의 Distribution 생성하기

  • CloudFront - Distributions - Create Distribution 선택
  • Web - Get Started 선택
  • Origin Domain Name - 전에 생성한 S3 검색 후 선택 (Origin ID 자동으로 추가됨)
  • Restrict Bucket Access - Yes 선택 (항상 Cloud Front URL 로 S3액세스 하도록)
  • Origin Access Identity - Create a New Identity 선택
  • Grant Read Permissions on Bucket - Yes, Update Bucket Policy 선택 (CloudFront 가 S3 버킷 정책에 엑세스하여 업데이트)
  • Cache and origin request settings - Use legacy cache settings 선택
  • Cache Based on Selected Request Headers - None(Improves Caching) 선택
  • Forward Cookies - None(Improves Caching) 선택
  • Query String Forwarding and Caching - Forward all, cache based on whitelist 선택
  • Query String WhiteList - w,h,f,q 를 순서대로 순서대로 적을 것
    (w, enter, h, enter, f, enter, q, enter)
  • Compress Objects Automatically - Yes 선택
  • Create Distribution 선택 후 생성

2. Lambda 의 ARN 추출하기

  • Lambda - resize-image 선택
  • 구분자 - 버전 - 1 선택
  • 상단의 ARN 복사

3. CloudFront - Lambda 연결하기

Lambda Function Associations 을 통해 CloudFront + Lambda 연결

  • CloudFront - Distributions - 생성된 Distribution 선택
  • Behaviors 선택
  • 생성된 Default 클릭 후 Edit 선택
  • 최하단의 Lambda Function Associations 수정
    • CloudFront Event - Origin Response 선택
    • Lambda Function ARN - 추출한 ARN 붙여넣기
    • Yes, Edit 선택

4. CloudFront - Lambda 연결 확인하기

  • Lambda - resize-image 선택
  • 구분자 - 버전 - 1 선택
  • 디자이너 클릭
  • CloudFront - Lambda 가 연결 되어 있으면 정상적으로 진행된 것임

7) S3에 이미지 업로드 후 불러오기

  • 아래 이미지를 로컬에 저장 (image.png)
  • S3 버켓에 업로드 하기
  • CloudFront - Distributions - 생성된 Distribution 선택
  • General - Domain Name 복사

profile
제가 겪은 이슈에 대해서 정리합니다. 기억보다는 기록이 더 낫다고 생각합니다.

0개의 댓글