본문 바로가기
Back-end

AWS 서버리스 단축URL 서비스 만들기 - 4

by 노아론 2021. 7. 30.

저번 단축 URL 생성 API 구현에 이어서 이번 글에서는 단축 URL로 접속 시, 원 URL로 이동시켜주는 Forwarder API 구현을 해볼 것이다.
이 또한 앞서서 진행한 단축 URL 생성 API와 유사한 방식으로 진행된다.

빨간 박스로 표시된 Forwarder API를 구현해본다

 

페이지 리다이렉트하는 Forwarder API 구현하기

이제 단축된 URL을 접속할 때 원 URL로 이동시켜주는 Forwarder API를 구현할 것이다.
단축 URL 서비스 아키텍쳐에서 두 개의 람다 중 빨간 박스에 있는 람다 함수를 만드는 차례다.
이 API를 구현하면 단축 URL의 기능으로서 마무리 단계에 접어들게 된다.
shorten-url-forwarder 라는 이름으로 람다를 생성해본다

 
생성이 되었다면 아래와 같이 뜰 것이다.

 
다시 vscode로 돌아가 방금 생성한 람다를 다운로드 해보자

 
람다를 다운로드 받고 난 프로젝트 구조의 현재 상태이다.
shorten-url-forwarder 폴더 아래에 lambda_function.py 이 다운로드 되었음을 알 수 있다.

 
구현에 앞서서 Forwarder API는 어떤 모습을 갖춰야 할지 고민해보자.
Forwarder API는 단축된 URL을 원래의 URL로 이동시키는 기능을 제공해야 한다.
그렇다면 단축된 URL은 브라우저 주소 창에서 입력되거나, 누군가 메신저로 주고받으면서 하이퍼링크 형태로 제공이 될 것이다 
예를 들면 이런 형태이다.

 
HTTP Method 관점에서 생각해본다면 단축 URL 생성 기능을 하는 Generator API와는 다른 점이 있다는 것을 눈치 챌 수 있다.
Generator API는 Request Body를 넣어 POST method로 요청을 하였다면 Forwarder API는 브라우저에 바로 입력하거나 HTTP 하이퍼링크를 통해 접속을 하게 된다.
따라서 GET Method로 이뤄져야 한다. 
그렇다면 서버에 넘겨줄 파라미터는 어떻게 보낼까?
hufs.me/adf3 라고 한다면 adf3가 path parameter로서 보내지게 된다.
이 부분에 대해선 API 게이트웨이에서 정의할 것이다 
본격적으로 Forwarder API를 구현해보자
자세한 코드 내용은 주석으로 달았다.

import os
import boto3
from botocore.client import Config

S3_BUCKET = os.environ['S3_BUCKET']
# S3 버킷 이름을 담은 변수를 전역변수로 두었고 버킷 이름은 환경변수에 저장을 한다 


def lambda_handler(event, context):
    s3 = boto3.client('s3', config=Config(signature_version='s3v4'))
    # S3에 접근할 수 있도록 클라이언트를 생성한다

    try:
        shorten_key = "url/" + event.get("pathParameters").get("key")
        # key 라는 값은 어디서 가져올까?
        resp = s3.head_object(Bucket=S3_BUCKET, Key=shorten_key)
        # S3 버킷에서 파일 경로를 Key에 지정한다
        redirect_url = resp.get('WebsiteRedirectLocation')
        # S3 버킷에서 가져온 파일에 대해 WebsiteRedirectLocation 속성의 값을 가져온다.
        # 우리가 원하는 원 URL 값이 된다
    except Exception as e:
        print(e)
        redirect_url = os.environ["HOST"]
        # S3 버킷에 접속하면서 버킷이 존재하지 않거나 연결이 불안정한 이유로 예외가 발생할 수 있다.
        # 이러한 경우를 위해 redirect_url로 서비스의 주소로 가도록 설정하였다

    return {
        "statusCode": 301,
        "headers": {
            "Location": redirect_url
        },
        "isBase64Encoded": False,
    }
    # 301 상태 코드는 요청에 대해 헤더에 주어진 값으로 완전히 옮겨졌음을 나타낸다

 
여기서 301 Moved Permanently 상태 응답이 무엇일까?
원 콘텐츠가 새로운 URL로 옮겨질 때의 상태코드이다.
더불어 우리는 위 API에서 GET 메소드를 사용할 것이다.
상태 응답 명세에서 301 은 GET과 HEAD 메소드의 응답으로만 사용하도록 되어 있다
만일 POST 메소드에서 리다이렉트를 수행한다면 308 Permanent Redirect를 사용해야 한다.
자세한 HTTP 상태 코드는 아래 Mozilla의 문서에서 확인할 수 있다
https://developer.mozilla.org/ko/docs/Web/HTTP/Status/301
HTTP 상태코드에 대한 설명은 여기서 마치고
다시 위에서 작성한 코드를 업로드 해보자
AWS Toolkit 탐색 창에서 shorten-url-forwarder 에 우측 클릭하여 Upload Lambda를 누른다

 
이전에 진행했던 람다 업로드와 동일하게 업로드 타입은 Directory로 선택한다

 
우리가 작업한 람다 함수 파일이 위치한 폴더를 클릭한다  

 
Build directory? 단계는 No를 선택한다.

 
이제 업로드가 됨을 볼 수 있다.
직접 AWS에 들어가 확인해보자
성공적으로 업로드 되었음을 확인하였다.

 
이제 코드에서 환경 변수를 가져올 수 있게 Configuration 탭에서 환경변수를 지정해보자
Environment variables에 들어가 Edit을 눌러 필요한 환경 변수인 HOSTS3_BUCKET 에 대해 지정을 하면 된다

 
S3 버킷에 접근할 권한이 있어야 하므로 Configuration의 Permissions에 들어가서 권한 추가를 해야한다.
Execution role에서 Role name을 클릭한다

 
Attach policies를 눌러 권한을 추가할 것이다

 
AmazonS3ReadOnlyAccess를 선택하여 추가한다

필요한 권한 설정은 완료되었으니 이제 이 람다 함수도 API 게이트웨이를 트리거로 연결할 것이다.
Add trigger를 누르자
트리거 설정은 API Gateway로 설정한다.
API는 새로 만들지 않고 목록에서 이전 Generator API의 트리거를 지정했을 때 만들었던 shorten-url-generator-API 를 선택하였다
Security는 단축 URL를 가지고 누구나 접속할 수 있어야 하므로 Open을 선택하였다.

 
이제 API Gateway가 트리거로 추가되었다 

 
API Gateway로 들어가서 API 리소스 설정에 대해 변경해보려고 한다
들어가면 /shorten-url-forwarder 로 경로가 설정되어 있을 것이다.
우린 이 리소스를 사용하지 않고 새로 추가할 것이다

 
먼저 리소스를 생성해주자
Actions 버튼에서 Create Resource를 선택한다

 
 
리소스 네임을 적절한 이름으로 입력하고 리소스의 경로는 /{key} 로 설정해준다

 
리소스가 생성되었다면 /{key} 리소스를 선택하고 Actions 버튼을 눌러 Create Method를 선택한다

 
Method는 GET으로 선택하고 체크 버튼을 누른다

 
체크를 누르면 아래와 같이 Setup 페이지가 나온다
Integration type은 Lambda Function을 선택하고 우리가 지금 진행하는 Forwarder API는 HTTP 응답 상태 코드를 지정할 수 있어야 하므로 Lambda Proxy Integration에는 체크를 한다.
Lambda Function 칸에는 람다 함수 이름을 입력하면 된다
그리고 Save를 눌러 생성을 해본다

 
이제 불필요하게 생성되었던 /shorten-url-forwarder 리소스와 /{key} 리소스의 OPTIONS 메소드는 제거하자
OPTIONS 메소드를 클릭하고 Delete Method를 선택한다.
/shorten-url-forwarder 리소스를 제거하는 경우엔 해당 리소스를 클릭하고 Delete Resource를 선택하면 된다.

Delete API를 하는 경우 현재 보이는 모든 리소스와 Method가 제거되니 주의한다.

 
필요하지 않은 것들을 제거하면 아래와 같이 남아있게 된다.

 
이제 Get Method Execution에서 Client 박스에 있는 TEST를 눌러 동작 확인을 해보자

 
key로는 우리가 저번 글에서 생성했던 단축 URL의 생성된 난수인 nrb0을 입력해보자
그리고 Test 버튼을 누르면 301로 상태코드가 확인되고 Response Body는 no data로 뜨게 되는 것을 확인할 수 있다. 

 
그런데 정말 페이지가 이동되는지 위의 테스트를 통해서는 잘 모르겠다는 생각이 들 수 있다
 
그렇다면 직접 URL를 입력해 들어가보자
우선 앞서 변경한 API에 대해서 배포를 해야한다. Actions 버튼에서 Deploy API를 누른다. 

 
배포 스테이지는 default로 설정한다
이번 배포에 대한 설명을 기재하고 싶다면 아래 Deployment description에 적으면 된다

 
배포가 되었고 API를 호출 할 수 있는 주소는 파란색 메세지에서 확인할 수 있다.  
우리의 API 리소스는 /{key} 이기에 
리다이렉트 해줄 주소는 https://yrbjrmwdr7.execute-api.ap-northeast-2.amazonaws.com/default/{key}가 될 것이다.


만일 위 페이지를 지나쳤다면 API 엔드포인트 전체 경로는 해당 람다 함수의 API 게이트웨이 트리거의 상세 정보에서 확인할 수 있다.   


저번 글에서 생성되었던 단축 URL 난수 코드인 nrb0을 key 자리에 둘 것이다
아래와 같은 전체 단축 URL 이 완성된다.
https://yrbjrmwdr7.execute-api.ap-northeast-2.amazonaws.com/default/nrb0
정상적으로 리다이렉트가 됨을 확인할 수 있다.
원 URL은 S3버킷의 해당 오브젝의 메타데이터에서 확인할 수 있듯 https://github.com/roharon 이다.

S3의 url/nrb0 오브젝트의 Metadata

 
그런데 여기서 의문점이 들 수 있다.
우린 단축 URL서비스를 만들고 있는데 생성되었다는 URL이 원 URL보다 훨씬 길다!
이는 https://yrbjrmwdr7.execute-api.ap-northeast-2.amazonaws.com/default/ 가 API 엔드포인트이기 떄문이다.
우린 나중에 이 값을 커스텀 도메인을 이용해 https://hufs.me 에 연결할 것이다.
이렇게 연결하게 된다면 최종적으로 hufs.me/nrb0의 형태가 된다. 
이렇게 단축 URL 서비스에 필요한 API를 모두 구현하였다.

다음 글은 계획하고 있지 않습니다
아래의 AWS 문서를 참고하여 S3의 정적 웹사이트 호스팅을 이용할 수 있습니다
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/WebsiteHosting.html


다음 글에선 S3의 정적 호스팅 기능을 이용해 웹사이트를 만들고 커스텀 도메인을 연결하는 내용에 대해서 다뤄보고자 한다. 

댓글