개요
실시간 AI 경험에서 중요한 건 단순히 모델이 얼마나 빨리 답을 내놓느냐가 아닙니다. 사용자가 체감하는 품질은 “정답이 만들어지는 과정을 얼마나 자연스럽게 보여주느냐” 에서 더 크게 드러납니다.
이번 핸즈온에서는 Amazon API Gateway WebSocket, AWS Lambda, Amazon Bedrock을 활용하여 실시간 AI 채팅 애플리케이션을 구축하면서, 실시간 스트리밍의 핵심 개념들을 직접 체험해보겠습니다.
핵심 아키텍처와 역할:
- API Gateway WebSocket: 연결을 붙잡아두는 역할 (연결 관리)
- Lambda: 토큰의 흐름을 조율하는 역할 (백프레셔 제어)
- Bedrock: 실제 답변을 만들어내는 역할 (AI 응답 생성)
- DynamoDB: 연결 상태와 메시지 메타데이터 관리
학습 목표
이 핸즈온을 통해 실시간 AI 스트리밍의 세 가지 핵심 축을 이해하고 구현할 수 있습니다:
- 안정적인 연결 관리: WebSocket 연결 생명주기와 세션 관리
- 적절한 속도 제어: 백프레셔를 통한 토큰 스트림 조율
- 중복 제거 처리: 멱등성과 순서 보장을 통한 품질 확보
사전 준비사항
- AWS 계정 및 적절한 권한을 가진 사용자로 로그인
- Python 3.8.5 이상
- AWS CLI 설정 완료
- Bedrock 모델 액세스 권한 (Nova Lite 모델 활용)
💡 아래 핸즈온은 Linux 환경을 상정하고 있습니다. 윈도우 사용자의 경우 WSL을 통한 실습을 권장합니다.
0단계: Github Clone 으로 작업 디랙터리 생성
- 아래 명령을 통해 리포지토리를 클론합니다.
git clone <https://github.com/KyoboDTS/websocket_chat_bedrock>
cd websocket_chat_bedrock
- 이후 작업은 모두 해당 디랙터리 내부에서 진행하며, 적절한 권한의 AWS CLI가 계정과 연동되어 있어야 합니다. 자세한 내용은 AWS CLI 공식문서를 참조해주세요
1단계: 연결 관리 인프라 구축
1.1 DynamoDB 테이블 생성 – 연결 상태 추적의 핵심
실시간 WebSocket 연결에서는 “누가 지금 연결되어 있는가?”를 정확히 파악하는 것이 중요합니다. API Gateway는 각 연결마다 고유한 connectionId
를 부여하는데, 이를 DynamoDB에 저장해서 메시지를 다시 보낼 때 활용합니다.
연결 관리 테이블 생성:
aws dynamodb create-table \
--table-name doc-example-websocket-chat-bedrock \
--attribute-definitions AttributeName=connection_id,AttributeType=S \
--key-schema AttributeName=connection_id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
세션 관리 테이블 생성:
대화형 AI에서는 이전 대화 맥락을 유지하는 것이 핵심입니다. 세션 관리 테이블은 사용자별로 여러 세션을 관리하고, 각 세션 내에서 대화 히스토리를 저장하기 위한 테이블입니다.
aws dynamodb create-table \
--table-name chat-sessions \
--attribute-definitions \
AttributeName=user_name,AttributeType=S \
AttributeName=session_id,AttributeType=S \
--key-schema \
AttributeName=user_name,KeyType=HASH \
AttributeName=session_id,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST
생성된 테이블 확인

1.2 IAM 역할 생성 – 최소 권한 원칙 적용
Lambda 함수가 DynamoDB, Bedrock, API Gateway와 안전하게 통신하기 위해서는 적절한 권한이 필요합니다. AWS의 최소 권한 원칙에 따라 필요한 권한만 부여합니다.
Lambda 실행 역할 생성:
# 신뢰 정책 파일 생성
cat > trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# IAM 역할 생성
aws iam create-role \
--role-name doc-example-apigateway-websocket-chat-bedrock \
--assume-role-policy-document file://trust-policy.json
권한 정책 생성 및 연결:
각 권한이 왜 필요한지 살펴보겠습니다:
- DynamoDB 권한: 연결 정보 저장/조회, 세션 데이터 관리
- Bedrock 권한: AI 모델 호출 및 스트리밍 응답 수신
- API Gateway 권한: WebSocket 연결로 메시지 전송 (
post_to_connection
)
# 권한 정책 파일 생성
cat > lambda-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Scan",
"dynamodb:Query"
],
"Resource": [
"arn:aws:dynamodb:*:*:table/doc-example-websocket-chat-bedrock",
"arn:aws:dynamodb:*:*:table/chat-sessions"
]
},
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:*:*:inference-profile/apac.amazon.nova-lite-v1:0",
"arn:aws:bedrock:*::*/amazon.nova-lite-v1:0"
]
},
{
"Effect": "Allow",
"Action": "execute-api:ManageConnections",
"Resource": "arn:aws:execute-api:*:*:*"
}
]
}
EOF
# 정책 생성
aws iam create-policy \
--policy-name BedrockWebSocketChatPolicy \
--policy-document file://lambda-policy.json
# 기본 Lambda 실행 정책 연결
aws iam attach-role-policy \
--role-name doc-example-apigateway-websocket-chat-bedrock \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
# 커스텀 정책 연결 (계정 ID 확인 필요)
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws iam attach-role-policy \
--role-name doc-example-apigateway-websocket-chat-bedrock \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/BedrockWebSocketChatPolicy
생성된 권한 확인
- Role(doc-example-apigateway-websocket-chat-bedrock)

- Policy(AWS 관리형 정책 및 커스텀 정책 확인)

1.3 Lambda 함수 생성 – 스트리밍 조율의 핵심
Lambda 함수는 Bedrock이 만들어내는 토큰을 받아서 적절한 속도로 클라이언트에게 전달하는 “교통 정리” 역할을 합니다. 환경 변수를 통해 스트리밍 품질을 세밀하게 조정할 수 있습니다.
Lambda 함수 코드 패키징:
# 함수 코드 압축
zip lambda-function.zip lambda_chat_bedrock.py
# Lambda에 입력할 ROLE의 ARN 확인 및 저장
ROLE_ARN=$(aws iam get-role --role-name doc-example-apigateway-websocket-chat-bedrock --query 'Role.Arn' --output text)
# Lambda 함수 생성
aws lambda create-function \
--function-name bedrock-websocket-chat \
--runtime python3.11 \
--role $ROLE_ARN \
--handler lambda_chat_bedrock.lambda_handler \
--zip-file fileb://lambda-function.zip \
--timeout 60 \
--environment 'Variables={
"table_name":"doc-example-websocket-chat-bedrock",
"session_table_name":"chat-sessions",
"BEDROCK_MODEL_ID":"apac.amazon.nova-lite-v1:0",
"BEDROCK_MAX_TOKENS":"2000",
"BEDROCK_TEMPERATURE":"0.7",
"BEDROCK_TOP_P":"0.9",
"STREAMING_CHUNK_SIZE":"1",
"STREAMING_CHUNK_DELAY":"0.01"
}'
Lambda 함수 생성 확인

1.4 API Gateway WebSocket API 생성 – 실시간 연결의 관문
WebSocket API는 HTTP와 달리 연결을 계속 유지하면서 양방향 통신을 가능하게 합니다.
AWS의 API Gateway WebSocket API 는 추가적인 구현 없이 WebSocket 요청을 클라이언트 – 백앤드 간 연결할 수 있게 합니다.
WebSocket API는 route-selection-expression
을 통해 들어오는 메시지를 적절한 Lambda 함수로 라우팅합니다.
WebSocket API 생성:
# API 생성
API_ID=$(aws apigatewayv2 create-api \
--name bedrock-websocket-chat \
--protocol-type WEBSOCKET \
--route-selection-expression '$request.body.action' \
--query 'ApiId' --output text)
echo "API ID: $API_ID"
# Lambda 함수 ARN 조회
LAMBDA_ARN=$(aws lambda get-function --function-name bedrock-websocket-chat --query 'Configuration.FunctionArn' --output text)
REGION=$(aws configure get region)
# 통합 생성
INTEGRATION_ID=$(aws apigatewayv2 create-integration \
--api-id $API_ID \
--integration-type AWS_PROXY \
--integration-method POST \
--integration-uri "arn:aws:apigateway:${REGION}:lambda:path/2015-03-31/functions/${LAMBDA_ARN}/invocations" \
--query 'IntegrationId' --output text)
echo "Integration ID: $INTEGRATION_ID"
라우트 생성 – WebSocket 생명주기 관리:
WebSocket은 세 가지 핵심 이벤트를 가집니다:
- $connect: 클라이언트가 처음 연결할 때 – connectionId를 DynamoDB에 저장
- $disconnect: 연결이 끊어질 때 – 유령 연결 방지를 위해 정리
- $sendmessage: 실제 메시지 전송 – AI 응답 생성 및 스트리밍
# $connect 라우트
aws apigatewayv2 create-route \
--api-id $API_ID \
--route-key '$connect' \
--target "integrations/${INTEGRATION_ID}"
# $disconnect 라우트
aws apigatewayv2 create-route \
--api-id $API_ID \
--route-key '$disconnect' \
--target "integrations/${INTEGRATION_ID}"
# sendmessage 라우트
aws apigatewayv2 create-route \
--api-id $API_ID \
--route-key 'sendmessage' \
--target "integrations/${INTEGRATION_ID}"
Lambda 권한 추가 – API Gateway가 Lambda를 호출할 수 있도록:
API Gateway가 각 라우트에서 Lambda 함수를 호출할 수 있도록 명시적인 권한을 부여해야 합니다.
# 계정 ID 조회
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# $connect 권한
aws lambda add-permission \
--function-name bedrock-websocket-chat \
--statement-id bedrock-websocket-chat-connect-invoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:${REGION}:${ACCOUNT_ID}:${API_ID}/*/\\$connect"
# $disconnect 권한
aws lambda add-permission \
--function-name bedrock-websocket-chat \
--statement-id bedrock-websocket-chat-disconnect-invoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:${REGION}:${ACCOUNT_ID}:${API_ID}/*/\\$disconnect"
# sendmessage 권한
aws lambda add-permission \
--function-name bedrock-websocket-chat \
--statement-id bedrock-websocket-chat-sendmessage-invoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:${REGION}:${ACCOUNT_ID}:${API_ID}/*/sendmessage"
스테이지 배포 – 실제 사용 가능한 엔드포인트 생성:
auto-deploy
옵션을 통해 변경사항이 자동으로 반영되도록 설정합니다.
# 스테이지 생성 및 배포
aws apigatewayv2 create-stage \
--api-id $API_ID \
--stage-name test \
--auto-deploy
# WebSocket URL 조회
API_ENDPOINT=$(aws apigatewayv2 get-api --api-id $API_ID --query 'ApiEndpoint' --output text)
WEBSOCKET_URL="${API_ENDPOINT}/test"
echo "WebSocket URL: $WEBSOCKET_URL"
API Gateway 생성 확인
- WebSocket API

- Stage

2단계: 실시간 스트리밍 체험하기
2.1 웹 애플리케이션 실행 – 사용자 관점에서 품질 확인
로컬 서버 시작:
# frontend 디렉토리로 이동
cd frontend
# 간단한 HTTP 서버 실행 (Python 3)
python -m http.server 8000
# 또는 Node.js가 있다면
# npx serve .
브라우저에서 접속:
http://localhost:8000
접속- WebSocket URL 입력:
wss://your-api-id.execute-api.region.amazonaws.com/test
- 사용자명 입력 후 “세션 로드” 클릭
2.2 실시간 AI 채팅 테스트 – 스트리밍 품질의 핵심 지표 확인
기본 채팅 테스트:
- “안녕하세요!” 메시지 전송
- AI 응답이 실시간으로 스트리밍되는지 확인
- 마크다운 형식 응답 렌더링 확인
세션 관리 테스트 – 대화 맥락 유지:
- 여러 메시지 주고받기 (“내 이름은 김철수야” → “내 이름이 뭐라고 했지?”)
- “새 세션 시작” 버튼으로 새 대화 시작
- 세션 목록에서 이전 대화 선택하여 히스토리 확인
스트리밍 품질 확인 – 사용자 체감 품질의 핵심:
- TTFB (Time To First Byte): 첫 토큰이 1-1.5초 내 도착하는지 확인
- 이것이 “빠르게 반응했다”는 첫인상을 결정합니다
- 청크 전송: 텍스트가 자연스럽게 한 글자씩 나타나는지 확인
- 너무 빠르면 읽기 어렵고, 너무 느리면 답답합니다
- 순서 보장: 메시지가 올바른 순서로 표시되는지 확인
- 네트워크 지연으로 순서가 바뀌면 품질이 낮다고 느껴집니다
- 채팅 결과 예시

3단계: 백프레셔와 연결 복구 체험하기
3.1 백프레셔 테스트 – 속도 차이 조율 체험
백프레셔란 데이터를 보내는 쪽(Bedrock)과 받아 처리하는 쪽(브라우저) 사이의 속도 차이를 조율하는 메커니즘입니다. Bedrock은 빠른 속도로 토큰을 만들어내지만, 브라우저가 그걸 그대로 감당하지 못한다면 중간에서 속도를 맞춰주는 완충 장치가 필요합니다.
긴 응답 요청:
"파이썬 웹 개발에 대해 자세히 설명해주세요. 프레임워크, 라이브러리, 배포 방법까지 포함해서 길게 답변해주세요."
동시 연결 테스트 – 확장성 확인:
- 여러 브라우저 탭에서 동시 접속
- 각각 다른 사용자명으로 메시지 전송
- 응답 속도 및 안정성 확인
- Lambda 동시 실행 제한과 DynamoDB 처리량 확인
3.2 연결 복구 테스트 – 실제 환경의 불안정성 대응
실제 사용자 환경에서는 네트워크가 불안정할 수 있습니다. WebSocket 연결이 끊어졌을 때 어떻게 복구되는지, 대화 히스토리는 어떻게 유지되는지 확인해보겠습니다.
네트워크 중단 시뮬레이션:
- 채팅 중 네트워크 연결 끊기
- 연결 복구 후 세션 목록 다시 로드
- 이전 대화 히스토리 정상 복구 확인
3.3 DynamoDB 데이터 확인 – 내부 동작 이해하기
실제로 연결 정보와 세션 데이터가 어떻게 저장되는지 확인해보겠습니다.
연결 테이블 조회:
aws dynamodb scan --table-name doc-example-websocket-chat-bedrock
- 사용자 및 세션 정보 확인이 가능합니다.

세션 테이블 조회:
aws dynamodb scan --table-name chat-sessions
- 해당하는 세션에서 대화한 내역을 확인할 수 있습니다.
- 실제 프로덕션 환경 생성시에는 해당 내용을 암호화하여 저장해야 할 것 입니다.

4단계: 운영 관점에서 시스템 이해하기
4.1 CloudWatch 로그 확인 – 문제 해결의 시작점
Lambda 함수에서 발생하는 모든 로그를 통해 스트리밍 과정에서 어떤 일이 일어나는지 확인할 수 있습니다.
Lambda 로그 조회:
# 로그 그룹 확인
aws logs describe-log-groups --log-group-name-prefix /aws/lambda/bedrock-websocket-chat
# 최근 로그 스트림 조회
aws logs describe-log-streams \
--log-group-name /aws/lambda/bedrock-websocket-chat \
--order-by LastEventTime \
--descending \
--max-items 1
# 로그 이벤트 조회 (로그 스트림명 필요)
aws logs get-log-events \
--log-group-name /aws/lambda/bedrock-websocket-chat \
--log-stream-name "LOG_STREAM_NAME"
4.2 API Gateway 메트릭 확인 – 서비스 건강도 모니터링
WebSocket 연결 메트릭:
ConnectCount
: 연결 수 – 동시 사용자 수 파악MessageCount
: 메시지 수 – 트래픽 패턴 분석IntegrationError
: 통합 오류 – Lambda 함수 문제 감지ClientError
: 클라이언트 오류 – 잘못된 요청이나 권한 문제- API Gateway 모니터링은 해당 API의 Dashboard 항목에서 가능하며, CloudWatch에서 또한 가능합니다.

5단계: 성능 최적화 – 사용자 경험 개선하기
5.1 스트리밍 파라미터 조정 – 체감 품질 튜닝
사용자가 “자연스럽다”고 느끼는 스트리밍 속도는 상황에 따라 다릅니다. 이 파라미터들을 조정해서 최적의 사용자 경험을 찾아보겠습니다.
Lambda 환경 변수 수정:
aws lambda update-function-configuration \
--function-name bedrock-websocket-chat \
--environment 'Variables={
"table_name":"doc-example-websocket-chat-bedrock",
"session_table_name":"chat-sessions",
"BEDROCK_MODEL_ID":"apac.amazon.nova-lite-v1:0",
"BEDROCK_MAX_TOKENS":"2000",
"BEDROCK_TEMPERATURE":"0.7",
"BEDROCK_TOP_P":"0.9",
"STREAMING_CHUNK_SIZE":"3",
"STREAMING_CHUNK_DELAY":"0.02"
}'
파라미터 설명과 사용자 경험에 미치는 영향:
STREAMING_CHUNK_SIZE
: 청크당 문자 수 (1-5 권장)- 1: 한 글자씩, 매우 자연스럽지만 네트워크 부하 증가
- 3-5: 단어 단위, 자연스러우면서 효율적
STREAMING_CHUNK_DELAY
: 청크 간 지연 시간 (0.01-0.05초)- 0.01초: 빠른 타이핑 느낌
- 0.05초: 천천히 생각하며 타이핑하는 느낌
BEDROCK_TEMPERATURE
: 창의성 조절 (0.1-1.0)- 0.1-0.3: 일관되고 예측 가능한 답변
- 0.7-1.0: 창의적이지만 때로는 예상 밖의 답변
5.2 DynamoDB 최적화 – 유령 연결 방지
연결이 이미 끊긴 상태인데도 서버가 메시지를 보내려 할 때 API Gateway는 HTTP 410 Gone을 반환합니다. 이런 유령 연결이 쌓이면 불필요한 리소스 점유나 DynamoDB 비용 증가로 이어집니다.
TTL 설정 (연결 테이블):
aws dynamodb update-time-to-live \
--table-name doc-example-websocket-chat-bedrock \
--time-to-live-specification Enabled=true,AttributeName=ttl
자동 배포 프로세스
CloudFormation 스택 배포
지금까지 수동으로 생성한 모든 리소스를 CloudFormation 템플릿으로 자동화할 수 있습니다. 이는 개발 환경과 운영 환경을 일관되게 관리하고, 인프라를 코드로 관리하는 IaC(Infrastructure as Code) 방식입니다.
전체 리소스 자동 배포:
# 의존성 설치
pip install -r requirements_bedrock.txt
# CloudFormation 스택 배포
python websocket_chat_bedrock.py deploy
# API 생성 및 배포
python websocket_chat_bedrock.py demo
# 채팅 테스트 (선택사항)
python websocket_chat_bedrock.py chat
리소스 정리:
# 전체 리소스 삭제
python websocket_chat_bedrock.py destroy
배포 스크립트 구성 요소
setup_bedrock.yaml의 주요 리소스:
- DynamoDB 테이블 2개 (연결 관리, 세션 관리)
- IAM 역할 및 정책 (최소 권한 원칙 적용)
- Lambda 함수 (환경 변수로 스트리밍 품질 제어)
- 필요한 권한 설정 (Bedrock, DynamoDB, API Gateway)
websocket_chat_bedrock.py의 주요 기능:
- CloudFormation 스택 관리 (생성/삭제)
- API Gateway WebSocket API 생성 (라우트 기반 메시지 처리)
- 라우트 및 통합 설정 ($connect, $disconnect, sendmessage)
- Lambda 권한 관리 (API Gateway 호출 권한)
- 자동 배포 및 정리 (개발 환경 빠른 구축/해체)
트러블슈팅 – 실제 운영에서 마주치는 문제들
일반적인 문제 해결
1. 연결 실패 (403 Forbidden) – 권한 문제
- IAM 권한 확인: Lambda 역할에 필요한 정책이 연결되어 있는가?
- API Gateway 스테이지 배포 상태 확인: 변경사항이 실제로 배포되었는가?
- Lambda 함수 권한 설정 확인: API Gateway가 Lambda를 호출할 권한이 있는가?
2. AI 응답 없음 – Bedrock 연동 문제
- Bedrock 모델 액세스 권한 확인: Nova Lite 모델에 대한 액세스가 활성화되어 있는가?
- Lambda 함수 로그에서 오류 메시지 확인: CloudWatch에서 실제 오류 내용 파악
- 환경 변수 설정 확인: 모델 ID와 파라미터가 올바르게 설정되어 있는가?
3. 메시지 순서 뒤바뀜 – 네트워크 지연 문제
- 네트워크 지연 확인: 클라이언트와 서버 간 지연 시간 측정
- 청크 크기 및 지연 시간 조정: 너무 빠른 전송으로 인한 순서 문제 해결
- 브라우저 개발자 도구에서 WebSocket 메시지 확인: 실제 메시지 순서 추적
4. 세션 데이터 손실 – 데이터 영속성 문제
- DynamoDB 테이블 권한 확인: 읽기/쓰기 권한이 올바른가?
- 연결 ID 및 세션 ID 매핑 확인: 연결과 세션이 올바르게 연결되어 있는가?
- TTL 설정으로 인한 자동 삭제 여부 확인: 의도하지 않은 데이터 삭제가 발생했는가?
성능 모니터링 지표 – 사용자 경험 품질 측정
핵심 메트릭과 사용자 경험에 미치는 영향:
- TTFB (Time To First Byte): 1-1.5초 이내 목표
- 이것이 “AI가 빠르게 반응한다”는 첫인상을 결정합니다
- 연결 성공률: 95% 이상
- 사용자가 채팅을 시작할 때 실패하면 서비스 신뢰도가 떨어집니다
- 메시지 전송 성공률: 99% 이상
- 메시지가 전달되지 않으면 대화가 끊어진 느낌을 줍니다
- Lambda 실행 시간: 30초 이내
- 너무 오래 걸리면 사용자가 기다리다 포기할 수 있습니다
알림 설정 권장사항 – 문제 조기 발견:
- Lambda 오류율 > 5%: AI 응답 생성에 문제가 있을 가능성
- API Gateway 4xx/5xx 오류 > 10%: 연결이나 권한 문제 발생
- DynamoDB 스로틀링 발생: 동시 사용자 증가로 인한 성능 저하
- 연결 수 급증 (예: 평소의 3배 이상): 예상치 못한 트래픽 증가
마무리
이 핸즈온을 통해 실시간 AI 스트리밍의 핵심 개념을 직접 체험해보았습니다:
- 연결 관리: WebSocket을 통한 지속적인 양방향 통신
- 백프레셔 제어: Lambda에서 토큰 스트림 속도 조율
- 순서 보장: 멱등성과 시퀀스를 통한 품질 확보
실시간 AI의 품질은 단순히 “빠른 응답”이 아니라 **“자연스러운 대화 경험”**에서 나옵니다. 첫 토큰이 빠르게 도착하고, 이후 글이 매끄럽게 이어지며, 순서가 뒤바뀌지 않을 때 사용자는 “품질이 좋다”고 느낍니다.
앞으로 AI와의 상호작용이 점점 더 실시간적이고 자연스러운 형태로 진화할수록, 이 세 가지 요소는 단순한 기술적 고려를 넘어 사용자 경험(UX)의 핵심이 될 것입니다.