요약: 이 글은 2025년 카카오페이-AWS 해커톤에 참가하여 AI 기반 대출 음성 상담 챗봇 서비스를 개발한 팀의 이야기입니다. 비대면 금융 환경에서 개인화된 상담의 부재라는 문제의식에서 출발하여, 음성 상담을 통해 사용자의 상황을 파악하고 맞춤형 대출 상품을 추천하는 챗봇을 구현했습니다. Amazon Transcribe, Bedrock, Polly 등 AWS AI 서비스를 활용하여 음성 인식부터 텍스트 변환, 챗봇 응답 생성 및 음성 합성까지 전 과정을 구축한 이야기를 전합니다. 특히, 실제 대출 데이터의 개인 정보 문제를 해결하기 위해 합성 데이터를 생성하고, RAG(Retrieval-Augmented Generation) 방식을 도입하여 개인 맞춤형 대출 추천 기능을 강화했던 생생한 이야기를 공유합니다.
💡 리뷰어 한줄평
sunny.ryu AI 기반 대출 음성 상담 챗봇이라니? 굉장히 신선하고 유용할 것 같아요. 얼마나 많은 고민을 거듭하며 개발했는지, AI와 핀테크가 어떻게 어우러질 수 있는지 궁금한 분들에게 강력 추천드려요!
시작하며
안녕하세요, 카카오페이 크레딧클랜 PM 조엘입니다. 2025년 카카오페이와 AWS가 함께 주최한 해커톤에서 대출 서비스의 확장성과 AI를 활용한 금융 중개 서비스를 만들어보고자 크레딧클랜 팀원들과 함께 참여했는데요. 생성형 AI를 활용한 서비스 개발에 관심이 많고 AI를 금융 서비스에 접목시키고자 하는 분들이 참고하면 좋은 이야기들을 전해보고자 합니다. 기획 배경, 전체 데이터 플로우, 백엔드 구현 세부사항, AI Agent 파이프라인, 그리고 마지막으로 개발 과정에서의 트러블슈팅 사례를 소개할게요. 그럼 우선 저희가 AI 대출 음성 상담 챗봇 서비스를 기획하게 된 배경을 먼저 공유드리겠습니다.
기획 배경
비대면 금융의 그림자, 그리고 개인화된 상담의 부재
저희는 비대면 금융 서비스 이용은 꾸준히 증가하고 있지만, 여전히 많은 소비자들이 불확실성 때문에 직접 상담을 선호하는 경향이 있다는 점에 집중했습니다. 특히, 중요한 결정이 필요한 대출의 경우 이러한 경향은 더욱 두드러지는데요. 이때, 온라인 대출 중개서비스에서 진정으로 필요한 것은 온라인에서도 개인의 상황을 깊이 이해하는 맞춤형 상담이라고 생각했습니다.
그렇게 탄생한 ‘당신의 목소리에 귀 기울이는, AI 대출 음성 상담 챗봇’
해커톤에서 개발한 대출 음성 상담 챗봇은 마치 은행 창구에서 상담을 받는 것처럼, 사용자의 음성을 통해 고민을 듣고 대출 상품을 추천하는 서비스입니다. AI는 음성으로 주고받은 답변으로 사용자에게 가장 적합한 금리와 한도를 제공하는 금융사를 추천하죠. 추천 결과가 만족스럽지 않다면, 추가 상담을 통해 더 나은 조건이나 맞춤형 솔루션을 제공하여 고객 만족도를 높이는 것에도 집중했습니다.

물론 텍스트로도 주고받을 수 있지만, ‘음성’으로 구현한 이유는 위에 언급한 문제점과 관련이 깊습니다. 일방향의 느낌보다는 쌍방향 소통처럼 은행 창구에서 대화하는 UX를 통해 소비자들의 불확실성을 낮추고, 대출 중개 플랫폼에서도 본인의 고민을 충분히 상담할 수 있는 경험을 선사하고 싶었습니다. 아직 존재하지 않은 시장이라 이번 해커톤을 통해 아이디어를 실현해보고 싶은 마음도 있었고요!
AI 대출 음성 상담 챗봇의 핵심적인 기능은 다음과 같습니다.
- 자연스러운 음성 인터페이스: 복잡한 텍스트 입력 없이, 음성을 통한 편리하고 직관적인 상담 경험을 제공합니다.
- 개인 맞춤형 상품 추천: 음성 상담 과정에서 파악된 사용자의 상황과 니즈를 기반으로, 최적의 조건과 혜택을 제공하는 금융 기관을 지능적으로 연결합니다.
- 데이터 기반 개선 제안: 사용자의 금융 데이터를 심층적으로 분석하고, 유사한 특성을 가진 다른 사용자와의 비교를 통해 개선 가능한 금융 관리 방안을 제시합니다. (더 좋은 신용 점수를 받을수록, 더 좋은 조건의 대출 상품이 나타나기 때문입니다)
핵심 기능들을 보니, 어떻게 구현하였는지 궁금하실 것 같아요. 이어서 제이코가 구현한 전체 서비스 플로우를 통해 기술적인 내용을 살펴보시죠!
전체 데이터 플로우
안녕하세요, 카카오페이 크레딧클랜의 백엔드 개발자 제이코입니다. 이번 해커톤에서 저희 팀은 사용자의 음성을 기반으로 대출 상담을 제공하는 챗봇 서비스를 구현했습니다.
사용자가 음성을 통해 질문을 하면, 그 음성을 텍스트로 변환하고 이를 기반으로 LLM이 적절한 답변을 생성한 뒤, 다시 음성으로 전환하여 사용자에게 응답하는 방식으로 동작합니다. 해당 흐름은 프론트엔드와 백엔드 간 WebSocket 통신, 그리고 백엔드에서 AWS의 다양한 AI 서비스를 연동하여 구성되었습니다. 전체적인 데이터 흐름은 다음과 같은 7단계로 구성됩니다.

그럼 이제, 각 단계를 조금 더 자세히 알아보겠습니다.
1. 프론트엔드 → 백엔드: 사용자의 음성을 전달

사용자가 마이크를 통해 질문을 하면, 프론트엔드는 해당 음성을 실시간으로 스트리밍하여 백엔드에 전달합니다. 이때, WebSocket 기반 통신 방식을 선택했습니다. WebSocket은 클라이언트와 서버 간 양방향 통신을 지원하고, HTTP처럼 매번 새로운 연결을 생성하지 않고 한 번의 연결로 지속적인 데이터를 주고받기가 가능합니다. 이를 통해, 지연을 최소화하며 자연스러운 실시간 대화 흐름을 구현할 수 있었습니다. 또한, 음성 입력은 일정 볼륨 임계값 이상일 때만 전송되도록 하여, 불필요한 네트워크 사용을 줄이고 주변 잡음이 전달되는 것을 방지했습니다.
2. 백엔드 → Amazon Transcribe: 사용자의 음성을 텍스트로 변환

프론트엔드에서 전달받은 음성은 Amazon Transcribe를 통해 텍스트로 변환됩니다. Amazon Transcribe는 AWS의 실시간 음성 인식 서비스로, 음성을 텍스트로 변환해 주는 STT(Speech-to-Text) 기능을 제공합니다. Amazon Transcribe는 스트리밍 API를 통해 연속적인 음성 입력을 실시간으로 처리할 수 있어, 사용자가 말을 멈추지 않고 계속 질문을 하더라도 중단 없이 텍스트로 변환할 수 있습니다. 이를 통해 연속적인 대화에 원활하게 대응할 수 있었습니다.
3. 백엔드 → 프론트엔드: 텍스트를 사용자에게 전달

Amazon Transcribe로부터 받은 텍스트 결과는 프론트엔드로 전달됩니다. 이를 통해 사용자는 자신의 질문이 정확하게 전달되었는지를 화면에서 실시간으로 확인할 수 있습니다.
4. 백엔드 → Amazon Bedrock: 사용자의 음성에 대한 챗봇 응답 생성

사용자의 질문은 Amazon Bedrock을 통해 적절한 응답으로 변환됩니다. Amazon Bedrock은 AWS에서 제공하는 다양한 생성형 AI 모델(Anthropic Claude, Meta Llama, Google PaLM 등)을 쉽게 사용할 수 있도록 API 형태로 제공하는 서비스입니다. 저희는 그중 하나인 Anthropic Claude를 사용하여 대출 관련 질문에 특화된 응답을 생성했습니다. Anthropic Claude는 자연스러운 대화 처리와 정확한 답변 제공에 강점을 가지고 있어, 금융 도메인에 특화된 질문에 대해 일관성 있고 신뢰할 수 있는 답변을 제공합니다. 또한, 질문의 맥락을 파악할 수 있도록 프롬프트를 설계하여 보다 정확한 응답을 생성할 수 있도록 했습니다.
5. 백엔드 → 프론트엔드: 챗봇 응답을 텍스트로 전달

Amazon Bedrock으로부터 생성된 응답 텍스트는 프론트엔드에 전송되어 화면에 출력됩니다. 덕분에 사용자는 음성뿐만 아니라 텍스트 형태로도 상담 내용을 확인할 수 있습니다.
6. 백엔드 → Amazon Polly: 챗봇 응답 텍스트를 음성으로 변환

텍스트 응답은 Amazon Polly를 통해 음성으로 변환됩니다. Amazon Polly는 AWS의 텍스트 음성 변환 서비스로, 텍스트를 자연스러운 음성으로 변환해 주는 TTS(Text-to-Speech) 기능을 제공합니다. 다양한 언어와 음색을 제공하며, 감정 표현이나 속도 조절 등도 가능하여 실제 사람처럼 말하는 효과를 낼 수 있습니다. 저희는 한국어 여성 음성을 사용해 부드러운 톤으로 상담 응답을 제공했습니다.
7. 백엔드 → 프론트엔드: 음성을 사용자에게 전달

Amazon Polly로부터 생성된 음성은 다시 프론트엔드로 전달되어 사용자에게 재생됩니다. 이로써 사용자는 질문–응답의 전체 상담 흐름을 음성 기반으로 자연스럽게 경험할 수 있으며, 이어서 추가 질문도 연속적으로 할 수 있습니다.
지금까지 전체적인 데이터 플로우를 살펴보았습니다. 이제, 이러한 흐름을 실제로 어떻게 구현했는지에 대한 구체적인 내용을 소개하겠습니다.
백엔드 구현 세부사항
안녕하세요, 카카오페이 크레딧클랜의 백엔드 개발자 그렉입니다. 앞서 설명드린 전체적인 데이터 플로우에 이어서 백엔드 구현 세부사항을 설명드리겠습니다.
1. WebSocket 메시지
WebSocket 통신은 HTTP 통신과 달리 요청마다 고유한 경로를 사용하지 않으므로, 각 메시지의 목적을 명확히 구분할 방법이 필요했습니다. 이를 위해 메시지에 type
필드를 추가하여 목적을 명시적으로 나타냈습니다.
{
"type": "AGENT_TEXT",
"text": "적합한 상품을 추천해 드릴게요."
}
2. 코틀린 코루틴 채널을 활용한 비동기 처리 흐름 단순화
AWS 서비스 연동 과정에서 중요하게 생각한 부분은 비동기 처리 흐름을 단순하게 유지하는 것이었습니다.
예를 들어 Amazon Transcribe에 요청을 보내고, 그 응답을 처리하여 Amazon Bedrock으로 전달하는 코드를 생각해 보겠습니다. Amazon Transcribe 클라이언트에 핸들러를 등록하고, 핸들러 내부에서 응답을 처리하여 Amazon Bedrock으로 전달하더라도 기대한 대로 동작할 것입니다. 하지만 이러한 방식은 비즈니스 로직이 여러 핸들러로 파편화되기 시작하기 때문에 흐름을 한눈에 파악하기 어려워진다는 단점을 가집니다.
이 문제를 해결하기 위해 코틀린 코루틴의 채널을 활용했습니다. 채널은 코루틴 간에 데이터 스트림을 전달할 수 있는 비동기 통신 수단입니다. 저희 프로젝트는 프로그래밍 언어로 코틀린을, 비동기 처리에는 코루틴을 사용하고 있었고, 이러한 기술 스택에서 채널이 비동기 통신 수단으로 적합하다고 판단했습니다.
데이터 전송 방향에 따라 업스트림과 다운스트림 채널을 구분하여 정의한 뒤, 비동기 처리 흐름을 다음과 같이 구성했습니다.
- AWS 서비스 요청 데이터를 업스트림 채널로 전송
- 업스트림 채널을 구독 중인 코루틴이 AWS 서비스에 요청
- AWS 서비스에서 응답
- AWS 서비스의 응답을 수신하는 핸들러가 응답 데이터를 다운스트림 채널로 전송
- 다운스트림 채널을 구독 중인 코루틴이 응답 데이터를 처리
이제 메인 로직을 아래 코드와 같이 한 곳으로 모을 수 있습니다.
launch {
while (true) {
val transcribeDownstreamElement = transcribeDownstreamChannels.getValue(sessionId).receive()
val webSocketMessage = ... // WebSocket 메시지 생성
sendSerialized(webSocketMessage)
if (transcribeDownstreamElement.isPartial.not()) {
val bedrockUpstreamElement = ... // Amazon Bedrock 요청 객체 생성
bedrockUpstreamChannels.getValue(sessionId).send(bedrockUpstreamElement)
}
}
}
launch {
while (true) {
val bedrockDownstreamElement = bedrockDownstreamChannels.getValue(sessionId).receive()
val webSocketMessage = ... // WebSocket 메시지 생성
sendSerialized(webSocketMessage)
val pollyUpstreamElement = ... // Amazon Polly 요청 객체 생성
pollyUpstreamChannels.getValue(sessionId).send(pollyUpstreamElement)
}
}
launch {
while (true) {
val pollyDownstreamElement = pollyDownstreamChannels.getValue(sessionId).receive()
val webSocketMessage = ... // WebSocket 메시지 생성
sendSerialized(webSocketMessage)
}
}
결과적으로 전체 흐름을 파악하기 쉬워졌고, 핸들러의 책임을 데이터의 가공과 전달로 한정할 수 있었습니다. 또한 프론트엔드 통신과 AWS 서비스 연동을 채널을 경계로 논리적으로 분리시킨 덕분에, 두 명의 서버 개발자가 병렬적으로 작업할 수 있다는 이점도 얻었습니다.
3. 다중 사용자 지원
기본적인 동작을 확인한 후 여러 팀원이 동시에 테스트하기 시작하자 의도치 않은 현상이 발생했습니다. A 팀원의 음성을 변환한 텍스트가 B 팀원에게 표시되기 시작한 것입니다.
따라서 여러 사용자의 동시 접속을 지원할 수 있도록 사용자 간 영향을 제거할 방법이 필요했습니다. 이를 위해 각 WebSocket 세션마다 고유한 세션 ID를 생성하고, 해당 세션 ID와 채널들을 매핑하도록 변경했습니다. 메모리 누수를 방지하기 위해 세션 종료 시점에 맵에 등록된 채널들을 닫고 맵에서 제거하는 로직도 추가해 주었습니다.
val transcribeUpstreamChannels = ConcurrentHashMap<SessionId, Channel<TranscribeUpstreamChannelElement>>()
val transcribeDownstreamChannels = ConcurrentHashMap<SessionId, Channel<TranscribeDownstreamChannelElement>>()
val bedrockUpstreamChannels = ConcurrentHashMap<SessionId, Channel<BedrockUpstreamChannelElement>>()
val bedrockDownstreamChannels = ConcurrentHashMap<SessionId, Channel<BedrockDownstreamChannelElement>>()
val pollyUpstreamChannels = ConcurrentHashMap<SessionId, Channel<PollyUpstreamChannelElement>>()
val pollyDownstreamChannels = ConcurrentHashMap<SessionId, Channel<PollyDownstreamChannelElement>>()
4. 정리
지금까지 말씀드린 내용을 한 장의 그림으로 표현하면 다음과 같습니다.

이어서 핀이 AI Agent 파이프라인에 대해 설명드리겠습니다.
AI Agent 파이프라인
안녕하세요, 카카오페이 크레딧클랜과 데이터실 데이터분석팀에 속한 핀입니다! 앞에서 제이코와 그렉이 백엔드 부분을 자세히 설명해 주셨는데요. 이번에는 대출 도메인에서 개인화된 대출 상담 경험을 위해서 AI Agent(이하 AI 에이전트)를 효과적으로 활용하고 고민한 부분을 공유하고자 합니다. 핵심은 사용자의 음성을 텍스트로 변환하고, 이 정보를 기반으로 AI 에이전트가 대출 상담하는 과정입니다. AI 에이전트는 세션 히스토리를 기억하며, 각 대출 가망 고객에게 맞춤형 응답과 케어를 제공합니다. 이러한 과정을 가능하게 하는 대출 도메인 특화 LLM 데이터 파이프라인을 함께 살펴보시죠.
대출 도메인에 특화된 전체적인 LLM 데이터 파이프라인을 살펴보면 아래 이미지와 같습니다!

구체적인 과정을 자세히 알아보겠습니다.
1. Synthetic Data Generation: 합성데이터 생성
카카오페이의 대출 서비스는 결국 금융사가 보유한 다양한 대출 상품을 필요로 하는 고객에게 최적의 방식으로 연결하는 데 중요한 역할을 합니다. 이를 위해서는 대출 상품과 고객의 행동 및 메타 데이터(예: 성별, 연령) 간의 정교한 매칭이 필수적입니다. 이러한 정밀한 매칭은 고객 만족도를 높이고, 금융사의 상품 활용도를 극대화하는 데 기여합니다.
합성 데이터 도입
그러나 대출 데이터는 민감한 개인 정보를 포함하고 있어, 원본 데이터를 그대로 AI 에이전트 학습 및 추론에 활용할 수 없습니다. 그래서 개인 정보 보호 규제를 준수하면서 AI 모델을 효과적으로 학습시키기 위한 방안이 필수적입니다. 이에 따라 원본 데이터와 유사한 통계적 속성을 지닌 합성 데이터(Synthetic Data)를 생성하는 것이 중요합니다. 합성 데이터는 개인 정보 유출의 위험 없이 AI 모델 개발 및 테스트에 활용될 수 있으며, 데이터 부족 문제를 해결하는 데에도 도움이 됩니다.
데이터 선별 및 분포 분석
이를 위해 먼저 하둡(Hadoop) 내에 저장된 가명 처리된 대출 및 마이데이터 중에서 대출 상담 및 케어에 필요한 데이터를 선별합니다. 다음으로, 선정된 데이터의 각 컬럼별 분포 정보를 생성합니다. 각 변수가 어떤 값의 범위를 가지며, 어떤 빈도로 나타나는지 먼저 파악했습니다. 특히, 대출 비즈니스가 여러 요인의 복합적인 작용으로 이루어진다는 점을 고려하여 변수 간의 상관관계와 다변량 분포(예: 공분산 행렬) 정보를 추출하는 데 집중했습니다.
추출된 다변량 분포를 포함한 통계 정보를 기반으로 AWS 환경에서 샘플링을 진행합니다. 이 과정에서 코풀라(Copula) 함수 기법을 활용하여 원본 데이터와 최대한 유사한 합성 데이터를 생성하고자 노력했습니다. 코풀라 함수는 각 변수의 주변 분포를 유지하면서 변수 간의 종속 구조를 모델링하는 통계적 방법입니다. 이를 통해 단순한 통계적 속성뿐만 아니라 변수 간의 복잡한 관계까지 합성 데이터에 반영할 수 있습니다.
실제 데이터 특성 반영 및 모델 강건성 확보
실제 환경에서의 모델 강건성 확보 또한 중요합니다. 이를 위해 실제 데이터의 특징인 결측치와 이상치를 합성 데이터에 적절히 반영하여 모델의 강건성을 높이는 작업도 병행했습니다. 마지막으로, 대출 도메인에 특화된 개별 변수 간의 논리적 제약 조건을 확인하여 실제 업무에서 발생하는 값의 범위와 규칙을 합성 데이터 생성 과정에 반영합니다. 앞의 작업들은 생성된 합성 데이터의 현실성을 높이고, AI 모델이 실제 비즈니스 상황을 더 잘 이해하도록 돕습니다.
2. Embedding to Knowledge Base
RAG(Retrieval-Augmented Generation) 방식 도입
대출 상품 추천 및 상담에 특화된 AI 에이전트는 고객과 금융사 사이의 효과적인 소통을 지원해야 합니다. 특히 카카오페이와 연동된 금융사의 다양한 대출 상품을 개별적인 고객의 금융 상황에 맞춰 정확하게 연결하는 것이 중요합니다.
대출 상품의 상세 조건은 빠르게 변동하며, 고객의 마이데이터, 대출 관련 데이터, 앱 내 행동 데이터 역시 끊임없이 업데이트됩니다. 이러한 변화하는 데이터를 모델에 직접 반영하기 위한 파인튜닝은 비용 효율성이 낮습니다. 따라서, 대출 상품과 고객 관련 정보가 업데이트될 때마다 외부 지식 베이스를 최신 상태로 유지하는 RAG(Retrieval-Augmented Generation) 방식을 채택했습니다. 이를 위해 변화하는 정보를 압축적인 형태의 임베딩 벡터로 변환하는 과정이 필요합니다.
효율적인 임베딩을 위한 청킹(Chunking)
금융사의 대출 상품과 고객 정보를 직접 임베딩하는 대신, 중간 단계에 청킹(Chunking) 과정을 도입했습니다. 청킹을 통해 얻는 이점은 다음과 같습니다.
- 트랜스포머 모델 기반의 임베딩 모델은 입력 길이에 제한이 있으므로, 긴 텍스트 데이터를 분할해야 합니다.
- 테이블 형태의 데이터 내 임베딩 벡터가 표현하는 의미론적 관련성을 유지하는 것이 중요합니다. 청킹 단위를 적절히 조정하여 의미론적 맥락을 보존할 수 있습니다.
- 외부 지식 베이스를 활용하는 RAG 시스템의 효율성과 정확도를 높여 고객과의 원활한 소통을 가능하게 합니다.
벡터 스토어(Vector Store)를 활용한 지식 베이스 구축
청킹된 데이터는 LLM을 활용하여 임베딩됩니다. 생성된 Dense 벡터 정보를 효율적인 지식 베이스로 활용하기 위해 벡터 스토어(Vector Store)에 저장해야 합니다. 이때, 방대한 고객 임베딩 정보를 실시간으로 검색하고, 고객 임베딩 데이터 크기의 큰 변동성을 유연하게 처리할 수 있는 솔루션이 필요한데요. 특별한 인프라 관리 없이 고객 임베딩 데이터 크기에 따른 자동 확장 및 축소 기능을 제공하며, 대량의 임베딩 데이터도 별도의 튜닝 없이 저장 및 검색할 수 있는 OpenSearch Serverless를 도입하여 이러한 요구 사항을 충족했습니다.
3. AI 에이전트: 개인 맞춤형 대출 추천 및 상담 AI 에이전트
싱글 에이전트 아키텍처
저희 팀이 개발하는 AI 에이전트는 대출 상품 추천 및 상담에 특화되어 있는데요. 앞에서는 데이터 생성 단계부터 지식 베이스의 핵심인 고객 및 대출 상품 임베딩 작업은 고품질 챗봇을 위해서 복잡하고 중요한 과정을 설명드렸습니다. 일반적으로는 성능을 모니터링하면서 이슈가 있을 때 정기적인 파인튜닝을 통해 지속적으로 개선하는 것이 이상적이지만, 개발 일정상의 제약으로 인해 RAG 시스템을 채택했습니다. AI 에이전트가 실제 고객과 효과적으로 소통하도록 구축하는 단계를 살펴보겠습니다.
저희 팀은 멀티 에이전트 대신 싱글 에이전트 아키텍처를 선택했습니다. 그 주된 이유는 태스크의 명확성과 단순성 때문입니다. 대출 상품 추천 및 상담은 선형적이고, 명확하게 정의된 프로세스와 규칙(고객 정보 수집 -> 조건 검토 -> 상품 추천 -> 고객 맥락에 맞는 상담)으로 이루어집니다. 싱글 에이전트는 이러한 명확한 절차와 제한된 도구 내에서 효율적으로 작업을 처리할 수 있으며, 별도의 역할 분담이나 복잡한 에이전트 간 협업이 불필요하므로 설계 및 운영이 단순해집니다.
두 번째 이유는 일관된 사용자 경험 제공입니다. 고객의 정보는 세션 기반으로 30일 동안 AI 에이전트에 저장되어 맥락 있는 대화가 가능합니다. 멀티 에이전트 시스템은 에이전트 간 통신, 역할 분담, 정보 공유 등 관리해야 할 요소가 많아 고객에게 혼란을 야기하거나 정보의 중복 또는 누락을 발생시킬 수 있습니다. 반면, 싱글 에이전트는 일관된 페르소나와 대화 흐름을 유지하여 사용자에게 자연스럽고 통일된 경험을 제공할 수 있습니다. 다만 만약 AI 에이전트의 역할이 더 커지거나 다른 금융 서비스와 연계될 경우 이 때는 싱글 에이전트에서 멀티 에이전트로 아키텍처 변경이 필요합니다.
효과적인 소통을 위한 프롬프트 엔지니어링
프롬프트 엔지니어링은 AI 에이전트가 고객의 의도를 정확히 파악하고 적절한 답변을 생성하도록 하는 데 중요한 역할을 합니다. 대출 사용자는 원하는 상품 종류와 관계없이 일반적으로 다음과 같은 유형으로 분류하고 대응할 수 있습니다.
- 신규 대출 희망자: 개인 맞춤형 대출 상품 추천 및 대출 절차 안내
- 기존 대출 갈아타기 희망자: 더 유리한 조건의 상품 비교 정보 제공 및 갈아타기 절차 안내
- 추가 대출 희망자: 추가 대출 가능 여부 및 적합한 상품 추천
- 단순 상품 정보 탐색자: 다양한 대출 상품의 기본 정보 및 조건 안내
유형을 분류한 후 AI 에이전트의 주요 단계별 목표를 다음과 같이 설정했습니다.
- 1단계: 개인 맞춤형 대출 상품 추천 - 고객의 상황과 니즈에 최적화된 상품 제시
- 2단계: 대출 조건 및 금리 비교 정보 제공 - 다양한 상품의 주요 조건들을 명확하게 비교하여 고객의 합리적인 선택 지원
- 3단계: 대출 절차 및 필요 서류 안내 - 복잡한 대출 과정을 쉽고 명확하게 안내하여 고객의 이해도 증진
- 4단계: 전문 상담 연결 유도
- 5단계: 잠재 고객 확보 - 잠재적인 대출 수요를 파악하고 관련 정보 제공
대출 AI 에이전트 개발의 핵심 목표는 개인화된 고객 경험을 제공하는 것입니다. 이를 위해 고객의 마이데이터와 앱 내 행동 데이터를 심층적으로 분석하여 특정 금융 행동을 유도하고, 더 낮은 금리 또는 더 높은 한도의 상품을 이용할 수 있도록 정교한 프롬프트 엔지니어링 작업을 진행합니다. 고객의 정보를 입력받으면, 지식 베이스 내 대출 상품 임베딩 정보를 활용하여 고객에게 적합한 상품들을 실시간으로 필터링합니다. 더 나아가, 고객의 임베딩과 입력된 정보를 종합적으로 분석하여 유사한 금융 특성을 가진 고객 클러스터를 식별하고, 해당 클러스터에 속한 고객들이 특정 금융 행동(예: 특정 신용 관리 습관, 특정 금융 상품 이용 이력 등)을 통해 더 유리한 조건의 대출 상품을 이용할 수 있음을 안내합니다.
고객과의 주요 소통 방식이 음성이라는 점을 고려하여, 추천 우선순위와 상품 개수를 결정하는 것은 프롬프트 엔지니어링 단계에서 중요한데요. 기술적인 효율성과 고객 대화의 명확성을 유지하기 위해, 고객의 신용도를 기준으로 최적의 두 가지 상품을 선정하여 추천하도록 설계했습니다. 각 상품을 추천할 때에는 금리, 한도, 상환 방식 등 주요 조건을 명확하게 비교하여 고객이 쉽게 이해하고 비교할 수 있도록 안내합니다.
지금까지 사용자의 음성을 텍스트로 변환하고, 이 정보를 기반으로 AI 에이전트가 대출 상담하는 과정을 자세히 설명했는데요. 다음장에는 AI 에이전트와 고객 간의 대화에서 마주친 기술적 문제를 푸는 과정을 도레가 설명하겠습니다.
개발 과정에서의 트러블슈팅 사례
안녕하세요, 카카오페이 크레딧클랜의 프론트엔드 개발자 도레입니다. 개발 과정에서 겪었던 주요 기술적 문제 두 가지와 해결 방법을 공유하고자 합니다.
1. 대용량 음성 데이터의 순차적 처리 구현
첫 번째 트러블슈팅 포인트는 서버에서 보내는 대용량 음성 데이터를 효율적으로 처리하기 위한 큐 시스템 구현입니다.
문제 상황
AI 에이전트의 응답 음성 데이터가 크기 때문에 한 번에 전송하고 처리하는 것이 비효율적이었습니다. 이로 인한 지연과 음질 저하 문제가 발생했습니다.
해결책: 큐 기반 오디오 처리 시스템
app/utils/audio.ts
파일에서 다음과 같은 오디오 큐 처리 시스템을 구현했습니다:
let audioQueue: Int16Array[] = [];
let isPlaying = false;
async function processAudioQueue(): Promise<void> {
if (isPlaying || audioQueue.length === 0) return;
isPlaying = true;
const audio = audioQueue.shift();
// 오디오 처리 로직...
// 오디오 재생 완료 시 다음 오디오 처리
source.onended = () => {
isPlaying = false;
resolve();
processAudioQueue();
};
source.start();
}
export async function playAudio(audio: Int16Array): Promise<void> {
audioQueue.push(audio);
await processAudioQueue();
}
이 코드는:
- 새로운 오디오 데이터를 큐에 추가
- 현재 재생 중이 아니라면 큐에서 오디오를 하나 가져와 재생
- 재생이 완료되면 재귀적으로 다음 오디오 처리
이 방식으로 사용자 경험을 방해하지 않으면서 대용량 오디오 데이터를 순차적으로 처리할 수 있었습니다.
2. 무음 감지를 통한 응답 지연 개선
두 번째 트러블슈팅 포인트는 사용자가 말을 멈추었을 때 Amazon Polly의 응답 지연 문제를 해결하기 위한 무음 감지 기능 구현입니다.
문제 상황
사용자가 말을 멈추었는데도 서버에서 이를 인식하지 못해 Amazon Polly에서 음성 변환 응답이 늦게 오는 문제가 있었습니다.
해결책: 무음 감지 기능 구현
app/hooks/useVoiceRecorder/index.ts
파일에서 다음과 같은 무음 감지 기능을 구현했습니다:
workletNode.port.onmessage = (event) => {
if (!recordingStateRef.current.isRecording || /* 기타 조건 확인 */) return;
const audioData = event.data as Int16Array;
// 일정 임계값 이상의 음성 데이터가 있는지 확인
const hasAudio = audioData.some(
(sample: number) => Math.abs(sample) > 100
);
if (hasAudio) {
lastAudioSendTime = Date.now();
const CHUNK_SIZE = 4000;
// 오디오 데이터를 분할하여 전송
for (let i = 0; i < audioData.length; i += CHUNK_SIZE) {
const chunk = audioData.slice(i, i + CHUNK_SIZE);
sendMessage(chunk);
}
}
};
// 무음 감지 및 무음 데이터 전송
setInterval(() => {
const now = Date.now();
const silenceTimeout = 300; // ms
// 마지막 음성 감지 후 일정 시간 이상 무음이 지속되면 무음 데이터 전송
if (now - lastAudioSendTime > silenceTimeout) {
const silence = new Int16Array(2048); // 무음 데이터
sendMessage(silence);
lastAudioSendTime = now; // 중복 전송 방지
}
}, 100);
이 코드는:
- 오디오 샘플에서 일정 임계값(100) 이상의 값이 있는지 확인하여 실제 음성이 있는지 감지
- 마지막으로 음성이 감지된 시간을 기록
- 300ms 동안 의미 있는 음성이 감지되지 않으면 무음 데이터를 서버에 전송
이 무음 감지 메커니즘을 통해 사용자가 말을 멈추었을 때 서버가 이를 빠르게 인식하고, Amazon Polly를 통한 음성 합성 과정을 신속하게 시작할 수 있게 되었습니다. 추가로, 오디오 데이터를 처리할 때 CHUNK_SIZE(4000)로 분할하여 전송함으로써 네트워크 부하를 분산하도록 하였습니다.
마치며

이번 해커톤은 AI와 금융서비스의 결합을 실현시키기 위해 크레딧클랜의 다양한 직군이 모여 치열하게 고민하고 구현해 볼 수 있었던 뜻깊은 시간이었습니다.
- AWS의 다양한 AI 서비스와 Bedrock 기술을 활용하여 사용자에게 자연스러운 상담 경험을 제공했고
- LLM 기반의 데이터 파이프라인과 AI Agent를 통해 개인 맞춤형 금융 서비스를 제공하는 방안을 고민해 보았습니다.
서비스 구현이 마냥 쉽지만은 않았는데요, 1박 2일 동안 모두가 열심히 트러블 슈팅을 하며 서비스를 구현한 것이 해커톤의 매력인 것 같아요. 특히 대출은 가명처리가 필요한 데이터라 LLM이 불가능한 영역이라고만 생각했는데, 합성 데이터를 만들며 새로운 가능성을 본 경험이 즐거웠습니다. 그리고 우리가 만든 서비스를 고도화하여 언젠가는 꼭 출시해보고 싶은 마음도 생겼고요. 앞으로 금융 서비스의 발전을 기대하며, 저희도 카카오페이의 서비스가 발전할 수 있도록 여러 가지 방향으로 고민해 보겠습니다.
지금까지 조엘, 제이코, 그렉, 도레, 핀이었습니다!