Presinged URL 과 DynamoDB 를 활용하여 안전한 Serverless 웹 페이지 구성

Ⅰ. 개요

Serverless 관련 학습을 하던 중 DynamoDB 에 공유하고자 하는 파일에 대한 데이터를 저장하고, Lambda 를 통해 DynamoDB 테이블을 쿼리하여 해당 파일 데이터를 통해 공유하는 파일의 Presigned URL 을 생성하고, 이를 사용자에게 전달해줌으로서 복잡한 인증 과정 없이 단순하지만 안전한 Serverless 웹 페이지 구성하는 방법에 대하여 실습해보았습니다. 본문은 해당 과정을 review 하여 과정에 대한 이해와 관련 개념에 대하여 설명하는 글 입니다.

진행한 실습의 대략적인 구성도 입니다.

사용자는 Route53을 통해 CloudFront를 거쳐 S3에 저장된 정적 웹 사이트에 접속하게 되고, API Gateway를 통해 연결된 Lambda 는 DynamoDB 를 쿼리하여 해당 데이터로 Presigned URL 을 생성하고, 이 URL을 사용자에게 전달합니다. 사용자는 이 URL 을 통해 안전하게 프라이빗 S3 에 저장된 파일을 공유받을 수 있게 됩니다.

Ⅱ. 본문

  1. DynamoDB 생성

이 과정은 Presigned URL 을 생성하여 안전하게 공유 할 파일에 대한 데이터를 저장하는 DynamoDB 를 생성하는 과정입니다.

Lambda 는 이 DynamoDB 를 쿼리하여 키 값이 일치한다면 저장된 파일의 데이터를 통해 Presigned URL 를 가져옵니다.

테이블 이름과 파티션 키는 원하는 이름으로 지정하여 DynamoDB 생성

파티션 키는 추후에 키값을 입력하는 항목이 됩니다.

2. S3 정적 웹페이지 호스팅

S3 버킷을 생성하여 정적 웹페이지를 호스팅 할 수 있도록 합니다.

1) S3 버킷 생성

버킷 이름은 호스팅하는 정적 웹페이지의 도메인 주소와 동일하게 설정해야합니다.
퍼블릭(인터넷)에 공개될 수 있도록 “모든 퍼블릭 액세스 차단”을 비활성화

2)정적 웹 사이트 호스팅 활성화

생성한 S3 버킷을 선택하면 기본적으로 정적 웹 사이트 호스팅이 비활성화 되어있는데 편집을 선택하여 활성화

정적 웹 사이트 호스팅을 활성화 하고, 인덱스 문서에 작성한 html 파일명을 입력

3) 버킷 정책 입력

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::Bucket-Name/*"
            ]
        }
    ]
}

Amazon S3 > 버킷 > “버킷명” 의 권한 탭에서 버킷 정책을 자신이 생성한 버킷 이름을 넣은 정책으로 위와 같이 편집합니다.

4) 웹페이지 작성 파일 버킷에 업로드

정적 웹페이지 호스팅을 위한 html,css, image 파일 등 미리 준비 된 파일을 정적 웹페이지 호스팅을 할 버킷에 업로드 합니다.

이때, 정적 웹페이지를 구성하는 html 파일에 아래와 같이 사용할 api gateway url을 호출하는 스크립트가 작성되어있어야 합니다.

아래의 코드는 Fetch API 로 작성하였습니다.

5) S3 버킷 엔드포인트로 정적 웹사이트 호스팅 확인

정적 웹 사이트 호스팅이 구성되었으면 버킷 웹 사이트 엔드포인트를 통해 정적 웹사이트 확인이 가능합니다.

3. Lambda 구성

이 과정은 DynamoDB 를 쿼리하여 해당 데이터로 Presigned URL 을 생성하고, 이 URL을 사용자에게 전달 하는 서버리스 앱에 메인 TASK를 담당 할 Lambda 를 구성하는 과정입니다.

1)Lambda 에 부여 할 IAM 역할 생성

IAM > 역할 > 역할 생성에서 신뢰할 수 있는 엔터티 유형은 AWS 서비스를 선택하고, 서비스 또는 사용 사례로 Lambda 를 선택합니다.

권한 추가를 통해 Amazon S3 Full Access 권한과 Amazon DynamoDB Full Access 권한을 추가합니다.

추가된 권환 확인 후 IAM Role 을 생성합니다.

2)Lambda 함수 생성

원하는 함수 이름을 입력하고,

작성된 Lambda 함수 코드에 맞는 런타임을 선택합니다.

기본 실행 역할은 1)에서 생성한 IAM Role ( IAM_Role_for_Lambda ) 를 선택합니다.

AWS-SDK 를 사용하여 DynamoDB 테이블에서 ‘filedata’ 테이블에서 ‘code’를 기준으로 쿼리하고, 쿼리 결과 해당하는 파일이 있는 경우 Presigned URL 을 반환하고 파일이 없는 경우 “none”을 반환하는 코드를 작성하여 Deploy 해줍니다.

코드 예시 참고 )

event 객체에서 이름이 code인 쿼리 문자열 매개변수의 값을 추출하는 코드 예시

DynamoDB 쿼리 결과에서 접근하고자 하는 버킷과 객체의 데이터를 추출하여, AWS S3 서비스에서 파일에 대한 Pre-signed URL을 생성하는 코드 예시

4. API Gateway 생성

API Gateway 는 사용자와 서비스 사이에 위치하여 각각의 서비스 엔드포인트 역할을 대신하여 API Gateway 로 요청을 보내게 되고, 요청을 받은 API Gateway 는 각 엔드포인트로 사용자를 대신하여 서비스에 요청하고, 응답을 받으면 다시 사용자에게 전달하는 프록시 역할도 합니다.

이번 서버리스 구성에서는 사용자가 S3 정적 웹사이트를 통해 Amazon API Gateway 에 요청을 보내면 이와 연결된 서비스 역할을 하는 Lambda 는 이 요청을 받아 처리하고, 응답을 다시 API Gateway 로 전달하면 프록시 역할도 하는 이 API Gateway 가 다시 사용자에게 전달하는 구조로 구성되어있습니다.

1)REST API 생성

Lambda 와 호환하여 사용 할 REST API 를 구축합니다.

원하는 API 이름을 입력하고 API 를 생성합니다.

2) API 리소스 생성

3)메서드 생성

API 게이트웨이에서 API 메서드는 메서드 요청과 메서드 응답을 구현합니다. 백엔드에서 서비스에 액세스하기 위한 요청을 제출하기 위해 클라이언트가 해야 하거나 해야 하는 작업을 정의하고 그에 대한 답변으로 클라이언트가 받는 응답을 정의하기 위해 API 메서드를 설정합니다.

메서드 유형 : GET

통합 유형 : Lambda

-Lambda 함수 : 앞서 생성한 Lambda 함수 선택

4) 메서드에 API 배포

새 스테이지 생성하고 배포

5. 파일용 S3 버킷 생성

정적 웹페이지에서 이미지를 다운로드 할 수 있도록 공유용 이미지 파일을 저장할 프라이빗 S3 버킷을 생성합니다.

해당 버킷의 파일에는 아무나 접근하지 못하도록 모든 퍼블릭 액세스를 차단하여 프라이빗 버킷으로 생성합니다.

공유하여 사용자가 다운받을수 있또록 할 이미지(객체)를 저장합니다.

6. DynamoDB 데이터 입력

1.에서 생성한 DynamoDB 항목을 생성하여 파일에 대한 데이터를 입력합니다.

code 의 값은 사용자가 웹 페이지에서 입력할 코드를 지정하여 입력합니다.

bucket 은 파일이 저장될 버킷 명을 입력합니다.

key 는 파일명을 입력합니다.

7. Route53 도메인 등록 및 ACM 통한 SSL 인증서 설정

1)Route53 호스팅 영역 생성

Route53 > 호스팅영역 > 호스팅영역 생성

보유하고있는 도메인 이름을 입력하여 인터넷 망에서 접근할 수 있도록 퍼블릭 호스팅 영역 생성

호스팅 영역 생성 후 기본으로 생성되는 레코드 값인 NS유형 레코드와 SOA 유형 레코드 중 NS 유형 레코드의 값/트래픽 라우팅 대상 의 네임서버를 도메인을 구입한 곳에 등록시켜준다.

네임서버 변경하여 NS 레코드 값의 값/트래픽 라우팅 대상과 동일한지 확인

8. CloudFront 통한 HTTPS 통신설정

이 과정은 더 안전한 연결을 위하여 CloudFront 의 HTTPS 리디렉션 기능을 사용하여 사용자가 Cloudfront 를 통해 접속할 시 HTTPS 통신이 연결되도록 설정하는 과정입니다.

1)ACM에 SSL 인증서 등록하기

Cloudfront 에서 사용할 SSL 인증서를 ACM에 등록해야합니다.

이때, Cloudfront 에서 사용하는 인증서는 버지니아북부(us-east-1) 리전의 ACM 에 등록해야만 사용 가능합니다.

ACM에서 퍼블릭 인증서 요청을 선택

도메인 이름에 사용하고자 하는 도메인을 입력하고

검증 방법에 DNS 검증 ( Route53에 도메인이 등록되어있어야 사용가능 ) 을 선택

검증 대기 중인 인증서를 선택하여 Route53 레코드 생성을 선택

레코드를 생성하고 잠시 대기하면

검증이 성공하고

인증서가 발급됩니다.

이제 이 버지니아 북부에서 발급받은 인증서는 Cloudfront 에서 사용 가능합니다.

2)Cloudfront 생성하기

호스팅하고자 하는 S3 를 가르키는 Cloudfront 배포를 생성합니다.

Origin domain 은 정적 웹사이트 호스팅을 할 S3 엔드포인트를 선택하고 이름은 Route53에 등록한 도메인 주소를 입력

이때 , 프로토콜은 HTTP만 해당으로 선택합니다.

원본 프로토콜을 HTTP만 해당으로 선택하면 Cloudfront 와 원본(S3) 사이 통신은 HTTP로 이루어 지고, 원본(S3) 에 HTTPS 프로토콜 관련 설정이 필요없습니다.

하지만 기본 캐시 동작 뷰어 프로토콜 정책은 Redirect HTTP to HTTPS 를 선택하여 외부 인터넷에서 CloudFront 까지의 접은은 HTTPS 통신이 이루어지도록 하여 간단한 설정으로 보다 안전한 통신이 가능하도록 설정 할 수 있습니다. (아래 화면 참고)

설정 부분에서 실제 사용할 도메인 주소를 입력하고, 사용자 정의 SSL 인증서에 앞서 ACM 에서 발급 받은 SSL 인증서를 선택

ACM에서 발급 받은 인증서를 Cloudfront 에 등록하는 것을 통해 이 인증서는 무료로 제공됩니다.

이처럼 Cloudfront 를 사용하면 AWS 리소스에서 CloudFront 엣지 로케이션으로 전송되는 캐싱 가능한 데이터에 대한 추가 요금이 부과되지 않을 뿐만 아니라 무료로 SSL 인증서도 사용 가능하다.

배포 후 활성화 되면 Cloudfront 를 통해 접속이 가능합니다.

3) Route53과 연결

단순 레코드 정의를 선택하고

레코드 이름에 CloudFront에서 입력한 대체도메인과 동일한 이름을 입력하고,

값/트래픽 라우팅 대상에서 CloudFront 배포에 대한 별칭을 선택한 후

앞서 생성한 Cloudfront 배포를 선택합니다.

이렇게 레코드가 생성되면 해당 주소로 접속 테스트를 진행합니다.

인증서가 유효한 HTTPS 보안 연결이 되었음을 확인 가능

DynamoDB 에 설정한 키 값 을 입력하면

안전하게 이미지를 다운 받을수 있었습니다.

Ⅲ. 마무리

Serverless 아키텍처는 어떠한 서비스와 결합하느냐에 따라 , 어떠한 Lambda 함수코드를 사용함에 따라 다양하고 고도화 된 기능을 편리하게 구성할 수 있습니다.

DynamoDB 에 파일에 대한 데이터를 저장하고, Lambda 를 통해 DynamoDB 테이블을 쿼리하여 공유하는 파일의 Presigned URL 을 생성하고, 이를 사용자에게 전달해줌으로서 복잡한 인증 과정 없이 단순하지만 보다 안전한 Serverless 웹 페이지 구성하는 과정에 대하여 살펴 보았습니다.

API gateway , Lambda 와 같은 서비스를 통해 S3 에서 호스팅 하는 정적 웹페이지도 동적 웹페이지 처럼 사용할 수 있었으며, Dynamo DB 와 S3의 Presigned URL 기능, Cloudfront 의 HTTPS 리디렉션 기능 등 을 활용하여 간단한 설정만으로 합리적인 비용으로 보다 안전한 Serverless 웹 사이트를 구축 할 수 있었습니다.

참고 자료 출처

[AWS 강의실] (Serverless 기반 아키텍처/개발) 7.AWS Serverless 기반 웹앱

[Enlico portolan] Generate a Presigned URL in S3 and Lambda – NodeJS Tutorial

https://burning-camp.tistory.com/43

Create Serverless REST APIs using – AWS Lambda, DynamoDB, API Gateway, JavaScript | by Amir Mustafa | AWS in Plain English

https://serverlessland.com/patterns/s3-upload-presignedurl-api-cdk-ts?ref=search
https://wildeveloperetrain.tistory.com/205
https://docs.aws.amazon.com/ko_kr/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html
https://docs.aws.amazon.com/ko_kr/apigateway/latest/developerguide/welcome.html

https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-requirements.html#https-requirements-aws-region

https://docs.aws.amazon.com/ko_kr/apigateway/latest/developerguide/how-to-method-settings.html

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다