Overview

필자는 요즘 AWS Lambda와 API Gateway, SNS, SQS 를 사용하여 백엔드 개발을 하고 있습니다.

백엔드는 웹, 앱 등 프론트엔드(클라이언트)에서 필요한 정보 조회나, 데이터 등록, 수정, 배치 등 사용자 눈에 보이지 않는 부분에서 비지니스 로직과 함께, 데이터베이스가 필요하면 데이터베이스를 사용하여 처리 한 후 요청한 프론트엔드(클라이언트)에게 응답 및 처리을 해 줌으로써 그 역할이 종료됩니다.

예전 개발방법과는 다르게, 서버가 없는 형태로 구현을 해야 하기 때문에 AWS에서 제공하는 Lambda 서비스(API Gateway, SNS, SQS 등등)로 구성하여 Lambda에 트리거를 연결 시켜 처리하는 방법으로 진행하고 있습니다.

API Gateway, SNS, SQS 등에서 제공해야 할 기능들은 많습니다.

주기적인 스케쥴링, api, 대용량 처리 등 그 기능에 따라 관리하는 Lambda 함수도 늘어나게 됩니다.

많은 Lambda와 트리거의 매칭을 어떻게 체계적으로 관리하고 유지보수를 쉽게 할 수 있을지 이번 글을 통해 간단하게 코드 작성 및 샘플을 만들어보기로 합니다.

이전 글 확인하기

이 글에서는 Lambda에 SNS 트리거를 연결하여 해보겠습니다.

  1. Lambda 함수를 생성해줍니다.
decorator


2. 트리거를 추가합니다.

decorator


3. 2번과 동일한 방법으로 SNS 트리거를 3~4개 연결해 줍니다.

4. 최종 트리거 모습입니다.

decorator


이제 사전 준비는 모두 끝났습니다. 트리거를 받아서 처리하는 Lambda의 코드를 작성하겠습니다.

  1. 기본 코드를 작성합니다. SNS 트리거로 Lambda가 실행이 되면 아래와 같은 코드를 실행합니다.
decorator


2. 작성된 코드에서는 모든 처리가 공통으로 되기 때문에 트리거로 추가한 SNS 이벤트에 따라서 분기 처리를 할 수가 없습니다. 그럼 SNS 1개당 1개의 Lambda를 생성하여 트리거를 추가해줘야 합니다. 하지만 저는 Lambda가 많이 생기는 걸 원하지 않습니다. Lambda 1개의 파일로 많은 SNS 트리거 처리를 하고 싶습니다. 그래서 아래와 같은 코드로 SNS 별로 분기 처리를 하게 되었습니다.

decorator


이런 식으로 분기 처리를 해서 1개의 Lambda 핸들러로 손쉽게 관리를 할 수 있게 되었습니다.

트리거가 몇 개 없을 때는 위와 같은 코드가 직관적이기도 하고, 개발 시간도 단축할 수 가 있을 거 같습니다. 하지만 API일 경우는 어떻게 될까요? 이전에 개발 하던 프로젝트의 특정 메뉴 핸들러 소스 입니다.

decorator
(분기 처리만 봐도 가독성도 상당히 안좋습니다.)


위와 같은 문제로 저는 Python의 데코레이터 패턴을 이용하여 AWS 에서 서비스하고 있는 Lambda 트리거들에 대한 라우팅을 하기로 생각을 합니다.

우선 라우팅을 어떻게 할 것인가를 고민을 하였습니다. 고민결과 아래와 같이 하기로 결정을 합니다.

  • Lambda 실행하여 처리를 어떤식으로 진행할지 프로세스를 먼저 결정합니다.
decorator


  • 라우터 & 데코레이터 UML 일부 발췌
decorator


  • 라우터가 컨트롤러를 로드 후 url_map의 트리거 정보와 컨트롤러 정보
decorator


  • 라우터 일부 코드 ( 컨트롤러 클래스 로드)
decorator


  • SNS 데코레이터 일부코드
decorator
decorator
decorator


현재 코드는 손 볼 곳은 많이 있지만 대략 검증을 할 수는 있을 것 같습니다.

작업한 코드를 토대로 SNS 데코레이터를 사용하여 컨트롤러 코드를 작성해봅니다.

# -*- coding: utf-8 -*-

import brandi

class TestController():
    """ 컨트롤러

    """

    @brandi.aws.sns(['testTopic1', 'testTopic2'])
    def test1(self):
        """
        """
        print('hello test function')

    @brandi.aws.sns('testTopic3')
    def test2(self):
        """
        """
        print('hello test2 function')

    @brandi.aws.sns('testTopic4')
    def test4(self):
        """
        """
        print('시작.')

        db = None
        result = {}

        try:

          # 디비 연결

          # 디비 조회

          ...
        except Exception as e:
            raise e
        finally:
            if db is not None:
                db.close()

        return {
             ...
        }

처음 if로 분기 처리 한 것보다 훨씬 깔끔 해졌습니다.

이로써 Lambda 1개로 여러 SNS(그 외 다른 트리거)를 쉽게 관리할 수 있게 되었습니다.

다음 편에서는 1개의 Lambda 핸들러에서 어떻게 유기적으로 컨트롤러의 메소드를 호출할 수 있는지, 라우터와 데코레이터 라우팅으로 핸들러와 컨트롤러 사이를 어떻게 연결을 시켜줄 수 있는지 연구하도록 하겠습니다.

Conclusion

지금까지 파이썬 데코레이터를 활용해 Lambda 트리거에 대한 라우팅 처리를 하는 방법에 대해 알아보았습니다.

현재는 글 작성 때보다 대규모 업데이트가 되면서 더 많은 기능을 할 수 있게 되었습니다.

글로는 전부 소개 못해드린 게 너무 아쉽지만, 타 언어에서 쓰는 방법에도 있듯이 라우터 설정을 파이썬 코드로 관리 할 수 있게 파일관리를 하거나 컨피그 파일로 관리 하는 방법 등 다양한 방법론이 있습니다.

따라서 개개인들이 추구하는 방법대로 라우팅 설계를 해보시는 걸 추천드리며 글을 마칩니다.

참고사이트


장현준 팀장 | 풀필먼트 개발팀
janghj@brandi.co.kr
브랜디, 오직 예쁜 옷만