소개
주문 팀은 JSON 주문을 받고 계산된 합계를 반환해야 합니다. 상태 확인, 쓰기, 읽기 경로를 제공된 Lambda 애플리케이션에 연결하고 유효한 요청과 거부된 요청을 테스트하며 정리 전에 저장된 DynamoDB 레코드를 확인합니다.
HTTP API로 Lambda 함수 공개와 Lambda에서 DynamoDB 읽기 및 쓰기를 먼저 완료하세요. 이 새 환경에는 애플리케이션, 역할, 별도 테이블이 제공됩니다.
인증 시험 관련 주제
| 인증 | 시험 과제 | 실습 |
|---|---|---|
| Solutions Architect – Associate (SAA-C03) | 태스크 2.1 | API 요청 검증, 응답과 저장된 비즈니스 데이터. |
| Developer – Associate (DVA-C02) | 태스크 1.1, 태스크 3.2 | API 요청 검증, 응답과 저장된 비즈니스 데이터. |
| DevOps Engineer – Professional (DOP-C02) | 태스크 3.2 | 기초 실습: API 요청 검증, 응답과 저장된 비즈니스 데이터. |
실습 개요

주문 백엔드 준비
이 단계에서는 제공된 요청 규약을 검사하고 함수에 주문 테이블 접근 권한을 부여하며 백엔드를 배포합니다. 애플리케이션은 정수 센트로 quantity × 250 + 취급 수수료 100센트를 계산합니다. 위쪽 AWS View로 요청과 저장된 데이터를 비교하세요.
작업 공간으로 이동해 애플리케이션을 읽으세요.
cd /home/labex/project
cat app.py
handler는 HTTP 페이로드 형식 2.0을 받습니다. POST /orders는 정확히 두 JSON 필드를 기대합니다. 하나는 문자로 시작하고 문자, 숫자, 하이픈을 사용하는 2–40자의 소문자 id이며, 다른 하나는 1부터 10까지의 정수 quantity입니다. 코드는 PutItem 전에 다른 형태를 거부합니다. GET /orders?id=...는 GetItem으로 저장된 레코드를 읽습니다. 각 응답에는 HTTP 상태와 JSON 본문이 포함됩니다. 제공된 애플리케이션을 다시 작성할 필요는 없습니다.
준비된 테이블 목록을 읽으세요.
aws dynamodb list-tables --query TableNames
labex-a02-orders와 labex-a02-reference를 확인하세요. orders 테이블만 이 API의 비즈니스 작업에 속합니다. ARN을 셸 변수로 읽으세요.
TABLE_ARN=$(aws dynamodb describe-table \
--table-name labex-a02-orders \
--query Table.TableArn \
--output text)
echo "$TABLE_ARN"
실행 역할은 아웃바운드 데이터베이스 접근을 제어합니다. here-document로 정책 파일을 생성하세요. 따옴표로 감싸지 않은 JSON 구분자는 $TABLE_ARN을 방금 읽은 ARN으로 치환합니다. 자격 증명은 포함하지 않습니다.
cat > orders-policy.json <<JSON
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:GetItem"],
"Resource": "$TABLE_ARN"
}]
}
JSON
이 이름이 있는 인라인 정책을 준비된 실행 역할에 연결하세요.
aws iam put-role-policy \
--role-name labex-a02-execution \
--policy-name OrdersData \
--policy-document file://orders-policy.json
app.py를 압축 파일의 최상위에 넣어 제공된 코드를 패키징하세요.
zip orders.zip app.py
준비된 역할 ARN을 읽으세요.
ROLE_ARN=$(aws iam get-role \
--role-name labex-a02-execution \
--query Role.Arn \
--output text)
echo "$ROLE_ARN"
10초 시간 제한으로 함수를 배포하세요. 애플리케이션은 환경에서 TABLE_NAME을 읽어 테이블 선택을 소스 코드와 분리합니다.
aws lambda create-function \
--function-name labex-a02-orders-api \
--runtime python3.12 \
--handler app.handler \
--role "$ROLE_ARN" \
--timeout 10 \
--environment '{"Variables":{"TABLE_NAME":"labex-a02-orders"}}' \
--zip-file fileb://orders.zip \
--query '{Name:FunctionName,Handler:Handler,Table:Environment.Variables.TABLE_NAME}'
함수 이름, app.handler, labex-a02-orders를 확인하세요. AWS View에서 Function 카드를 검사하고 주문 테이블에 여전히 항목이 0개인지 확인하세요. 코드 배포와 데이터 접근 권한 부여는 주문을 생성하지 않습니다.
상태 확인 및 주문 경로 매핑
이 단계에서는 경로 세 개에 통합 하나를 설정하고 각 경로에 함수 호출 권한을 부여합니다.
HTTP API를 생성하고 ID를 저장하세요.
API_ID=$(aws apigatewayv2 create-api \
--name labex-a02 \
--protocol-type HTTP \
--query ApiId \
--output text)
echo "$API_ID"
printf '%s\n' "$API_ID" > api-id.txt
자동 배포를 사용하는 $default 스테이지를 이름 그대로 생성하세요.
aws apigatewayv2 create-stage \
--api-id "$API_ID" \
--stage-name '$default' \
--auto-deploy \
--query '{Stage:StageName,AutoDeploy:AutoDeploy}'
백엔드 ARN을 읽고 페이로드 2.0 통합을 생성하세요. 통합의 POST 메서드는 Lambda를 호출하며 각 클라이언트 경로에는 여전히 자체 HTTP 메서드가 있습니다.
FUNCTION_ARN=$(aws lambda get-function-configuration \
--function-name labex-a02-orders-api \
--query FunctionArn \
--output text)
echo "$FUNCTION_ARN"
INTEGRATION_ID=$(aws apigatewayv2 create-integration \
--api-id "$API_ID" \
--integration-type AWS_PROXY \
--integration-method POST \
--integration-uri "$FUNCTION_ARN" \
--payload-format-version 2.0 \
--query IntegrationId \
--output text)
echo "$INTEGRATION_ID"
공개 상태 확인 엔드포인트를 이 통합에 매핑하세요.
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'GET /health' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
JSON 쓰기 경로를 매핑하세요.
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'POST /orders' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
저장된 주문 읽기 경로를 매핑하세요.
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'GET /orders' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
실행 역할의 데이터베이스 정책은 API Gateway에 함수 호출을 허용하지 않습니다. 계정 ID를 읽은 뒤 정확한 호출 권한 세 개를 추가하세요. 각 정책 문은 API ID, 문자 그대로의 $default, 클라이언트 메서드, 경로를 사용합니다. \$는 치환되는 셸 문자열에서 달러 기호를 보존합니다.
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "$ACCOUNT_ID"
aws lambda add-permission \
--function-name labex-a02-orders-api \
--statement-id ApiHealth \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-account "$ACCOUNT_ID" \
--source-arn "arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/GET/health" \
--query Statement \
--output text
aws lambda add-permission \
--function-name labex-a02-orders-api \
--statement-id ApiWriteOrder \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-account "$ACCOUNT_ID" \
--source-arn "arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/POST/orders" \
--query Statement \
--output text
aws lambda add-permission \
--function-name labex-a02-orders-api \
--statement-id ApiReadOrder \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-account "$ACCOUNT_ID" \
--source-arn "arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/GET/orders" \
--query Statement \
--output text
생성된 ID로 준비된 작업 공간 API 주소를 구성하세요. 이 주소는 작업 공간 안에서 요청을 처리하며 AWS 공개 호스트 이름은 아닙니다.
API_URL="http://127.0.0.1:8081/api/$API_ID"
echo "$API_URL"
상태 확인 경로를 테스트하세요. curl -i는 HTTP 응답 헤더를 포함합니다.
curl -i "$API_URL/health"
HTTP 200과 {"healthy": true}를 확인하세요. AWS View에서 세 경로 키가 모두 NONE이고 스테이지의 AutoDeploy가 활성화되었으며 상태 확인 호출이 200을 반환했는지 확인하세요. 이 요청은 주문 저장이 아니라 상태 확인이므로 주문 테이블은 여전히 비어 있어야 합니다.

유효한 주문 및 거부된 요청 테스트
이 단계에서는 주문 두 개를 생성하고 저장된 결과를 읽으며 실패가 비즈니스 데이터에 영향을 미치기 전에 확인합니다.
HTTP 요청은 메서드, 경로, 헤더, 선택적 본문으로 구성됩니다. -X POST는 쓰기 메서드를 선택하고 -H는 Content-Type: application/json을 제공하며 --data는 JSON 문자열을 보냅니다. 수량 2인 주문을 생성하세요.
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"order-one","quantity":2}'
HTTP 201 Created와 order-one, 수량 2, total_cents: 600 (2 × 250 + 100)을 포함한 본문을 확인하세요. 상태는 클라이언트에 주문이 저장되었음을 알리고 본문은 계산 결과를 보고합니다.
다른 수량으로 두 번째 주문을 생성하세요.
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"order-two","quantity":5}'
HTTP 201과 total_cents: 1350을 확인하세요. 쿼리 파라미터로 API를 통해 두 주문을 읽으세요.
curl -i "$API_URL/orders?id=order-one"
curl -i "$API_URL/orders?id=order-two"
두 응답은 모두 HTTP 200이며 해당 생성 응답과 같은 ID, 수량, 합계여야 합니다. 읽기 핸들러는 새 클라이언트 수량으로 합계를 다시 계산하는 대신 DynamoDB 상태를 조회합니다.
CLI로 첫 저장 항목을 독립적으로 검사하세요.
aws dynamodb get-item \
--table-name labex-a02-orders \
--key '{"id":{"S":"order-one"}}' \
--consistent-read \
--query Item
타입이 지정된 항목에는 quantity: {"N":"2"}와 total_cents: {"N":"600"}이 포함됩니다. AWS View에서 실제 테이블 레코드 두 개를 POST 및 GET 호출 응답과 비교하세요.
문법적으로 유효한 JSON 요청도 비즈니스 규약을 위반할 수 있습니다. 음수 수량을 보내세요.
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"bad-negative","quantity":-1}'
HTTP 400 Bad Request와 Use an id and an integer quantity from 1 to 10을 확인하세요. JSON 문자열로 인코딩한 숫자도 거부됩니다.
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"bad-type","quantity":"2"}'
마지막으로 잘못된 형식의 JSON 본문을 테스트하세요.
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{not-json'
마지막 두 요청도 HTTP 400을 반환합니다. 실제 핸들러 이벤트는 CloudWatch Logs에 나타날 수 있지만 테이블에는 여전히 유효한 두 주문만 있어야 합니다. 요청 검증은 제공된 애플리케이션에서 PutItem 전에 이루어집니다. 일치하는 API 경로만으로는 본문을 검증하지 않습니다.
유효한 읽기 ID가 저장된 주문을 가리키지 않을 수도 있습니다. 생성하지 않은 ID를 쿼리하세요.
curl -i "$API_URL/orders?id=missing-order"
Order not found와 함께 HTTP 404를 확인하세요. 이는 400 잘못된 요청과 다릅니다. ID 형식은 올바르지만 항목이 없습니다. 위쪽 AWS View에서 실제 201, 200, 400, 404 응답을 검사하고 호출의 Show logs를 펼쳐 입력과 결과를 비교하세요. 이 수동 UI 검사는 원격 레코드와 실제 실행에 대한 독립적인 읽기 전용 검사를 보완합니다.

환경에서 이 필드를 비교하려면 DynamoDB tables 카드까지 아래로 스크롤하세요.
이 400 응답은 애플리케이션 검증을 확인합니다. 요청이 Lambda에 도달하고 함수가 쓰기 전에 입력을 거부합니다. 이후 배우는 JWT 거부는 Lambda에 도달하기 전에 API Gateway에서 요청을 중단합니다. 실행 로그와 저장된 항목을 비교하여 어느 경계에서 거부했는지 확인하세요.
API 및 소유한 주문 리소스 제거
이 단계에서는 관련 없는 참조 테이블, 로그, 준비된 실행 역할을 보존하면서 API 리소스를 삭제합니다.
리소스 목록은 api-id.txt의 API ID, labex-a02-orders-api, 그 /aws/lambda/labex-a02-orders-api 로그 그룹, labex-a02-orders, OrdersData 인라인 역할 정책으로 구성됩니다. 경로, 통합, 기본 스테이지를 포함한 API부터 삭제하세요.
aws apigatewayv2 delete-api --api-id "$API_ID"
함수와 그 호출 정책을 제거하세요.
aws lambda delete-function --function-name labex-a02-orders-api
별도의 함수 로그 그룹을 삭제하세요.
aws logs delete-log-group --log-group-name /aws/lambda/labex-a02-orders-api
소유한 주문 테이블과 데이터를 삭제하세요.
aws dynamodb delete-table \
--table-name labex-a02-orders \
--query TableDescription.TableName \
--output text
준비된 역할에 추가한 데이터 정책만 제거하세요.
aws iam delete-role-policy --role-name labex-a02-execution --policy-name OrdersData
목록을 성공적으로 읽어 삭제를 입증하세요. 인증 또는 네트워크 오류는 삭제 증거가 아닙니다.
aws apigatewayv2 get-apis --query 'Items[].Name'
aws lambda list-functions --query 'Functions[].FunctionName'
aws dynamodb list-tables --query TableNames
첫 두 목록은 비어 있어야 하며 테이블 목록에는 labex-a02-reference만 있어야 합니다. 원래 항목이 남아 있는지 확인하세요.
aws dynamodb get-item \
--table-name labex-a02-reference \
--key '{"id":{"S":"reference"}}' \
--query Item
message: {"S":"keep unchanged"}를 확인하세요. 역할은 관련 없는 로깅 정책을 계속 유지해야 합니다.
aws iam list-role-policies --role-name labex-a02-execution --query PolicyNames
FunctionLogs만 있는지 확인하세요. AWS View에서 API, Function, 호출 기록은 사라지고 참조 테이블과 INFO platform reference keep unchanged는 남아 있어야 합니다. 준비된 리소스는 유지하세요. 테스트 자격 증명과 VM 종료는 리소스 확인 후에 처리됩니다.
요약
정확한 데이터베이스 정책과 API 호출 권한으로 HTTP 경로 세 개를 제공된 Lambda 애플리케이션에 연결했습니다. 서로 다른 계산 합계의 주문을 생성하고 조회했으며 실제 DynamoDB 레코드를 확인하고 성공, 잘못된 요청, 없는 주문 응답을 구별했습니다. 이후 참조 리소스를 보존하면서 API와 소유한 데이터, 함수, 로그, 정책을 제거했습니다.
자세한 내용은 AWS 공식 문서를 참고하세요: HTTP API Lambda 이벤트 및 응답 형식; HTTP API 라우트 및 쿼리 매개변수.



