서버리스 함수와 애플리케이션 테스트 방법

서버리스 함수와 애플리케이션 테스트 방법

서버리스 함수를 테스트할 때는 전통적인 테스트 유형과 기법을 사용하지만, 서버리스 애플리케이션을 하나의 전체로 테스트하는 것도 고려해야 해요. 클라우드 기반 테스트는 함수와 서버리스 애플리케이션 모두의 품질에 대한 가장 정확한 측정을 제공해요.

서버리스 애플리케이션 아키텍처에는 API 호출을 통해 중요한 애플리케이션 기능을 제공하는 관리형 서비스가 포함돼요. 따라서 개발 주기에는 함수와 서비스가 상호작용할 때 기능을 검증하는 자동화된 테스트가 포함되어야 해요.

클라우드 기반 테스트를 만들지 않으면 로컬 환경과 배포 환경 사이의 차이로 인해 문제가 발생할 수 있어요. 지속적 통합 프로세스는 코드를 다음 배포 환경(예: QA, Staging, Production)으로 승격하기 전에 클라우드에 프로비저닝된 리소스 모음에 대해 테스트를 실행해야 해요.

이 짧은 안내서를 계속 읽어 서버리스 애플리케이션용 테스트 전략을 배우거나, Serverless Test Samples 저장소를 방문해 선택한 언어와 런타임에 특화된 실용적인 예제로 바로 들어가 보세요.

테스트 유형 간의 관계를 보여주는 그림.

서버리스 테스트에서도 여전히 단위(unit), 통합(integration), 종단 간(end-to-end) 테스트를 작성해요.

  • 단위 테스트 – 격리된 코드 블록에 대해 실행하는 테스트예요. 예를 들어 특정 품목과 목적지에 대한 배송비를 계산하는 비즈니스 로직을 검증하는 것처럼요.
  • 통합 테스트 – 일반적으로 클라우드 환경에서 상호작용하는 둘 이상의 구성 요소나 서비스를 포함하는 테스트예요. 예를 들어 함수가 큐의 이벤트를 처리하는 것을 검증하는 것처럼요.
  • 종단 간 테스트 – 전체 애플리케이션에 걸친 동작을 검증하는 테스트예요. 예를 들어 인프라가 올바르게 설정되었고 고객 주문을 기록하기 위해 이벤트가 서비스 간에 예상대로 흐르는 것을 확인하는 것처럼요.

출처: AWS Lambda 개발자 안내서

본문

목표 비즈니스 결과

서버리스 솔루션을 테스트하는 것은 설정에 더 많은 시간이 걸릴 수 있어요. 서비스 간 이벤트 기반 상호작용을 검증해야 하기 때문이에요. 이 안내서를 읽는 동안 다음 실용적인 비즈니스 이유를 염두에 두세요:

  • 애플리케이션의 품질 높이기
  • 기능 구축 및 버그 수정 시간 단축

애플리케이션의 품질은 많은 시나리오를 테스트하는 데 달려 있어요. 비즈니스 시나리오를 고려하고 클라우드 서비스에 대해 실행하도록 테스트를 자동화하세요. 이렇게 하면 애플리케이션 품질이 높아져요.

버그와 구성 문제는 개발 주기 초기에 잡으면 비용이 덜 들어요. 프로덕션까지 발견되지 않은 문제는 해결하는 데 더 많은 노력과 인력이 필요하죠.

좋은 서버리스 테스트 전략은 소프트웨어 품질을 개선하고 반복을 가속화해요. Lambda 함수와 애플리케이션이 클라우드에서 예상대로 작동하는지 검증해요.

무엇을 테스트할 것인가

관리형 서비스 동작(behaviors), 클라우드 구성, 보안 정책, 코드와의 통합을 테스트하는 전략을 권장해요. 동작 테스트(Behavior testing) 는 블랙박스 테스트라고도 하며, 내부를 알지 못한 채 시스템이 예상대로 작동하는지 검증해요.

  • Lambda 함수 내부의 비즈니스 로직을 확인하려면 단위 테스트를 실행하세요.
  • 통합된 서비스가 실제로 호출되고 입력 매개변수가 올바른지 검증하세요.
  • 워크플로에서 이벤트가 모든 예상 서비스를 종단 간 통과하는지 확인하세요.

전통적인 서버 기반 아키텍처에서 팀은 종종 애플리케이션 서버에서 실행되는 코드만 테스트해요. 다른 구성 요소, 서비스, 의존성은 외부적이고 범위 밖으로 간주하죠.

서버리스 애플리케이션은 작은 작업 단위로 구성돼요. 예를 들어 데이터베이스에서 제품을 검색하거나, 큐의 항목을 처리하거나, 저장소의 이미지 크기를 조정하는 Lambda 함수가 있죠. 각 구성 요소는 자체 환경에서 실행돼요. 팀은 단일 애플리케이션 내에서 이러한 작은 단위를 여러 개 관리해요.

일부 기능은 Amazon S3 같은 관리형 서비스로 완전히 처리되거나 커스텀 코드 없이 구축될 수 있어요. 이러한 관리형 서비스는 테스트할 필요가 없어요. 하지만 코드가 어떻게 통합되는지는 테스트해야 합니다.

서버리스 테스트 방법

로컬에 배포된 애플리케이션을 테스트하는 방법은 이미 알고 있을 거예요. 데스크톱이나 컨테이너 안의 코드에 대해 테스트를 작성하죠. 예를 들어 로컬 웹 서비스를 호출하고 응답을 확인할 수 있어요.

서버리스 솔루션은 함수 코드와 큐, 데이터베이스, 이벤트 버스, 메시징 시스템 같은 클라우드 기반 관리형 서비스를 사용해요. 이러한 구성 요소는 이벤트 기반 아키텍처(event-driven architecture) 로 연결되는데, 여기서 이벤트(events) 라고 하는 메시지가 한 리소스에서 다른 리소스로 흘러요. 일부 상호작용은 동기식이에요. 결과를 즉시 반환하는 웹 서비스처럼요.

다른 상호작용은 큐에 항목을 넣거나 워크플로 단계를 시작하는 것처럼 비동기식이에요. 테스트 전략은 두 유형을 모두 다루고 서비스 간 상호작용을 테스트해야 해요. 비동기 상호작용의 경우 즉시 보이지 않는 다운스트림 구성 요소의 부작용을 감지해야 할 수도 있어요.

클라우드 환경을 로컬에서 완전히 복제할 수는 없어요. 여기에는 큐, 데이터베이스 테이블, 이벤트 버스, 보안 정책이 포함되죠. 로컬과 클라우드 환경의 차이는 문제를 일으켜요. 이러한 차이는 버그를 재현하고 수정하는 시간을 늘려요.

서버리스 애플리케이션에서 구성 요소는 전적으로 클라우드에 존재해요. 기능을 개발하고 버그를 수정하려면 클라우드 코드와 서비스에 대해 테스트해야 해요.

테스트 기법

테스트 전략에는 기법의 조합이 포함될 가능성이 높아요. 콘솔에서 빠른 대화형 테스트로 함수를 디버그하고, 비즈니스 로직을 확인하는 자동화된 단위 테스트를 작성하며, 모의(mock)로 외부 서비스 호출을 검증해요. 서비스를 흉내내는 에뮬레이터에 대해 테스트할 수도 있죠.

  • 클라우드에서 테스트: 실제 서비스, 보안 정책, 구성으로 테스트하기 위해 인프라와 코드를 배포해요. 클라우드 기반 테스트는 코드 품질의 가장 정확한 측정을 제공해요.

    콘솔에서 함수를 디버깅하는 것은 클라우드에서 빠르게 테스트하는 방법이에요. 샘플 테스트 이벤트를 선택하거나 커스텀 이벤트를 만들 수 있어요. 콘솔을 통해 팀과 테스트 이벤트를 공유할 수도 있죠.

    개발·빌드 수명 주기에서 테스트를 자동화하려면 콘솔 밖에서 테스트하세요. 이 안내서의 언어별 테스트 섹션에서 자동화 전략을 확인하세요.

  • 모의(mock)로 테스트: 모의는 코드에서 외부 서비스를 시뮬레이션하는 객체예요. 서비스 호출과 매개변수를 검증하는 미리 정의된 동작을 제공하죠. 페이크(fake) 는 테스트를 단순화하거나 가속화하기 위해 지름길을 쓰는 모의예요. 예를 들어 페이크 데이터 접근 객체는 인메모리 데이터 저장소에서 데이터를 반환할 수 있죠. 모의는 복잡한 의존성을 단순화할 수 있지만, 중첩된 의존성을 대체하기 위해 더 많은 모의가 필요할 수도 있어요.

  • AWS SAM CLI로 로컬 테스트: AWS SAM CLI를 사용해 AWS Lambda와 같은 런타임 환경을 쓰는 Docker 컨테이너에서 Lambda 함수를 로컬로 호출할 수 있어요. 클라우드에 배포하지 않고 함수 로직과 이벤트 처리를 테스트할 수 있죠.

  • 에뮬레이션으로 테스트: VS Code의 LocalStack 통합을 사용해 서비스 통합 테스트를 위해 여러 AWS 서비스를 로컬에서 에뮬레이션해요.

클라우드에서 테스트

클라우드에서 테스트하는 것은 단위 테스트, 통합 테스트, 종단 간 테스트 모두의 모든 단계에 유용해요. 클라우드 기반 코드와 서비스에 대해 실행하는 테스트는 코드 품질에 대한 가장 정확한 측정을 제공해요.

AWS Management Console의 테스트 이벤트로 Lambda 함수를 클라우드에서 실행하는 간단한 방법이 있어요. 테스트 이벤트 는 함수에 대한 JSON 입력이에요. 함수에 입력이 필요 없다면 이벤트는 빈 JSON 문서 ({})일 수 있어요. 콘솔은 많은 서비스 통합에 대한 샘플 이벤트를 제공해요. 팀과 이벤트를 공유해 테스트를 더 쉽게 만들 수도 있죠.

콘솔에서 샘플 함수를 디버그하는 방법을 알아보세요.

참고
콘솔에서 함수를 실행하는 것은 빠른 디버깅 방법이지만, 애플리케이션 품질과 개발 속도를 높이려면 테스트 주기를 자동화하는 것이 필수적이에요.

테스트 자동화 샘플은 Serverless Test Samples 저장소에서 확인할 수 있어요. 다음 명령줄은 자동화된 Python 통합 테스트 예제를 실행해요:

python -m pytest -s tests/integration -v

테스트는 로컬에서 실행되지만 클라우드 기반 리소스와 통신해요. 이러한 리소스는 AWS Serverless Application Model과 AWS SAM 명령줄 도구로 배포되었어요. 테스트 코드는 먼저 배포된 스택의 출력(예: API 엔드포인트, 함수 ARN, 보안 역할)을 검색해요.

그런 다음 API 엔드포인트에 요청을 보내요. 응답에는 Amazon S3 버킷 목록이 포함돼요. 이 테스트는 클라우드 기반 리소스에 대해 실행되어 배포·보안·작동이 확인되는지 검증해요.

========================= test session starts =========================
      platform darwin -- Python 3.10.10, pytest-7.3.1, pluggy-1.0.0
      -- /Users/t/code/aws/serverless-test-samples/python-test-samples/apigw-lambda/venv/bin/python
      cachedir: .pytest_cache
      rootdir: /Users/t/code/aws/serverless-test-samples/python-test-samples/apigw-lambda
      plugins: mock-3.10.0
      collected 1 item                                                                                                        

      tests/integration/test_api_gateway.py::TestApiGateway::test_api_gateway 

      --> Stack outputs:

        HelloWorldApi
        = https://p7teqs3162.execute-api.us-east-2.amazonaws.com/Prod/hello/
        > API Gateway endpoint URL for Prod stage for Hello World function

        PythonTestDemo
        = arn:aws:lambda:us-east-2:123456789012:function:testing-apigw-lambda-PythonTestDemo-iSij8evaTdxl
        > Hello World Lambda Function ARN

        PythonTestDemoIamRole
        = arn:aws:iam::123456789012:role/testing-apigw-lambda-PythonTestDemoRole-IZELQQ9MG4HQ
        > Implicit IAM Role created for Hello World function

      --> Found API endpoint for "testing-apigw-lambda" stack...
      --> https://p7teqs3162.execute-api.us-east-2.amazonaws.com/Prod/hello/
      API Gateway response:
      amplify-dev-123456789-deployment|myapp-prod-p-loggingbucket-123456|s3-java-bucket-123456789
      PASSED

      ========================= 1 passed in 1.53s =========================

클라우드 네이티브 애플리케이션 개발에서 클라우드 테스트는 다음 이점을 제공해요:

  • 모든 사용 가능한 서비스를 테스트할 수 있어요.
  • 항상 가장 최신 서비스 API와 반환 값을 사용해요.
  • 클라우드 테스트 환경은 프로덕션 환경과 매우 유사해요.
  • 테스트는 보안 정책, 서비스 할당량, 구성, 인프라별 매개변수를 다룰 수 있어요.
  • 모든 개발자가 클라우드에서 하나 이상의 테스트 환경을 빠르게 만들 수 있어요.
  • 클라우드 테스트는 코드가 프로덕션에서 올바르게 실행될 것이라는 확신을 높여요.

클라우드에서 테스트하는 데는 단점도 있어요. 클라우드 배포는 보통 로컬 데스크톱 배포보다 오래 걸려요.

AWS Serverless Application Model(AWS SAM) Accelerate, AWS Cloud Development Kit(AWS CDK) watch mode, SST(서드파티) 같은 도구는 이러한 지연 시간을 줄여줘요. 이러한 도구는 인프라와 코드를 모니터링한 다음 클라우드 환경에 업데이트를 자동 배포해요.

참고
Serverless 개발자 안내서에서 AWS Serverless Application Model, CloudFormation, AWS Cloud Development Kit(AWS CDK)에 대해 더 알아보려면 Infrastructure as Code 만들기를 참고하세요.

로컬 테스트와 달리 클라우드 테스트는 비용이 발생할 수 있는 리소스를 사용해요. 격리된 테스트 환경은 엄격한 계정 통제가 있는 조직의 DevOps 팀에 작업을 더할 수 있어요. 그래도 복잡한 로컬 환경을 설정하는 개발자 시간이 IaC 도구로 구축한 일회용 클라우드 환경을 쓰는 것보다 더 비쌀 수 있어요.

이러한 고려 사항에도 불구하고 클라우드 테스트는 여전히 서버리스 솔루션의 품질을 보장하는 최고의 방법이에요.

모의(mock)로 테스트

모의로 테스트하는 것은 클라우드 서비스의 동작을 시뮬레이션하기 위해 코드에서 대체 객체를 만드는 기법이에요.

예를 들어 Amazon S3 서비스의 모의를 사용하는 테스트를 작성할 수 있어요. CreateObject 메서드가 호출될 때마다 모의는 정해진 응답을 반환해요. Amazon S3나 다른 서비스 엔드포인트를 호출하지 않죠.

모의 프레임워크는 종종 모의 객체를 생성해 줘요. 일부 프레임워크는 일반적이고, 다른 프레임워크는 AWS 서비스를 모의하는 Python 라이브러리 Moto처럼 AWS SDK를 대상으로 해요.

모의 객체는 에뮬레이터와 달라요. 개발자는 테스트 코드의 일부로 모의를 만들어요. 에뮬레이터는 흉내내는 시스템과 같은 기능을 노출하는 독립 실행형 애플리케이션이죠.

모의 사용의 장점은 다음과 같아요:

  • 모의는 애플리케이션 통제 밖의 서드파티 서비스(API, SaaS 공급자 같은)를 해당 서비스에 직접 접근할 필요 없이 시뮬레이션할 수 있어요.
  • 모의는 실패 조건을 테스트하는 데 유용해요. 특히 서비스 중단 같은 조건은 시뮬레이션하기 어렵죠.
  • 모의는 일단 구성되면 빠른 로컬 테스트를 제공할 수 있어요.
  • 모의는 거의 모든 종류의 객체에 대체 동작을 제공할 수 있어서, 모의 전략은 에뮬레이터보다 더 다양한 서비스를 커버할 수 있어요.
  • 새 기능이나 동작을 사용할 수 있게 되면 모의 테스트가 더 빨리 반응할 수 있어요. 일반 모의 프레임워크를 사용하면 업데이트된 AWS SDK를 사용할 수 있는 즉시 새 기능을 시뮬레이션할 수 있죠.

모의 테스트에는 다음과 같은 단점이 있어요:

  • 모의는 일반적으로 상당한 설정·구성 노력이 필요해요. 특히 서로 다른 서비스의 반환 값을 파악해 응답을 제대로 모의하는 것이 까다롭죠.
  • 모의는 개발자가 작성·구성·유지 관리해야 하므로 책임이 늘어나요.
  • 서비스의 API와 반환 값을 이해하려면 클라우드에 접근해야 할 수도 있어요.
  • 모의는 유지 관리가 어려울 수 있어요. 모의된 클라우드 API 서명이 바뀌거나 반환 값 스키마가 진화하면 모의를 업데이트해야 해요. 애플리케이션 로직을 확장해 새 API를 호출하게 되면 모의도 업데이트가 필요하죠.
  • 모의를 사용하는 테스트는 데스크톱 환경에서는 통과하지만 클라우드에서는 실패할 수 있어요. 결과가 현재 API와 일치하지 않을 수 있고, 서비스 구성과 할당량은 테스트할 수 없어요.
  • 모의 프레임워크는 AWS Identity and Access Management(IAM) 정책이나 할당량 한도를 테스트하거나 감지하는 데 제한적이에요. 모의는 권한 부여 실패나 할당량 초과를 시뮬레이션하는 데는 더 좋지만, 테스트는 프로덕션 환경에서 어떤 결과가 실제로 발생하는지 판별할 수 없어요.

AWS SAM CLI로 로컬 테스트

AWS SAM CLI를 사용해 AWS Lambda와 같은 런타임 환경을 쓰는 Docker 컨테이너에서 함수를 테스트해 보세요. 클라우드에 배포하지 않고 로컬에서 함수 로직과 이벤트 처리를 테스트할 수 있어요. 함수가 다른 AWS 서비스에 API 호출을 하면 그 호출은 실제 AWS 리소스에 닿아요.

로컬 컨테이너로 테스트하는 장점은 다음과 같아요:

  • 정확한 테스트를 위해 AWS Lambda 런타임 환경을 사용해요.
  • 클라우드 배포 없이 빠른 로컬 개발 반복이 가능해요.
  • 익숙한 로컬 개발 도구로 디버깅을 지원해요.

로컬 컨테이너로 테스트하는 데는 이런 제한이 있어요:

  • 함수의 AWS 서비스 호출이 실제 AWS 리소스와 상호작용해 비용이 발생하고 프로덕션 데이터에 영향을 줄 수 있어요.
  • 로컬에 Docker가 설치·실행 중이어야 해요.

에뮬레이션으로 테스트

에뮬레이터는 유사한 API와 반환 값을 제공해 AWS 서비스를 흉내내는 로컬 실행 애플리케이션이에요. LocalStack은 서비스 통합 테스트를 위한 완전한 로컬 개발 환경을 제공하는 인기 있는 에뮬레이션 도구예요.

LocalStack은 서버리스 애플리케이션을 로컬에서 테스트하는 데 사용할 수 있는 AWS 클라우드 에뮬레이터예요. 실제 AWS 서비스에 연결하지 않고도 DynamoDB, Amazon S3, Amazon SQS 같은 서비스와 통합하는 Lambda 함수를 테스트할 수 있죠. AWS Toolkit for VS Code에서 LocalStack을 사용할 수 있어요.

에뮬레이터로 테스트하는 장점은 다음과 같아요:

  • 에뮬레이터는 빠른 로컬 개발 반복과 테스트를 도와줄 수 있어요.
  • 에뮬레이터는 로컬 환경에서 코드를 개발하는 데 익숙한 개발자에게 친숙한 환경을 제공해요. 예를 들어 n-계층 애플리케이션 개발에 익숙하다면 프로덕션과 유사한 데이터베이스 엔진과 웹 서버를 로컬 머신에서 실행해 빠르고 로컬이며 격리된 테스트 능력을 확보할 수 있죠.
  • 에뮬레이터는 클라우드 인프라(개발자 클라우드 계정 같은)에 변경을 요구하지 않으므로 기존 테스트 패턴으로 구현하기 쉬워요.
  • 에뮬레이터는 실제 AWS 리소스를 사용하지 않으므로 여러 서비스를 시작하거나 일부 리소스를 오래 실행할 때 예상치 못한 요금이 발생하지 않아요.

에뮬레이터로 테스트하는 데는 이런 단점이 있어요:

  • 에뮬레이터는 특히 CI/CD 파이프라인에서 설정·복제가 어려울 수 있어요. 이는 자체 소프트웨어를 관리하는 IT 직원이나 개발자의 워크로드를 늘릴 수 있어요.
  • 에뮬레이션된 기능과 API는 보통 서비스 업데이트에 뒤처져요. 테스트된 코드가 실제 API와 일치하지 않아 오류가 발생하고 새 기능 채택을 방해할 수 있죠.
  • 에뮬레이터는 지원, 업데이트, 버그 수정, 기능 패리티 개선이 필요해요. 이는 서드파티 회사일 수 있는 에뮬레이터 작성자의 책임이에요.
  • 에뮬레이터에 의존하는 테스트는 로컬에서 성공적인 결과를 줄 수 있지만, 프로덕션 보안 정책, 서비스 간 구성, Lambda 할당량 초과 때문에 클라우드에서는 실패할 수 있어요.

모범 사례

다음 섹션은 성공적인 서버리스 애플리케이션 테스트를 위한 권장 사항을 제공해요.

Serverless Test Samples 저장소에서 테스트와 테스트 자동화의 실용적 예제를 찾을 수 있어요.

클라우드에서 테스트 우선시하기

클라우드에서 테스트하는 것은 가장 안정적이고 정확하며 완전한 테스트 커버리지를 제공해요. 클라우드 맥락에서 테스트를 수행하면 비즈니스 로직뿐 아니라 보안 정책, 서비스 구성, 할당량, 가장 최신 API 서명과 반환 값까지 포괄적으로 테스트되죠.

테스트 가능하도록 코드 구조화하기

Lambda 특정 코드를 핵심 비즈니스 로직과 분리해 테스트와 Lambda 함수를 단순화하세요.

Lambda 함수 핸들러 는 이벤트 데이터를 받아 비즈니스 로직 메서드에 중요한 세부 정보만 전달하는 얇은 어댑터여야 해요. 이 전략을 사용하면 Lambda 특정 세부 사항에 신경 쓸 필요 없이 비즈니스 로직 주변에 포괄적인 테스트를 감쌀 수 있어요. AWS Lambda 함수는 테스트 대상 구성 요소를 만들고 초기화하는 데 복잡한 환경이나 많은 의존성을 설정하도록 요구해서는 안 되죠.

일반적으로 들어오는 event 및 context 객체에서 데이터를 추출·검증한 다음, 그 입력을 비즈니스 로직을 수행하는 메서드로 보내는 핸들러를 작성해야 해요.

개발 피드백 루프 가속화

개발 피드백 루프를 가속화하는 도구와 기법이 있어요. 예를 들어 AWS SAM Accelerate와 AWS CDK watch mode는 클라우드 환경을 업데이트하는 데 필요한 시간을 줄여줘요.

GitHub의 Serverless Test Samples 저장소에 있는 샘플은 이러한 기법 중 일부를 탐구해요.

또한 소스 제어 체크인 후에만이 아니라 개발 중 가능한 한 일찍 클라우드 리소스를 만들고 테스트할 것을 권장해요. 이 관행은 솔루션을 개발할 때 더 빠른 탐색과 실험이 가능하게 해줘요. 또한 개발 머신에서 배포를 자동화하면 클라우드 구성 문제를 더 빨리 발견하고 업데이트·코드 검토 과정의 낭비를 줄여줘요.

통합 테스트에 집중하기

Lambda로 애플리케이션을 구축할 때 구성 요소를 함께 테스트하는 것이 모범 사례예요.

둘 이상의 아키텍처 구성 요소에 대해 실행하는 테스트를 통합 테스트 라고 해요. 통합 테스트의 목표는 코드가 구성 요소에 걸쳐 어떻게 실행되는지뿐 아니라 코드를 호스팅하는 환경이 어떻게 동작하는지 이해하는 것이에요. 종단 간 테스트 는 전체 애플리케이션에 걸친 동작을 검증하는 특수한 유형의 통합 테스트예요.

통합 테스트를 구축하려면 애플리케이션을 클라우드 환경에 배포하세요. 로컬 환경이나 CI/CD 파이프라인에서 할 수 있어요. 그런 다음 테스트 대상 시스템(SUT)을 실행하고 예상 동작을 검증하는 테스트를 작성하세요.

예를 들어 테스트 대상 시스템은 API Gateway, Lambda, DynamoDB를 사용하는 애플리케이션일 수 있어요. 테스트는 API Gateway 엔드포인트에 합성 HTTP 호출을 하고 응답에 예상 페이로드가 포함되었는지 검증할 수 있죠. 이 테스트는 AWS Lambda 코드가 올바르고 각 서비스가 요청을 처리하도록 올바르게 구성되었는지(IAM 권한 포함) 검증해요. 또한 다양한 크기의 레코드를 기록하도록 테스트를 설계해 DynamoDB의 최대 레코드 크기 같은 서비스 할당량이 올바르게 설정되었는지 확인할 수도 있어요.

세 개의 서비스로 구성된 테스트 대상 시스템을 보여주는 다이어그램.

격리된 테스트 환경 만들기

클라우드에서 테스트하려면 일반적으로 테스트·데이터·이벤트가 겹치지 않도록 격리된 개발자 환경이 필요해요.

한 가지 접근 방식은 각 개발자에게 전용 AWS 계정을 제공하는 것이에요. 이는 공유 코드 베이스에서 작업하는 여러 개발자가 리소스를 배포하거나 API를 호출하려 할 때 발생할 수 있는 리소스 이름 지정 충돌을 피하게 해줘요.

자동화된 테스트 프로세스는 각 스택에 대해 고유하게 이름이 지정된 리소스를 만들어야 해요. 예를 들어 AWS SAM CLI sam deploy 또는 sam sync 명령이 고유 접두사가 있는 스택을 자동으로 지정하도록 스크립트나 TOML 구성 파일을 설정할 수 있어요.

경우에 따라 개발자가 AWS 계정을 공유하기도 해요. 스택에 운영 비용이 많이 드는 리소스가 있거나 프로비저닝·구성이 복잡하기 때문일 수 있어요. 예를 들어 데이터베이스는 설정과 시딩(seeding)을 쉽게 하기 위해 공유될 수 있어요.

개발자가 계정을 공유한다면 소유권을 식별하고 겹침을 없애는 경계를 설정해야 해요. 한 가지 방법은 스택 이름에 개발자 사용자 ID를 접두사로 붙이는 것이에요. 또 다른 인기 있는 접근 방식은 코드 브랜치를 기준으로 스택을 설정하는 것이에요. 브랜치 경계로 환경이 격리되면서도 개발자는 관계형 데이터베이스 같은 리소스를 계속 공유할 수 있죠. 이 방식은 개발자가 한 번에 둘 이상의 브랜치에서 작업할 때 모범 사례예요.

클라우드에서 테스트하는 것은 단위 테스트, 통합 테스트, 종단 간 테스트를 포함한 모든 테스트 단계에 유용해요. 적절한 격리를 유지하는 것이 필수적이지만, QA 환경이 프로덕션 환경과 최대한 비슷하게 보이길 원할 거예요. 이러한 이유로 팀은 QA 환경에 변경 통제 프로세스를 추가해요.

프로덕션 이전(pre-production) 및 프로덕션 환경에서는 경계가 일반적으로 계정 수준에서 그려져서 워크로드를 소음 이웃(noisy neighbor) 문제로부터 격리하고 민감한 데이터를 보호하기 위해 최소 권한 보안 제어를 구현해요. 워크로드에는 할당량이 있어요. 테스트가 프로덕션용으로 할당된 할당량을 소비하거나(noisy neighbor) 고객 데이터에 접근하는 것을 원하지 않을 거예요. 부하 테스트도 프로덕션 스택과 격리해야 하는 또 다른 활동이에요.

모든 경우에 환경은 불필요한 지출을 피하도록 알림과 제어로 구성되어야 해요. 예를 들어 만들 수 있는 리소스의 유형·계층·크기를 제한하고, 예상 비용이 특정 임계값을 초과하면 이메일 알림을 설정할 수 있어요.

격리된 비즈니스 로직에 모의 사용하기

모의 프레임워크는 빠른 단위 테스트를 작성하는 데 유용한 도구예요. 특히 수학·금융 계산이나 시뮬레이션 같은 복잡한 내부 비즈니스 로직을 다루는 테스트에 유용하죠. 입력이 다른 클라우드 서비스에 대한 호출의 패턴이나 내용을 바꾸지 않는, 테스트 케이스 수가 많거나 입력 변형이 많은 단위 테스트를 찾아보세요.

모의로 단위 테스트가 커버하는 코드는 클라우드에서의 테스트로도 커버되어야 해요. 개발자 랩톱이나 빌드 머신 환경이 클라우드의 프로덕션 환경과 다르게 구성될 수 있기 때문이에요. 예를 들어 Lambda 함수가 특정 입력 매개변수로 실행될 때 할당된 메모리나 시간보다 더 많이 사용할 수 있어요. 또는 코드가 같은 방식으로(혹은 아예) 구성되지 않은 환경 변수를 포함하고, 그 차이가 코드를 다르게 동작하게 하거나 실패하게 할 수 있죠.

통합 테스트에서는 모의의 이점이 덜해요. 필요한 모의를 구현하는 노력이 연결 지점 수에 따라 증가하기 때문이에요. 종단 간 테스트는 모의를 사용해서는 안 되는데, 이런 테스트는 일반적으로 모의 프레임워크로 쉽게 시뮬레이션할 수 없는 상태와 복잡한 로직을 다루기 때문이에요.

마지막으로 모의 클라우드 서비스를 사용해 서비스 호출의 올바른 구현을 검증하는 것은 피하세요. 대신 클라우드에서 서비스 호출을 만들어 동작·구성·기능 구현을 검증하세요.

에뮬레이터는 가급적 아껴 쓰기

에뮬레이터는 일부 사용 사례에 편리할 수 있어요. 예를 들어 인터넷 접근이 제한적이거나 불안정하거나 느린 개발 팀에게요. 하지만 대부분의 상황에서는 에뮬레이터를 아껴 쓰는 것을 선택하세요.

에뮬레이터를 피하면 최신 서비스 기능과 최신 API로 구축·혁신할 수 있어요. 벤더 릴리스를 기다려 기능 패리티를 달성할 필요가 없죠. 여러 개발 시스템과 빌드 머신에서 구매·구성에 필요한 초기·지속 비용을 줄일 수 있어요. 또한 많은 클라우드 서비스에는 에뮬레이터가 전혀 없다는 문제를 피할 수 있어요. 에뮬레이션에 의존하는 테스트 전략은 그러한 서비스를 사용할 수 없게 만들거나(잠재적으로 더 비싼 해결책으로 이어짐) 제대로 테스트되지 않은 코드와 구성을 만들어낼 수 있어요.

테스트에 에뮬레이션을 사용할 때도 에뮬레이션된 환경에서만 시뮬레이션하거나 모의할 수 있는 클라우드 서비스와의 상호작용을 구성 검증과 테스트를 위해 여전히 클라우드에서 테스트해야 해요.

로컬 테스트의 어려움

에뮬레이터와 모의 호출로 로컬 데스크톱에서 테스트하면 코드가 CI/CD 파이프라인에서 환경을 거쳐 이동하면서 테스트 불일치를 경험할 수 있어요. 데스크톱에서 애플리케이션 비즈니스 로직을 검증하는 단위 테스트는 클라우드 서비스의 중요한 측면을 정확히 테스트하지 못할 수 있어요.

다음 예제는 모의·에뮬레이터로 로컬 테스트할 때 주의해야 할 사례를 제공해요:

예제: Lambda 함수가 S3 버킷을 만드는 경우

Lambda 함수의 로직이 S3 버킷 생성에 의존한다면, 완전한 테스트는 Amazon S3가 호출되었고 버킷이 성공적으로 생성되었는지 확인해야 해요.

  • 모의 테스트 설정에서는 성공 응답을 모의하고 잠재적으로 실패 응답을 처리하는 테스트 케이스를 추가할 수 있어요.
  • 에뮬레이션 테스트 시나리오에서는 CreateBucket API가 호출될 수 있지만, 로컬 호출을 하는 자격 증명이 Lambda 서비스에서 오는 것이 아니라는 점을 알아야 해요. 호출 자격 증명은 클라우드에서처럼 보안 역할을 수임하지 않으므로, 클라우드에서 실행할 때와 다른 더 허용적인 역할이나 사용자 ID를 사용하는 자리 표시자 인증이 대신 사용되죠.

모의 및 에뮬레이션 설정은 Lambda 함수가 Amazon S3를 호출하면 무엇을 하는지 테스트하지만, 그 설정은 구성된 대로의 Lambda 함수가 Amazon S3 버킷을 성공적으로 생성할 수 있는지 검증하지는 않아요. 함수에 할당된 역할에 함수가 s3:CreateBucket 작업을 수행할 수 있게 하는 보안 정책이 연결되어 있는지 확인해야 해요. 그렇지 않으면 함수는 클라우드 환경에 배포될 때 실패할 가능성이 있어요.

예제: Lambda 함수가 Amazon SQS 큐의 메시지를 처리하는 경우

Amazon SQS 큐가 Lambda 함수의 소스라면, 완전한 테스트는 큐에 메시지를 넣으면 Lambda 함수가 성공적으로 호출되는지 검증해야 해요.

에뮬레이션 테스트와 모의 테스트는 일반적으로 Lambda 함수 코드를 직접 실행하고, 함수 핸들러의 입력으로 JSON 이벤트 페이로드(또는 역직렬화된 객체)를 전달해 Amazon SQS 통합을 시뮬레이션하도록 설정돼요.

Amazon SQS 통합을 시뮬레이션하는 로컬 테스트는 Lambda 함수가 주어진 페이로드로 Amazon SQS에 의해 호출될 때 무엇을 하는지 테스트하지만, 그 테스트는 Amazon SQS가 클라우드 환경에 배포되었을 때 Lambda 함수를 성공적으로 호출하는지 검증하지는 않아요.

Amazon SQS와 Lambda에서 마주칠 수 있는 구성 문제의 예는 다음과 같아요:

  • Amazon SQS 표시 제한 시간(visibility timeout)이 너무 낮아 의도한 하나만 호출되어야 하는데 여러 번 호출되는 경우.
  • Lambda 함수의 실행 역할이 큐에서 메시지 읽기를 허용하지 않는 경우(sqs:ReceiveMessage, sqs:DeleteMessage, sqs:GetQueueAttributes 통해).
  • Lambda 함수에 전달되는 샘플 이벤트가 Amazon SQS 메시지 크기 할당량을 초과하는 경우. 따라서 그 크기의 메시지는 Amazon SQS가 절대 보낼 수 없으므로 테스트가 유효하지 않아요.

이 예제들이 보여주듯, 비즈니스 로직은 다루지만 클라우드 서비스 간 구성을 다루지 않는 테스트는 신뢰할 수 없는 결과를 낼 가능성이 높아요.

FAQ

계산을 수행하고 다른 서비스를 호출하지 않고 결과를 반환하는 Lambda 함수가 있습니다. 정말 클라우드에서 테스트해야 하나요?

네. Lambda 함수에는 테스트 결과를 바꿀 수 있는 구성 매개변수가 있어요. 모든 Lambda 함수 코드는 타임아웃과 메모리 설정에 의존하며, 이러한 설정이 제대로 설정되지 않으면 함수가 실패할 수 있어요.

Lambda 정책은 표준 출력 로깅을 Amazon CloudWatch로도 활성화해요. 코드가 CloudWatch를 직접 호출하지 않아도 로깅을 가능하게 하는 권한이 필요해요. 이 필수 권한은 정확하게 모의하거나 에뮬레이션할 수 없어요.

클라우드에서 테스트하면 단위 테스트에 어떻게 도움이 되나요? 클라우드에 있고 다른 리소스에 연결되어 있으면 통합 테스트 아닌가요?

단위 테스트 를 격리된 상태에서 아키텍처 구성 요소에 대해 동작하는 테스트로 정의하지만, 이는 다른 서비스를 호출하거나 일부 네트워크 통신을 사용하는 구성 요소를 포함하는 테스트를 막지 않아요.

많은 서버리스 애플리케이션에는 클라우드에서도 격리된 상태로 테스트할 수 있는 아키텍처 구성 요소가 있어요. 예를 들어 입력을 받아 데이터를 처리하고 Amazon SQS 큐에 메시지를 보내는 Lambda 함수가 있죠. 이 함수의 단위 테스트는 입력 값이 큐에 있는 메시지의 특정 값으로 이어지는지 테스트할 가능성이 높아요.

Arrange, Act, Assert 패턴으로 작성된 테스트를 생각해 보세요:

  • Arrange: 리소스 할당(메시지를 받을 큐, 테스트 대상 함수).
  • Act: 테스트 대상 함수 호출.
  • Assert: 함수가 보낸 메시지를 검색하고 출력 검증.

모의 테스트 접근 방식은 인프로세스 모의 객체로 큐를 모의하고, Lambda 함수 코드가 포함된 클래스나 모듈의 인프로세스 인스턴스를 만드는 방식이에요. Assert 단계에서 큐에 있는 메시지가 모의 객체에서 검색될 거예요.

클라우드 기반 접근 방식에서 테스트는 테스트 목적으로 Amazon SQS 큐를 만들고, 격리된 Amazon SQS 큐를 출력 대상으로 구성된 환경 변수로 Lambda 함수를 배포해요. Lambda 함수를 실행한 후 테스트는 Amazon SQS 큐에서 메시지를 검색해요.

클라우드 기반 테스트는 같은 코드를 실행하고 같은 동작을 주장하며 애플리케이션의 기능적 정확성을 검증해요. 하지만 IAM 역할, IAM 정책, 함수의 타임아웃·메모리 설정 같은 Lambda 함수의 설정을 검증할 수 있다는 추가 이점이 있어요.

다음 단계 및 리소스

다음 리소스를 사용해 더 배우고 테스트의 실용적인 예제를 탐구하세요.

샘플 구현

GitHub의 Serverless Test Samples 저장소 에는 이 안내서에 설명된 패턴과 모범 사례를 따르는 테스트의 구체적인 예제가 있어요. 저장소에는 이전 섹션에서 설명한 모의, 에뮬레이션, 클라우드 테스트 프로세스의 샘플 코드와 안내형 안내가 포함돼 있죠. 이 저장소를 사용해 AWS의 최신 서버리스 테스트 지침을 파악해 보세요.

더 읽어보기

최신 AWS 서버리스 기술 블로그, 비디오, 교육에 접근하려면 Serverless Land를 방문하세요.

다음 AWS 블로그 게시물도 읽어볼 것을 권장해요:

도구

더 알아보기 (Learn more)

  • 클라우드·모의·SAM CLI 로컬·에뮬레이션 테스트 기법과 격리, 통합 테스트 우선, 모범 사례, FAQ를 익혀 보세요.