← 전체 프로젝트

01. 한 줄로 보는 JB Silver Connect

JB Silver Connect

60세 이상 고객이 말이나 글로 AI 금융 도우미와 상담하고, 번호표 · 지점 찾기 · 법인 서류 안내를 받아 창구와 호출 화면까지 한 흐름으로 이어지는 서비스 — JB금융 해커톤 데모

기간
2026-06-11 ~ 2026-06-13
팀 · 역할
4명 · 백엔드 · 프론트 3종 구현
  • Python 3.11
  • FastAPI
  • Pydantic 2
  • Gemini
  • Groq
  • Next.js 16 × 3
  • Web Speech API
  • import-linter

↓ 스크롤 또는 ← → 키로 넘기기

02. 설계 원칙 - 3일 안에 5개 컨텍스트, 섞이지 않게

지점 · 상담 · 법인 · 대기열 · 예약 다섯 기능을 3일 안에 만들었습니다. 빠를수록 계층이 섞이기 쉬워, 모든 기능을 같은 모양으로 쌓고 방향을 검사로 강제했습니다.

문제
짧은 기간에 기능을 빠르게 붙이면 라우터에 로직이 쌓이고, 기능끼리 서로의 내부를 직접 부르게 된다
선택
모든 컨텍스트를 domain → app → adapter로 나누고 import-linter layers 계약으로 강제. 컨텍스트끼리는 adapter 계층의 포트 하나로만 연결
대가
파일 수가 많아지고(추적 파일 277개), 코드가 장황해진다
효과
Mock을 실제 구현으로 바꿀 때 교체 지점이 명확하다 — 상담 → 대기열 등록도 포트 하나로 연결
5개 컨텍스트와 레이어 방향 (도식)
5개 컨텍스트와 레이어 방향 (도식)

왜 이 선택인가 — 버린 대안

  • 라우터에 로직을 직접 넣는 단일 구조
    3일 뒤 실제 은행 시스템으로 바꾸려면 전부 다시 짜야 한다

컨텍스트를 같은 모양으로 쌓는 이유

다섯 기능이 모두 같은 층 구조(바깥 연결부 · 업무 규칙 · 핵심 규칙)를 가지면, 새 기능을 만들 때도 어디에 무엇을 둘지 고민할 필요가 없습니다. 검사기가 층을 거꾸로 오르는 코드를 잡아냅니다.

근거: setup.cfg — import-linter 계약 · jb/ARCHITECTURE.md

03. LLM 폴백 체인 - 시연 도중 멈추지 않게

무료 API 키가 없거나 한도를 넘으면 시연 도중 AI가 말을 멈춥니다. 어댑터 목록을 앞에서부터 차례로 시도하고, 전부 실패해도 Mock이 답하게 했습니다.

문제
해커톤 시연은 무료 API 한도와 네트워크에 기대야 한다 — 한 번 끊기면 발표가 멈춘다
선택
FallbackLlmAdapter가 Gemini → Groq → Mock 순으로 시도. 호출하는 쪽은 LlmPort 하나만 안다. 같은 패턴을 지도에도 재사용(네이버 → Mock)
대가
마지막 오류만 다시 던지고 앞선 실패는 기록하지 않는다. 외부 클라이언트가 동기 호출이라 이벤트 루프를 막을 수 있다
효과
키가 하나도 없어도 AI 상담 흐름이 끝까지 돈다
음성 · 글로 대화하는 AI 도우미
음성 · 글로 대화하는 AI 도우미

왜 이 선택인가 — 버린 대안

  • 호출부에서 키 유무로 분기
    기능마다 if 문이 퍼진다 — 분기는 조립 지점 한 곳에서만

폴백 체인이란?

전화가 안 되면 문자를, 문자도 안 되면 메모를 남기는 식으로 연락 수단을 순서대로 준비해 두는 방식입니다. 앱은 "연락해"라고만 요청하고, 어떤 수단이 쓰였는지는 신경 쓰지 않습니다.

근거: fallback_llm_adapter.py · core/di.py — 조립 지점

04. Mock 어댑터 - 은행 시스템 없이 끝까지

해커톤에서는 실제 계좌 · 고객 DB · 외부 API에 접근할 수 없습니다. 포트마다 Mock 구현을 끼워, 설정 파일을 비워 두어도 전체 흐름이 돌게 했습니다.

문제
실제 은행 데이터 없이 상담 → 번호표 → 창구 → 호출 전체를 보여 줘야 한다
선택
고객 · 계좌 · 지도 · 법인 안내 · 번호표 · 저장소 포트마다 Mock 구현. "실 서비스 전환 시 유스케이스 코드 변경 0"을 원칙으로
대가
저장소가 모두 메모리라 서버를 다시 켜면 데이터가 사라진다. 법인 안내 데이터는 손으로 고른 것
효과
.env를 비워 두어도 전체 흐름 동작 — 이 포트폴리오의 캡처도 키 없이 로컬에서 찍었다
포트별 실제 구현과 Mock (도식)
포트별 실제 구현과 Mock (도식)

왜 이 선택인가 — 버린 대안

  • 실제 DB · API부터 연결
    3일 안에 접근 권한을 얻을 수 없다 — 다음 단계로 남김

Mock 어댑터란?

영화 촬영용 소품 은행처럼 모양과 사용법은 진짜와 같지만 속은 가짜인 부품입니다. 나중에 진짜 부품으로 갈아 끼워도 나머지는 고칠 필요가 없습니다.

근거: mock_customer_directory.py

05. 화면 3개 - 고객 · 창구 · 호출

고객 휴대폰, 직원 단말, 대기실 모니터는 사용자도 화면 요구도 다릅니다. Next.js 앱 3개가 같은 API를 바라보게 나눴습니다.

문제
한 앱에 세 사용자를 담으면 화면 크기 · 글자 크기 · 권한이 모두 뒤섞인다
선택
고객(www) · 창구(teller) · 호출(display) 분리. 대기열은 대기 → 현장 도착 → 호출로 바뀌고, 30분 미도착 · 호출 후 1분이면 자동 파기. 법인 창구 번호는 B 접두
대가
WebSocket 대신 폴링(창구 5초 · 호출 2초)이라 반영이 최대 5초 늦다. 설정이 세 벌로 중복
효과
상담 한 건이 창구 브리핑 카드와 호출 화면까지 이어진다 (로컬 시연 확인)
고객 앱 — 말로 시작하는 AI 상담
고객 앱 — 말로 시작하는 AI 상담
창구 단말 — AI가 정리한 방문 내용
창구 단말 — AI가 정리한 방문 내용
대기실 호출 화면
대기실 호출 화면

왜 이 선택인가 — 버린 대안

  • 한 앱 안에서 경로로 분리
    사용자 · 화면 크기가 전혀 다르다 — 각자 따로 배포할 수 있게

같은 명부를 보는 세 화면

은행 번호표 시스템처럼 손님 발권기, 직원 단말, 대기실 전광판을 따로 두되 모두 같은 중앙 명부(API)를 들여다보는 구조입니다.

근거: queue_entry_entity.py — 상태 전이 · 자동 파기

06. 시니어 UX와 창구 브리핑

고령 고객은 작은 글씨와 타이핑이 어렵고, 직원은 긴 설명을 한눈에 파악하기 어렵습니다. 화면은 크게 · 말로, 상담은 요약 카드로 창구에 넘겼습니다.

문제
60세 이상 고객에게 일반 금융 앱의 글자 크기와 입력 방식은 장벽이다
선택
기본 글자 18px · 포커스 테두리 3px · 한국어 음성 인식. 답변은 3문장 이내 존댓말, 한 번에 한 가지. 대화를 목적 · 금액 · 서류 · 조언 · 창구 종류의 JSON 브리핑으로 구조화, 파싱 실패 시 안전한 기본값
대가
안내 버튼은 단순 키워드 매칭이고, 음성 인식은 지원하지 않는 브라우저에서 꺼진다
효과
말로 시작한 상담이 요약 카드로 창구까지 한 흐름으로 이어진다 (사용성 조사는 다음 단계)
말로도 글로도 — 크게 보이는 상담 화면
말로도 글로도 — 크게 보이는 상담 화면
창구로 넘어간 AI 브리핑 카드
창구로 넘어간 AI 브리핑 카드

왜 이 선택인가 — 버린 대안

  • 긴 AI 답변을 그대로 전달
    고령 고객도 직원도 한 번에 읽기 어렵다 — 짧게, 구조화해서

브리핑 카드

은행 직원이 "천천히, 크게, 하나씩" 응대하는 방식을 화면과 AI 말투에 옮겼습니다. 상담 내용은 요약 메모지로 만들어 창구 직원에게 먼저 넘깁니다.

근거: handoff_interactor.py — 브리핑 구조화 · useSpeechRecognition.ts

07. 결과와 회고

개발 기간
3일
컨텍스트
5개 (헥사고날)
화면
고객 · 창구 · 호출 3종
외부 키 없이
전체 흐름 동작

아쉬운 점 · 다음에 할 것

  • 커밋 메시지 대부분이 "." — 무엇을 왜 바꿨는지 git에 남지 않았다
  • 폴백 체인이 앞선 실패를 기록하지 않아, 어떤 모델이 답했는지 알 수 없다
  • 설계 문서의 컨텍스트 목록이 실제 코드와 어긋난 채 남았다