WhatsApp 사용자들의 가장 흔한 습관 (그리고 이를 다루는 방법)

발행: (2026년 2월 27일 오후 12:28 GMT+9)
16 분 소요
원문: Dev.to

Source: Dev.to

AWS 전문 솔루션 아키텍트
AWS 적용 AI
표현된 의견은 전적으로 제 개인적인 것이며, 제 고용주의 견해나 의견을 대변하지 않습니다.

Overview

WhatsApp‑to‑Amazon Connect 통합을 최적화하는 방법을 배우세요. 빠르게 연속해서 들어오는 메시지를 하나의 일관된 메시지로 버퍼링합니다. 이 단계별 가이드는 다음을 사용한 전체 아키텍처를 다룹니다:

  • AWS CDK
  • DynamoDB Streams (텀블링 윈도우 사용)
  • AWS Lambda
  • AWS End User Messaging Social
  • Amazon Connect

고객이 WhatsApp을 통해 문의할 때는 보통 한 번에 하나의 메시지만 보내지 않습니다. 빠르게 입력하죠:

Hello
I need help
with my order
P12345

각 메시지는 별도의 웹훅 이벤트를 트리거하며, 최적화가 없으면 각각이 Amazon Connect에 별개의 채팅 메시지로 생성됩니다. 결과는?

  • 파편화된 대화
  • 혼란스러운 상담원
  • 불필요한 비용

AI 기반 채팅에서는 상담원이 아직 처리 중일 때 사용자가 추가 메시지를 보내지 못하도록 보통 방지합니다. 비동기식 프로그래밍 메시지에서는 이를 제어할 수 없지만, 응답하기 전에 기다리는 시간을 제어할 수 있습니다. 이 블로그는 WhatsApp‑to‑Connect 시나리오에만 국한되지 않고, 동일한 문제에 직면한 모든 채팅 채널(SMS, 소셜 미디어 DM 등)에도 적용됩니다.

메시지‑버퍼링 레이어를 사용해 빠르게 연속된 WhatsApp 메시지를 하나의 일관된 메시지로 집계한 뒤 Amazon Connect에 전달하는 방법을 배울 수 있습니다.

Code repository:

아키텍처 요약

AWS End User Messaging SocialAmazon Connect 사이의 버퍼링 레이어는 다음을 수행합니다:

  1. 들어오는 WhatsApp 메시지를 DynamoDB 테이블에 캡처합니다.
  2. DynamoDB Streams와 텀블링 윈도우를 사용하여 메시지를 버퍼링합니다.
  3. 동일 발신자로부터 연속된 텍스트 메시지를 하나로 집계합니다.
  4. 결합된 메시지를 단일 채팅 메시지로 Amazon Connect에 전달합니다.

Result: 에이전트는 파편화된 메시지의 홍수 대신 깔끔하고 자연스러운 대화를 보게 됩니다.

데이터 흐름

  1. WhatsApp → AWS End User Messaging SocialSNS 토픽에 게시합니다.
  2. **Lambda on_raw_messages**가 각 메시지를 DynamoDB 테이블 **raw_messages**에 저장합니다.
  3. DynamoDB Streams가 텀블링 윈도우를 버퍼로 사용하여 **Lambda message_aggregator**를 트리거합니다.
  4. 집계기는 동일 발신자의 텍스트 메시지를 그룹화, 정렬 및 연결합니다.
  5. 집계된 메시지는 WhatsApp 이벤트 핸들러로 전달되며, 해당 핸들러는 Amazon Connect 채팅 세션을 생성/업데이트합니다.

문제 설명

When users send multiple messages quickly:

Message #Content
1안녕
2도움을 필요로 합니다
3내 주문과 관련해서
4P12345

버퍼링 없이 각 메시지는 별도의 Amazon Connect 채팅 메시지가 되어 다음과 같은 문제가 발생합니다:

  • 에이전트가 따라가기 어려운 단편화된 대화.
  • 비용 증가 (각 메시지가 개별 청구됨).
  • 여러 하위 Lambda 호출.

DynamoDB Table: raw_messages

  • Partition key: from (보내는 사람 전화번호)
  • Sort key: id (메시지 ID)
  • TTL: 자동 정리를 위해 활성화됨
  • Streams: 텀블링 윈도우와 함께 활성화됨

from을 파티션 키로 사용하면 동일한 사용자의 메시지가 함께 저장되어 동일한 샤드에 배치되므로 스트림에서 순차적으로 처리할 수 있습니다.

Lambda: 원시 메시지 저장

import json, decimal, os, boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.getenv('RAW_MESSAGES_TABLE'))

def lambda_handler(event, context):
    records = event.get("Records", [])

    for record in records:
        sns = record.get("Sns", {})
        sns_message = json.loads(sns.get("Message", "{}"), parse_float=decimal.Decimal)
        webhook_entry = json.loads(sns_message.get("whatsAppWebhookEntry", "{}"))

        for change in webhook_entry.get("changes", []):
            value = change.get("value", {})
            metadata = value.get("metadata", {})
            contacts = value.get("contacts", [])

            for message in value.get("messages", []):
                item = message.copy()
                item["metadata"] = metadata
                item["messaging_product"] = value.get("messaging_product")

                # Store in DynamoDB
                table.put_item(Item=item)

    return {'statusCode': 200}

Buffering Strategy: Tumbling Window

텀블링 윈도우는 버퍼링 전략의 핵심입니다. DynamoDB Streams는 message_aggregator Lambda를 트리거하지만, 각 레코드마다 호출하는 대신 윈도우는 설정 가능한 초(기본 20 s)만큼 대기한 뒤 해당 윈도우에 누적된 모든 레코드와 함께 함수를 호출합니다.

  • One Lambda per shard → 윈도우 내에서 같은 사용자의 메시지가 함께 처리됩니다.

Source:

Aggregator Lambda

집계기는 발신자별로 메시지를 그룹화하고, 타임스탬프 순으로 정렬한 뒤, 연속된 텍스트 메시지를 줄바꿈으로 연결합니다. 이미지, 오디오, 문서 등 텍스트가 아닌 메시지는 별개의 항목으로 그대로 유지됩니다.

입력 예시

Message 1: Hello
Message 2: I need help
Message 3: with my order
Message 4: P12345

출력 (단일 집계 메시지)

Hello
I need help
with my order
P12345

핵심 집계 로직

import os, json, boto3
from boto3.dynamodb.types import TypeDeserializer

lambda_client = boto3.client('lambda')
deserializer = TypeDeserializer()

def deserialize_dynamodb(image):
    return {k: deserializer.deserialize(v) for k, v in image.items()}

def aggregate_all_messages(records):
    # 발신자별로 그룹화
    grouped = {}
    for rec in records:
        sender = rec['from']
        grouped.setdefault(sender, []).append(rec)

    aggregated = []
    for sender, msgs in grouped.items():
        # 타임스탬프(또는 ID) 기준으로 정렬하여 순서 유지
        msgs.sort(key=lambda x: x.get('timestamp') or x.get('id'))
        # 연속된 텍스트 메시지 연결
        text_parts = [m['body'] for m in msgs if m.get('type') == 'text']
        aggregated_body = "\n".join(text_parts)

        # 텍스트가 아닌 항목 보존(선택적 처리)
        non_text = [m for m in msgs if m.get('type') != 'text']

        agg_msg = {
            "from": sender,
            "aggregated_body": aggregated_body,
            "original_messages": msgs,
            "non_text_attachments": non_text
        }
        aggregated.append(agg_msg)

    return aggregated

def lambda_handler(event, context):
    raw_records = event.get("Records", [])
    records = []

    for record in raw_records:
        if record.get("eventName") == "INSERT":
            new_image = record.get("dynamodb", {}).get("NewImage", {})
            deserialized = deserialize_dynamodb(new_image)
            records.append(deserialized)

    if not records:
        return {"state": event.get('state', {})}

    aggregated = aggregate_all_messages(records)

    # 각 집계 메시지를 WhatsApp 이벤트 핸들러에 전달
    for agg in aggregated:
        lambda_client.invoke(
            FunctionName=os.environ['WHATSAPP_EVENT_HANDLER'],
            InvocationType='Event',
            Payload=json.dumps(agg)
        )

    return {"state": event.get('state', {})}

최종 단계: Amazon Connect로 전달

집계가 완료되면 Lambda가 asynchronously WhatsApp event handler를 호출하여, 결합된 메시지로 Amazon Connect 채팅 세션을 생성하거나 업데이트합니다. 에이전트는 이제 파편화된 메시지들의 홍수가 아니라 one 채팅 항목을 보게 됩니다.

핵심 요약

  • 버퍼링을 통해 빠르게 연속되는 메시지를 처리하면 채팅 파편화를 줄일 수 있습니다.
  • DynamoDB Streams의 텀블링 윈도우는 메시지를 배치 처리하는 간단하고 서버리스 방식을 제공합니다.
  • 이 패턴은 모든 채팅 채널(WhatsApp, SMS, 소셜 미디어 DM 등)에서 작동합니다.

위에 링크된 GitHub 저장소에서 전체 구현을 자유롭게 살펴보세요. 즐거운 개발 되세요!

메시지 버퍼링의 장점

  • 더 깔끔한 대화 흐름 – 여러 개의 빠른 메시지가 하나의 일관된 메시지로 표시됩니다.
  • 비용 최적화 – 다운스트림 메시지 수가 줄어 Amazon Connect Chat 비용이 낮아집니다.
  • 자동 정리 – TTL이 오래된 원시 메시지를 자동으로 삭제합니다.
  • 확장성 – DynamoDB Streams가 높은 처리량(스트림당 최대 10 000 레코드)을 처리합니다.
  • 신뢰성 – 스트림 처리로 최소 1회 전달이 보장되어 메시지가 손실되지 않습니다.
  • 예시 시나리오 – 1 000개의 원시 메시지가 250개의 메시지로 집계됨(비율 4 : 1). 메시지는 인간 상담원이 응답합니다.

비용 비교

구성 요소버퍼링 없이버퍼링 사용절감액
DynamoDB + Streams≈ $0.0013
Lambda (전체 함수)≈ $0.00078
버퍼링 인프라스트럭처$0.00≈ $0.002
인바운드 API 호출1 000 회250 회75 % 감소
Connect Chat (인바운드) 비용$4.00$1.00$3.00
총합$4.00≈ $1.00≈ $3.00 (75 % 감소)

참고: 총 비용에는 Connect 인바운드/아웃바운드와 End‑User Messaging(EUM) 인바운드/아웃바운드가 모두 포함됩니다. 이 예시에서는 Amazon Connect Chat 인바운드 메시지만 감소시켰습니다.

  • Connect Chat 비용: $0.004 × msg(인) + $0.004 × msg(아웃) – 공식 가격 페이지를 참고하세요.
  • EUM 비용: $0.005 × msg(인) + $0.005 × msg(아웃) – 공식 가격 페이지를 참고하세요.

Prerequisites

  1. WhatsApp Business Account (WABA) – 새 계정을 만들거나 기존 계정을 AWS로 마이그레이션합니다.

    • Meta Business Account를 보유하거나 생성합니다.
    • AWS End User Messaging (EUM) Social 콘솔을 열고 내장된 Facebook 포털을 통해 비즈니스 계정을 연결합니다.
    • SMS/음성 인증을 받을 수 있는 전화번호를 확보하고 WhatsApp에 추가합니다.
    • ⚠️ 개인 WhatsApp 번호를 사용하지 마세요.
  2. Amazon Connect 인스턴스 – 아직 없으시다면 Amazon Connect 설정 가이드를 따라 주세요.

  3. 인스턴스 식별자 – Amazon Connect 콘솔에서 다음 ARN을 찾습니다:

    arn:aws:connect:::instance/INSTANCE_ID
    arn:aws:connect:::instance/INSTANCE_ID/contact-flow/CONTACT_FLOW_ID
  4. Contact flow – 사용자 경험을 정의하는 인바운드 컨택트 플로우를 생성(또는 재사용)하고 게시합니다.

  5. Region alignment – AWS End User Messaging WhatsApp 번호가 구성된 동일한 리전에서 모든 리소스를 배포합니다.

배포 단계

# Clone the sample repository
git clone https://github.com/aws-samples/sample-whatsapp-end-user-messaging-connect-chat.git
cd sample-whatsapp-end-user-messaging-connect-chat/whatsapp-eum-connect-chat

# Follow the CDK Deployment Guide (README.md) to deploy the stack

배포가 완료된 후, SSM 매개변수 /whatsapp_eum_connect_chat/config 를 귀하의 Amazon Connect 세부 정보로 업데이트하십시오:

{
  "instance_id": "",
  "contact_flow_id": "",
  "chat_duration_minutes": 60,
  "ignore_reactions": "yes",
  "ignore_stickers": "yes"
}

매개변수 참조

매개변수설명
instance_id귀하의 Amazon Connect 인스턴스 ID
contact_flow_id채팅용 인바운드 연락 흐름의 ID
chat_duration_minutes채팅 세션이 활성 상태를 유지하는 시간 (기본값 = 60)
ignore_reactionsWhatsApp 반응을 무시할지 여부 (기본값 = yes)
ignore_stickersWhatsApp 스티커를 무시할지 여부 (기본값 = yes)

Source:

스택을 AWS End‑User Messaging에 연결

  1. SNS 토픽 ARN 가져오기

    • AWS Systems Manager → Parameter Store를 엽니다.
    • /whatsapp_eum_connect_chat/topic/in 값( arn:aws:sns 로 시작)을 복사합니다.
  2. EUM Social 콘솔에서 대상 구성

    • Destination → Amazon SNS를 선택합니다.
    • 복사한 토픽 ARN을 붙여넣습니다.

선택적 조정

  • 버퍼 윈도우 – 기본값은 20 초입니다. 변경하려면 config.pyBUFFER_IN_SECONDS를 편집하고 재배포하십시오:

    BUFFER_IN_SECONDS = 20  # 필요에 따라 수정 (초)
  • 테스트 – Amazon Connect **Contact Control Panel (CCP)**를 열고, EUM 번호로 WhatsApp 메시지를 전송한 뒤, 빠르게 들어오는 메시지들이 Connect에서 하나의 메시지로 집계되는 것을 확인하십시오.

  • 추가 개선 사항

    • 사용 사례에 따라 버퍼 윈도우를 조정합니다(실시간에는 짧게, 비용 절감에는 길게).
    • 스트림 처리 실패에 대비해 Dead‑Letter Queue를 추가합니다.
    • 사용자 정의 집계 로직을 구현합니다(예: 이미지들을 함께 그룹화).
    • Agent‑Initiated WhatsApp 솔루션과 결합하여 양방향 통신을 완전하게 구현합니다.

유용한 링크

  • 프로젝트 저장소
  • Amazon Connect 관리자 가이드
  • Amazon Connect API 레퍼런스
  • AWS 최종 사용자 메시징 소셜 사용자 가이드
  • DynamoDB Streams 개발자 가이드
  • Amazon DynamoDB와 AWS Lambda를 사용한 확장 가능한 이벤트‑기반 아키텍처 구축

AWS 전문 솔루션 아키텍트 – Applied AI @ AWS
표현된 의견은 전적으로 저 개인의 것이며, 고용주의 견해를 대변하지 않습니다.

0 조회
Back to Blog

관련 글

더 보기 »