한 은행이 대출 승인을 더 빠르게 하기 위해 AI를 사용하고 싶어 했습니다. 제가 NestJS로 그 주변에 구축할 것들
요약
AI 모델 도입 시 발생할 수 있는 통합 문제를 NestJS를 활용해 해결하는 방법을 다룹니다. 모델 장애 시 자동 승인되는 위험을 방지하기 위해 타임아웃 설정, 안전한 폴백(fallback) 경로 구축, 수동 검토 큐로의 라우팅 및 로깅의 중요성을 강조합니다.
핵심 포인트
- AI 모델의 성능보다 모델 주변의 통합 및 예외 처리가 더 중요함
- 모델 호출 시 타임아웃을 강제하여 시스템 전체의 지연 방지
- 실패 시 자동 승인이 아닌 수동 검토 대기열로 라우팅하는 페일 세이프 구축
- 규제 대응을 위해 모든 결정 과정에 대한 상세한 로깅 필수
한 소규모 디지털 은행의 대출 담당자는 데이터 팀이 구축한 새로운 모델에 대해 매우 기대하고 있었습니다. 이 모델은 소득, 소비 패턴, 상환 이력을 바탕으로 1초도 안 되어 대출 신청 점수를 매기고, 자동으로 승인 또는 거절을 결정할 수 있었습니다. 운영 첫 주에는 아주 훌륭하게 작동했습니다. 하지만 두 번째 주, 모델 제공업체에 오후 시간대 장애가 발생했습니다. 해당 시간 동안 제출된 모든 대출 신청은 응답이 오지 않은 채 그대로 멈춰버렸습니다. 일부 고객들은 페이지를 새로고침하고 두 번 제출하기도 했습니다. 즉시 거절되었어야 할 몇몇 신청 건들은 결국 승인되고 말았습니다. 몇 달 전 누군가가 작성했지만 제대로 테스트되지 않았던 폴백 (fallback) 경로가, 점수를 매길 수 없는 모든 항목을 승인하는 것으로 기본 설정되어 있었기 때문입니다.
데이터 팀의 누구도 모델 자체에 잘못을 저지른 것은 아니었습니다. 모델은 정확했습니다. 부족했던 것은 모델 주변의 모든 것, 즉 모델이 느려지거나, 틀리거나, 사용할 수 없거나, 혹은 이토록 중대한 결정에 맹목적으로 신뢰해서는 안 되는 상황이 발생했을 때 어떻게 할지를 결정하는 부분이었습니다.
진짜 문제는 결코 모델이 아니다
은행이 대출 승인이나 사기 점수 산정 (fraud scoring) 같은 업무에 모델을 도입할 때, 실제로 겪는 문제는 AI 문제가 아닙니다. 그것은 통합 (integration) 문제입니다. 모델은 당신이 호출하는 하나의 서비스이며, 다른 모든 서비스와 마찬가지로 느려질 수 있고, 실패할 수 있으며, 확신에 차서 틀릴 수도 있습니다. 중요한 질문은 모델이 똑똑한지 여부가 아닙니다. 모델이 모두가 예상했던 대로 작동하지 않는 순간, 백엔드 (backend)가 무엇을 하느냐 하는 것입니다.
느린 모델이 전체 흐름을 멈추지 못하도록 타임아웃 (timeout) 강제하기
첫 번째 가드레일 (guardrail)은 모델 호출이 결코 무한정 대기 상태로 머물지 않도록 보장하는 것입니다. 모델 제공업체가 느려지거나 다운된다면, 요청은 빠르게 실패 (fail fast)하고 안전한 기본값으로 폴백 (fallback)되어야 하며, 고객이 로딩 화면만 바라보게 해서는 안 됩니다.
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom, timeout, catchError } from 'rxjs';
...
여기서 폴백 (fallback)은 조용한 승인이 아니라 명시적인 에러라는 점에 주목하세요. 다음에 어떤 일이 일어나든, 서비스 호출이 실패했다고 해서 대출을 승인하는 것으로 기본값을 설정하는 것은 그 자체로 결코 용납될 수 없는 동작입니다.
대출 결정에서 페일 세이프 (fail safe)가 실제로 의미하는 바 결정하기
타임아웃 (timeout)이나 실패가 감지되면 다음 단계에서 무언가 조치가 취해져야 하며, 이토록 중요한 결정의 경우 그 조치가 결코 자동 승인이 되어서는 안 됩니다. 합리적인 페일 세이프 (fail safe) 경로는 대신 신청 건을 수동 검토 대기열 (manual review queue)로 라우팅하는 것입니다.
async handleScoringFailure(applicationId: string) {
await this.reviewQueueService.enqueue({
applicationId,
...
이렇게 하면 고객에게 정직하게 상황을 알릴 수 있으며, 기술적인 실패가 아무도 의도하지 않은 금융 결정으로 조용히 변질되는 것을 방지할 수 있습니다.
나중에 설명할 수 있도록 모든 결정 사항을 로깅 (logging)하기
은행은 결국 특정 고객이 왜 승인되었는지, 거절되었는지, 또는 플래그 (flag)가 지정되었는지에 대해 몇 달 후 혹은 규제 기관에 설명해야 할 상황이 생깁니다. 이는 모든 스코어링 (scoring) 결정이 모델의 출력값 및 기반 데이터와 함께 단순히 실행되고 버려지는 것이 아니라 기록되어야 함을 의미합니다.
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn } from 'typeorm';
@Entity('loan_decisions')
...
이러한 체계가 갖춰지면, 1초 미만으로 내려진 결정이라도 나중에 완전히 재구성하여 설명할 수 있습니다. 이는 거의 다른 어떤 종류의 애플리케이션보다 은행 업무에서 훨씬 더 중요한 요소입니다.
가장 중요한 결정에는 인간을 루프에 포함시키기 (human in the loop)
모든 결정에 사람이 검토할 필요는 없지만, 실제적인 결과가 따르는 결정—거액의 대출, 경계선에 있는 점수, 거절에 대해 이의를 제기하는 고객 등—은 결코 모델 단독으로 확정되어서는 안 됩니다. NestJS는 이러한 게이트(gate)를 강제할 수 있는 깔끔한 환경을 제공합니다. 즉, 모델이 우연히 출력한 결과에 따르는 것이 아니라, 은행이 실제로 동의하는 규칙에 기반하여 특정 결과를 고객에게 직접 전달하는 대신 검토 대기열(review queue)로 라우팅하는 체크 과정을 구현할 수 있습니다.
더 큰 그림 (The bigger picture)
NestJS가 AI 모델의 정확도를 높여주는 것은 아니며, 결코 그렇게 시도해서도 안 됩니다. NestJS가 제공하는 것은 모델 주변의 구조입니다. 타임아웃(timeouts)을 강제할 수 있는 곳, 페일 세이프(fail safe)가 실제로 무엇을 의미하는지 결정할 수 있는 곳, 나중에 설명할 수 있도록 모든 결정을 로그(log)로 남기는 곳, 그리고 검토가 필요한 결정에 대해 사람이 검토하도록 요구하는 곳입니다. 이러한 구조가 바로 대출 승인과 같이 중대한 사안에 AI 모델을 사용할 수 있을 만큼 안전하게 만드는 핵심입니다.
만약 여러분의 팀이 실제 돈이나 실제 고객과 관련된 프로세스에 AI를 도입하려 한다면, 그 주변에 적절한 가드레일(guardrails)을 구축하는 방법에 대해 기꺼이 논의해 드릴 수 있습니다.
저는 백엔드 소프트웨어 엔지니어 Peace Melodi입니다. 여러분의 비즈니스가 강력한 확장성(scalability)과 보안(security)을 갖춘 상태에서, 시스템 중단 없이 수백만 명의 사용자를 편안하게 처리하며 크게 성장하기를 원하신다면 언제든 연락해 주세요.
LinkedIn: https://www.linkedin.com/in/melodi-peace-406494368
GitHub: https://github.com/PeaceMelodi
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기