쿠키 기본 설정 선택

당사는 사이트와 서비스를 제공하는 데 필요한 필수 쿠키 및 유사한 도구를 사용합니다. 고객이 사이트를 어떻게 사용하는지 파악하고 개선할 수 있도록 성능 쿠키를 사용해 익명의 통계를 수집합니다. 필수 쿠키는 비활성화할 수 없지만 '사용자 지정' 또는 ‘거부’를 클릭하여 성능 쿠키를 거부할 수 있습니다.

사용자가 동의하는 경우 AWS와 승인된 제3자도 쿠키를 사용하여 유용한 사이트 기능을 제공하고, 사용자의 기본 설정을 기억하고, 관련 광고를 비롯한 관련 콘텐츠를 표시합니다. 필수가 아닌 모든 쿠키를 수락하거나 거부하려면 ‘수락’ 또는 ‘거부’를 클릭하세요. 더 자세한 내용을 선택하려면 ‘사용자 정의’를 클릭하세요.

자습서: Lambda 함수 URL을 사용하여 웹후크 엔드포인트 생성

포커스 모드
자습서: Lambda 함수 URL을 사용하여 웹후크 엔드포인트 생성 - AWS Lambda

이 자습서에서는 Lambda 함수 URL을 생성하여 웹후크 엔드포인트를 구현합니다. 웹후크는 HTTP를 사용하여 애플리케이션 간에 데이터를 자동으로 전송하는 경량형 이벤트 기반 통신입니다. 웹후크를 사용하면 다른 시스템에서 발생하는 이벤트(예: 새 고객의 웹 사이트 가입, 결제 처리, 파일 업로드)에 대한 즉각적인 업데이트를 받을 수 있습니다.

Lambda를 활용하면 Lambda 함수 URL 또는 API Gateway를 사용하여 웹후크를 구현할 수 있습니다. 함수 URL은 고급 권한 부여 또는 요청 검증 같은 기능이 필요하지 않은 간단한 웹후크에 적합합니다.

작은 정보

특정한 사용 사례에 가장 적합한 방법을 잘 모르는 경우 HTTP 요청을 사용하여 Lambda 함수를 간접 호출하는 메서드 선택 섹션을 참조하세요.

사전 조건

이 자습서를 완료하려면 로컬 시스템에 Python(버전 3.8 이상) 또는 Node.js(버전 18 이상)가 설치되어 있어야 합니다.

HTTP 요청을 사용하여 엔드포인트를 테스트할 수 있도록 자습서에서는 curl을 사용합니다. 이는 다양한 네트워크 프로토콜을 사용하여 데이터를 전송하는 데 사용할 수 있는 명령줄 도구입니다. 아직 도구를 설치하지 않은 경우, 도구를 설치하는 방법을 알아보려면 curl 설명서를 참조하세요.

Lambda 함수 생성

HTTP 요청이 웹후크 엔드포인트로 전송될 때 실행되는 Lambda 함수를 우선 생성합니다. 이 예제에서 전송 애플리케이션은 결제가 제출될 때마다 업데이트를 전송하며 결제 성공 여부를 HTTP 요청 본문에 표시합니다. Lambda 함수는 요청을 구문 분석하고 결제 상태에 따라 조치를 취합니다. 이 예제에서는 코드가 결제의 주문 ID만 인쇄하지만, 실제 애플리케이션에서는 주문을 데이터베이스에 추가하거나 알림을 전송할 수 있습니다.

또한 이 함수는 웹후크, 해시 기반 메시지 인증(HMAC)에 사용되는 가장 일반적인 인증 방법을 구현합니다. 이 방법을 사용하면 발신 및 수신 애플리케이션 두 가지 모두가 보안 키를 공유합니다. 전송 애플리케이션은 해싱 알고리즘을 사용하여 메시지 콘텐츠와 함께 이 키를 사용하여 고유한 서명을 생성하며, 웹후크 요청 내에 서명을 HTTP 헤더로 포함합니다. 그런 다음 수신 애플리케이션이 이 단계를 반복하여 보안 키를 사용해 서명을 생성하며, 결과 값을 요청 헤더에 전송된 서명과 비교합니다. 결과가 일치하면 요청이 정상적인 것으로 간주됩니다.

Python 또는 Node.js 런타임과 함께 Lambda 콘솔을 사용하여 함수를 생성합니다.

Python
Lambda 함수 생성
  1. Lambda 콘솔의 함수 페이지를 엽니다.

  2. 다음을 수행하여 기본 'Hello world' 함수를 생성합니다.

    1. 함수 생성을 선택합니다.

    2. 새로 작성을 선택합니다.

    3. [함수 이름(Function name)]에 myLambdaWebhook을 입력합니다.

    4. 런타임에서 Python 3.13을 선택합니다.

    5. 함수 생성을 선택합니다.

  3. 코드 소스 창에서 다음을 복사하고 붙여 넣어 기존 코드를 바꿉니다.

    import json import hmac import hashlib import os def lambda_handler(event, context): # Get the webhook secret from environment variables webhook_secret = os.environ['WEBHOOK_SECRET'] # Verify the webhook signature if not verify_signature(event, webhook_secret): return { 'statusCode': 401, 'body': json.dumps({'error': 'Invalid signature'}) } try: # Parse the webhook payload payload = json.loads(event['body']) # Handle different event types event_type = payload.get('type') if event_type == 'payment.success': # Handle successful payment order_id = payload.get('orderId') print(f"Processing successful payment for order {order_id}") # Add your business logic here # For example, update database, send notifications, etc. elif event_type == 'payment.failed': # Handle failed payment order_id = payload.get('orderId') print(f"Processing failed payment for order {order_id}") # Add your business logic here else: print(f"Received unhandled event type: {event_type}") # Return success response return { 'statusCode': 200, 'body': json.dumps({'received': True}) } except json.JSONDecodeError: return { 'statusCode': 400, 'body': json.dumps({'error': 'Invalid JSON payload'}) } except Exception as e: print(f"Error processing webhook: {e}") return { 'statusCode': 500, 'body': json.dumps({'error': 'Internal server error'}) } def verify_signature(event, webhook_secret): """ Verify the webhook signature using HMAC """ try: # Get the signature from headers signature = event['headers'].get('x-webhook-signature') if not signature: print("Error: Missing webhook signature in headers") return False # Get the raw body (return an empty string if the body key doesn't exist) body = event.get('body', '') # Create HMAC using the secret key expected_signature = hmac.new( webhook_secret.encode('utf-8'), body.encode('utf-8'), hashlib.sha256 ).hexdigest() # Compare the expected signature with the received signature to authenticate the message is_valid = hmac.compare_digest(signature, expected_signature) if not is_valid: print(f"Error: Invalid signature. Received: {signature}, Expected: {expected_signature}") return False return True except Exception as e: print(f"Error verifying signature: {e}") return False
  4. 배포 섹션에서 배포를 선택하여 함수의 코드를 업데이트하세요.

Node.js
Lambda 함수 생성
  1. Lambda 콘솔의 함수 페이지를 엽니다.

  2. 다음을 수행하여 기본 'Hello world' 함수를 생성합니다.

    1. 함수 생성을 선택합니다.

    2. 새로 작성을 선택합니다.

    3. [함수 이름(Function name)]에 myLambdaWebhook을 입력합니다.

    4. 런타임에서 nodejs22.x를 선택합니다.

    5. 함수 생성을 선택합니다.

  3. 코드 소스 창에서 다음을 복사하고 붙여 넣어 기존 코드를 바꿉니다.

    import crypto from 'crypto'; export const handler = async (event, context) => { // Get the webhook secret from environment variables const webhookSecret = process.env.WEBHOOK_SECRET; // Verify the webhook signature if (!verifySignature(event, webhookSecret)) { return { statusCode: 401, body: JSON.stringify({ error: 'Invalid signature' }) }; } try { // Parse the webhook payload const payload = JSON.parse(event.body); // Handle different event types const eventType = payload.type; switch (eventType) { case 'payment.success': { // Handle successful payment const orderId = payload.orderId; console.log(`Processing successful payment for order ${orderId}`); // Add your business logic here // For example, update database, send notifications, etc. break; } case 'payment.failed': { // Handle failed payment const orderId = payload.orderId; console.log(`Processing failed payment for order ${orderId}`); // Add your business logic here break; } default: console.log(`Received unhandled event type: ${eventType}`); } // Return success response return { statusCode: 200, body: JSON.stringify({ received: true }) }; } catch (error) { if (error instanceof SyntaxError) { // Handle JSON parsing errors return { statusCode: 400, body: JSON.stringify({ error: 'Invalid JSON payload' }) }; } // Handle all other errors console.error('Error processing webhook:', error); return { statusCode: 500, body: JSON.stringify({ error: 'Internal server error' }) }; } }; // Verify the webhook signature using HMAC const verifySignature = (event, webhookSecret) => { try { // Get the signature from headers const signature = event.headers['x-webhook-signature']; if (!signature) { console.log('No signature found in headers:', event.headers); return false; } // Get the raw body (return an empty string if the body key doesn't exist) const body = event.body || ''; // Create HMAC using the secret key const hmac = crypto.createHmac('sha256', webhookSecret); const expectedSignature = hmac.update(body).digest('hex'); // Compare expected and received signatures const isValid = signature === expectedSignature; if (!isValid) { console.log(`Invalid signature. Received: ${signature}, Expected: ${expectedSignature}`); return false; } return true; } catch (error) { console.error('Error during signature verification:', error); return false; } };
  4. 배포 섹션에서 배포를 선택하여 함수의 코드를 업데이트하세요.

Lambda 함수 생성
  1. Lambda 콘솔의 함수 페이지를 엽니다.

  2. 다음을 수행하여 기본 'Hello world' 함수를 생성합니다.

    1. 함수 생성을 선택합니다.

    2. 새로 작성을 선택합니다.

    3. [함수 이름(Function name)]에 myLambdaWebhook을 입력합니다.

    4. 런타임에서 Python 3.13을 선택합니다.

    5. 함수 생성을 선택합니다.

  3. 코드 소스 창에서 다음을 복사하고 붙여 넣어 기존 코드를 바꿉니다.

    import json import hmac import hashlib import os def lambda_handler(event, context): # Get the webhook secret from environment variables webhook_secret = os.environ['WEBHOOK_SECRET'] # Verify the webhook signature if not verify_signature(event, webhook_secret): return { 'statusCode': 401, 'body': json.dumps({'error': 'Invalid signature'}) } try: # Parse the webhook payload payload = json.loads(event['body']) # Handle different event types event_type = payload.get('type') if event_type == 'payment.success': # Handle successful payment order_id = payload.get('orderId') print(f"Processing successful payment for order {order_id}") # Add your business logic here # For example, update database, send notifications, etc. elif event_type == 'payment.failed': # Handle failed payment order_id = payload.get('orderId') print(f"Processing failed payment for order {order_id}") # Add your business logic here else: print(f"Received unhandled event type: {event_type}") # Return success response return { 'statusCode': 200, 'body': json.dumps({'received': True}) } except json.JSONDecodeError: return { 'statusCode': 400, 'body': json.dumps({'error': 'Invalid JSON payload'}) } except Exception as e: print(f"Error processing webhook: {e}") return { 'statusCode': 500, 'body': json.dumps({'error': 'Internal server error'}) } def verify_signature(event, webhook_secret): """ Verify the webhook signature using HMAC """ try: # Get the signature from headers signature = event['headers'].get('x-webhook-signature') if not signature: print("Error: Missing webhook signature in headers") return False # Get the raw body (return an empty string if the body key doesn't exist) body = event.get('body', '') # Create HMAC using the secret key expected_signature = hmac.new( webhook_secret.encode('utf-8'), body.encode('utf-8'), hashlib.sha256 ).hexdigest() # Compare the expected signature with the received signature to authenticate the message is_valid = hmac.compare_digest(signature, expected_signature) if not is_valid: print(f"Error: Invalid signature. Received: {signature}, Expected: {expected_signature}") return False return True except Exception as e: print(f"Error verifying signature: {e}") return False
  4. 배포 섹션에서 배포를 선택하여 함수의 코드를 업데이트하세요.

보안 암호 키 생성

Lambda 함수는 웹후크 요청을 인증할 수 있도록 호출 애플리케이션과 공유하는 보안 키를 사용합니다. 이 예제에서는 키가 환경 변수에 저장됩니다. 프로덕션 애플리케이션에서는 보다 안전한 옵션으로 AWS Secrets Manager를 사용하는 것이 좋습니다. Secrets Manager를 사용하여 보안 암호 키를 저장하는 방법에 대한 자세한 내용은 AWS Secrets Manager 사용 설명서의 Create an AWS Secrets Manager secretGet secrets from AWS Secrets Manager 섹션을 참조하세요.

웹후크 보안 암호 키 생성 및 저장
  1. 암호화 보안 난수 생성기를 사용하여 긴 무작위 문자열을 생성합니다. Python 또는 Node.js에서 다음 코드 조각을 사용하여 32자 보안 암호를 생성 및 인쇄하거나, 원하는 방법을 사용할 수 있습니다.

    Python
    예 보안 암호를 생성하는 코드
    import secrets webhook_secret = secrets.token_urlsafe(32) print(webhook_secret)
    Node.js
    예 보안 암호를 생성하는 코드(ES 모듈 형식)
    import crypto from 'crypto'; let webhookSecret = crypto.randomBytes(32).toString('base64'); console.log(webhookSecret)
    예 보안 암호를 생성하는 코드
    import secrets webhook_secret = secrets.token_urlsafe(32) print(webhook_secret)
  2. 다음을 수행하여 생성된 문자열을 함수의 환경 변수로 저장합니다.

    1. 함수에 대한 구성 페이지에서 환경 변수를 선택합니다.

    2. 편집을 선택합니다.

    3. Add environment variable(환경 변수 추가)을 선택합니다.

    4. 에서 WEBHOOK_SECRET을 입력한 다음, 에서 이전 단계에서 생성한 보안 암호를 입력합니다.

    5. Save(저장)를 선택합니다.

자습서의 뒷부분에서 이 보안 암호를 다시 사용하여 함수를 테스트해야 하므로 이 보안 암호를 지금 메모해 두세요.

함수 URL 엔드포인트 생성

Lambda 함수 URL을 사용하여 웹후크의 엔드포인트를 생성합니다. 인증 유형 NONE을 사용하여 퍼블릭 액세스 권한이 있는 엔드포인트를 생성하면 URL이 있는 누구나 함수를 간접적으로 호출할 수 있습니다. 함수 URL에 대한 액세스 권한 제어를 자세히 알아보려면 Lambda 함수 URL에 대한 액세스 제어 섹션을 참조하세요. 웹후크에 대한 고급 인증 옵션이 필요한 경우 API Gateway를 사용하는 것이 좋습니다.

함수 URL 엔드포인트 생성
  1. 함수의 구성 탭에서 함수 URL을 선택합니다.

  2. 함수 URL 생성(Create function URL)을 선택합니다.

  3. 인증 유형에서 없음을 선택합니다.

  4. Save(저장)를 선택합니다.

방금 생성한 함수 URL의 엔드포인트가 함수 URL 창에 표시됩니다. 자습서의 뒷부분에서 사용할 엔드포인트를 복사합니다.

콘솔에서 함수 테스트

HTTP 요청을 사용하여 URL 엔드포인트를 사용하여 함수를 간접적으로 호출하려면 우선 콘솔에서 이를 테스트하여 코드가 예상대로 작동하는지 확인합니다.

콘솔에서 함수를 확인하려면 먼저 다음과 같은 테스트 JSON 페이로드를 통해 자습서 앞부분에서 생성한 보안 암호를 사용하여 웹후크 서명을 계산합니다.

{ "type": "payment.success", "orderId": "1234", "amount": "99.99" }

다음과 같은 Python 또는 Node.js 코드 예제 중 하나를 사용해 고유한 보안 암호를 이용하여 웹후크 서명을 계산합니다.

Python
웹후크 서명 계산
  1. 다음 코드를 calculate_signature.py라는 이름의 파일에 저장합니다. 코드의 웹후크 보안 암호를 원하는 고유한 값으로 바꿉니다.

    import secrets import hmac import json import hashlib webhook_secret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M" body = json.dumps({"type": "payment.success", "orderId": "1234", "amount": "99.99"}) signature = hmac.new( webhook_secret.encode('utf-8'), body.encode('utf-8'), hashlib.sha256 ).hexdigest() print(signature)
  2. 코드를 저장한 디렉터리에서 다음 명령을 실행하여 서명을 계산합니다. 코드가 출력하는 서명을 복사합니다.

    python calculate_signature.py
Node.js
웹후크 서명 계산
  1. 다음 코드를 calculate_signature.mjs라는 이름의 파일에 저장합니다. 코드의 웹후크 보안 암호를 원하는 고유한 값으로 바꿉니다.

    import crypto from 'crypto'; const webhookSecret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M" const body = "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}"; let hmac = crypto.createHmac('sha256', webhookSecret); let signature = hmac.update(body).digest('hex'); console.log(signature);
  2. 코드를 저장한 디렉터리에서 다음 명령을 실행하여 서명을 계산합니다. 코드가 출력하는 서명을 복사합니다.

    node calculate_signature.mjs
웹후크 서명 계산
  1. 다음 코드를 calculate_signature.py라는 이름의 파일에 저장합니다. 코드의 웹후크 보안 암호를 원하는 고유한 값으로 바꿉니다.

    import secrets import hmac import json import hashlib webhook_secret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M" body = json.dumps({"type": "payment.success", "orderId": "1234", "amount": "99.99"}) signature = hmac.new( webhook_secret.encode('utf-8'), body.encode('utf-8'), hashlib.sha256 ).hexdigest() print(signature)
  2. 코드를 저장한 디렉터리에서 다음 명령을 실행하여 서명을 계산합니다. 코드가 출력하는 서명을 복사합니다.

    python calculate_signature.py

이제 콘솔에서 테스트 HTTP 요청을 사용하여 함수 코드를 테스트할 수 있습니다.

콘솔에서 함수 테스트
  1. 함수의 코드 탭을 선택합니다.

  2. 테스트 이벤트 섹션에서 새로운 테스트 이벤트 생성을 선택합니다.

  3. Event Name(이벤트 이름)myEvent를 입력합니다.

  4. 다음을 복사하여 이벤트 JSON 창에 붙여 넣어 기존 JSON을 바꿉니다. 웹후크 서명을 이전 단계에서 계산한 값으로 바꿉니다.

    { "headers": { "Content-Type": "application/json", "x-webhook-signature": "2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a" }, "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}" }
  5. Save(저장)를 선택합니다.

  6. 간접 호출를 선택합니다.

    다음과 유사한 출력 화면이 표시되어야 합니다.

    Python
    Status: Succeeded Test Event Name: myEvent Response: { "statusCode": 200, "body": "{\"received\": true}" } Function Logs: START RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Version: $LATEST Processing successful payment for order 1234 END RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 REPORT RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Duration: 1.55 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 36 MB Init Duration: 136.32 ms
    Node.js
    Status: Succeeded Test Event Name: myEvent Response: { "statusCode": 200, "body": "{\"received\":true}" } Function Logs: START RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 Version: $LATEST 2025-01-10T18:05:42.062Z e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 INFO Processing successful payment for order 1234 END RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 REPORT RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 Duration: 60.10 ms Billed Duration: 61 ms Memory Size: 128 MB Max Memory Used: 72 MB Init Duration: 174.46 ms Request ID: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
    Status: Succeeded Test Event Name: myEvent Response: { "statusCode": 200, "body": "{\"received\": true}" } Function Logs: START RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Version: $LATEST Processing successful payment for order 1234 END RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 REPORT RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Duration: 1.55 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 36 MB Init Duration: 136.32 ms

HTTP 요청을 사용하여 함수 테스트

curl 명령줄 도구를 사용하여 웹후크 엔드포인트를 테스트합니다.

HTTP 요청을 사용하여 함수 테스트
  1. 터미널 또는 쉘 프로그램에서 다음 curl 명령을 실행합니다. URL을 고유한 함수 URL 엔드포인트의 값으로 바꾸고, 웹후크 서명을 고유한 보안 키를 사용하여 계산한 서명으로 바꿉니다.

    curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \ -H "Content-Type: application/json" \ -H "x-webhook-signature: d5f52b76ffba65ff60ea73da67bdf1fc5825d4db56b5d3ffa0b64b7cb85ef48b" \ -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'

    다음 결과가 표시됩니다.

    {"received": true}
  2. 함수의 CloudWatch 로그를 검사해 다음을 수행하여 페이로드를 올바르게 구문 분석했는지 확인합니다.

    1. Amazon CloudWatch 콘솔에서 로그 그룹 페이지를 엽니다.

    2. 함수의 로그 그룹(/aws/lambda/myLambdaWebhook)을 선택합니다.

    3. 최신 로그 스트림을 선택합니다.

      함수의 로그에서 다음과 유사한 출력 화면이 표시되어야 합니다.

      Python
      Processing successful payment for order 1234
      Node.js
      2025-01-10T18:05:42.062Z e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 INFO Processing successful payment for order 1234
      Processing successful payment for order 1234
  3. 다음 curl 명령을 실행하여 코드가 잘못된 서명을 감지하는지 확인합니다. URL을 고유한 함수 URL 엔드포인트로 바꿉니다.

    curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \ -H "Content-Type: application/json" \ -H "x-webhook-signature: abcdefg" \ -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'

    다음 결과가 표시됩니다.

    {"error": "Invalid signature"}

리소스 정리

이 자습서 용도로 생성한 리소스를 보관하고 싶지 않다면 지금 삭제할 수 있습니다. 더 이상 사용하지 않는 AWS 리소스를 삭제하면 AWS 계정에 불필요한 요금이 발생하는 것을 방지할 수 있습니다.

Lambda 함수를 삭제하려면
  1. Lambda 콘솔의 함수 페이지를 엽니다.

  2. 생성한 함수를 선택합니다.

  3. 작업, 삭제를 선택합니다.

  4. 텍스트 입력 필드에 confirm를 입력하고 Delete(삭제)를 선택합니다.

콘솔에서 Lambda 함수를 생성하면 Lambda는 함수에 대한 실행 역할도 생성합니다.

집행 역할 삭제
  1. IAM 콘솔에서 역할 페이지를 엽니다.

  2. Lambda가 생성한 실행 역할을 선택합니다. 역할의 이름 형식은 myLambdaWebhook-role-<random string>입니다.

  3. Delete(삭제)를 선택합니다.

  4. 텍스트 입력 필드에 역할의 이름을 입력하고 Delete(삭제)를 선택합니다.

프라이버시사이트 이용 약관쿠키 기본 설정
© 2025, Amazon Web Services, Inc. 또는 계열사. All rights reserved.