[프로젝트 기록] 보이스피싱 대응 훈련 백엔드(청음) 개선기

김지혁·2026년 2월 15일

프로젝트

목록 보기
1/5
post-thumbnail

[프로젝트 기록] 보이스피싱 대응 훈련 백엔드(guardian-server) 개선기

데이콘(공모전 주최) 링크 : https://dacon.io/competitions/official/236666/overview/description
공용문서 링크 :
https://www.notion.so/2fd189dee3ba80fb8e4ed264bd944ea2
깃헙 링크 :
https://github.com/0798JiHyuk/-repository
(추후 조직링크로 변경..)

한 줄 소개

실전형 보이스피싱 대응 학습을 위해, 숏폼/롱폼 훈련 결과를 자동 집계하고 주간 리포트까지 생성하는 백엔드 기능을 고도화했다.

프로젝트 배경

이번 작업의 목표는 크게 두 가지였다.
1. 사용자 훈련 데이터를 끝나자마자 요약해 리포트로 제공하기
2. 롱폼 시뮬레이터 답변 품질을 높이기 위해 대화 맥락(history)을 안정적으로 전달하기

기존에는 weekly_reports 조회 API는 있었지만, 실제 리포트 생성 로직이 비어 있어 체감 가능한 피드백 경험이 약했다. 또한 롱폼 응답 생성 시 직전 맥락 반영이 제한적이라 답변 일관성이 흔들리는 문제가 있었다.

이번에 구현한 핵심 작업

1) 주간 리포트 생성 서비스 구현

파일: src/services/reports.service.ts

기존 export const reportsService = {}; 상태에서 실제 생성 로직을 완성했다.

  • 최근 7일 기준 기간 계산 (from_date, to_date)
  • training_results 기준 훈련 횟수/평균 점수/정확도 집계
  • 모드별 취약 유형 추출
    • short: training_shorts.category_code
    • long: training_scenarios.category
  • OpenAI Responses API를 호출해 한국어 요약 생성
    • one_line_feedback
    • weak_patterns[]
    • action_guides[]
  • weekly_reports upsert 처리 (ON CONFLICT)
  • FK 이슈(에러코드 23503) 발생 시 top_wrong_type_code=null로 재시도하는 안전장치 추가

핵심 포인트는 "집계 SQL + AI 요약 + DB upsert"를 한 사이클로 묶어, 조회 전에 데이터가 만들어지는 구조를 만든 것이다.

2) 훈련 종료 시 자동 리포트 생성 연결

파일:

  • src/routes/trainingShort.routes.ts
  • src/routes/trainingLong.routes.ts

숏폼/롱폼 세션 finish 시점에 generateWeeklyReport(userId, mode)를 호출하도록 연결했다.

  • 학습 직후 리포트 최신화
  • 리포트 생성 실패가 학습 완료 응답 자체를 막지 않도록 try/catch + warn 처리

즉, 사용자 경험 관점에서 "훈련 완료 -> 바로 리포트 확인" 흐름이 자연스럽게 이어지게 했다.

3) 리포트 조회 API 안정성 개선

파일: src/routes/reports.routes.ts

/api/reports/weekly에서 다음을 개선했다.

  • 정렬 기준을 generated_at DESC로 변경해 가장 최근 생성본을 확실히 반환
  • 요청/결과 로그 추가 ([reports/weekly] request/result)
  • 예외 발생 시 503 + 구조화된 에러 코드(REPORT_QUERY_FAILED) 반환

운영 중 장애 분석을 빠르게 하려는 목적이 컸다.

4) 롱폼 대화 맥락 전달(History) 개선

파일:

  • src/routes/trainingLong.routes.ts
  • src/services/ai.service.ts
  • src/services/simulator.service.ts
  • scripts/simulator_bridge.py

변경 내용:

  • 서버가 longform_messages에서 기존 대화를 조회해 history 배열로 구성
  • aiGenerateLongformReply 및 시뮬레이터 클라이언트 계층에 history 파라미터 추가
  • Python 브리지에서 받은 history를 시뮬레이터 메시지 컨텍스트로 재구성

효과:

  • 턴이 누적되어도 답변 문맥 일관성 향상
  • 역할(role) 매핑 정리(ai -> assistant)로 모델 입력 안정화

5) 텍스트 인코딩/음성 생성 품질 보강

파일:

  • feedback_agent.py
  • simulator_test_2.py

주요 개선:

  • UTF-8 안전 정제 함수 추가로 깨진 문자열/서로게이트 문자 대응
  • TTS 입력 텍스트 전처리 강화(기호 정리, 문장부호 정돈)
  • 프롬프트 메시지를 JSON 형태로 stderr 출력해 디버깅 가시성 확보

트러블슈팅에서 배운 점

  1. 리포트 기능은 "조회 API"만 만들면 끝이 아니었다.
    실제 생성 트리거를 사용자 행동 지점(finish)에 붙여야 데이터가 살아 움직인다.

  2. AI 요약은 항상 실패 가능성을 전제로 설계해야 한다.
    API 키 누락, 파싱 실패, DB 제약 이슈를 각각 분리해 fallback/재시도를 넣어야 운영이 안정된다.

  3. 대화형 시스템에서 문맥(history)은 품질의 핵심이다.
    한 턴의 입력만 보내는 구조보다, 정돈된 대화 이력을 전달할 때 응답 품질이 확실히 좋아진다.

현재 아키텍처 흐름(요약)

  1. 사용자가 숏폼/롱폼 훈련 진행
  2. 세션 종료 API 호출
  3. 서버가 최근 7일 학습 데이터를 집계
  4. AI가 취약 패턴/행동 가이드를 요약
  5. weekly_reports upsert
  6. /api/reports/weekly에서 최신 리포트 조회

기술 스택과 선택 이유

사용 언어

  • TypeScript (Node.js): API 서버의 핵심 로직(라우팅, 서비스, DB 연동)을 타입 안정성 있게 운영하기 위해 선택했다. DTO/응답 스키마가 많은 백엔드에서 런타임 오류를 줄이고 리팩터링 안정성을 높이는 데 유리했다.
  • Python: 시뮬레이터 브리지와 피드백/음성 관련 실험 코드에 사용했다. AI/오디오 처리 라이브러리 생태계가 강하고, 프로토타이핑 속도가 빨라 모델 연동 실험에 적합했다.

사용 프레임워크/라이브러리

  • Express: REST API를 빠르게 구성하고 미들웨어 기반으로 인증, 에러 핸들링, 라우트 분리를 명확히 하기 쉬워서 사용했다.
  • PostgreSQL(pg): 훈련 결과 집계, 주간 리포트 upsert, 조인 기반 통계 쿼리가 핵심이라 관계형 DB가 적합했다.
  • Zod: 요청 유효성 검증을 스키마로 명시해 입력 신뢰도를 높이고, 잘못된 요청을 초기에 차단하기 위해 사용했다.
  • express-session: 로그인 기반 사용자 식별(req.session.user.id)이 필요해 세션 인증 구조를 적용했다.
  • AWS S3 SDK(@aws-sdk/client-s3, @aws-sdk/s3-request-presigner): 음성 파일 업로드/조회 URL을 안전하게 관리하기 위해 presigned URL 방식을 사용했다.
  • OpenAI API(Responses/Chat): 주간 리포트 요약 생성, 대화형 시뮬레이터 응답, 피드백 분석 등 생성형 AI 기능을 백엔드 서비스 계층에 통합했다.

백엔드 관점에서의 선택 포인트

  1. 유지보수성: TypeScript + 계층형 구조(routes/services/repositories)로 기능 확장 시 영향 범위를 예측하기 쉬웠다.
  2. 운영 안정성: 리포트 생성 실패를 업무 실패로 전파하지 않고 fallback/재시도를 넣어 사용자 플로우를 보호했다.
  3. 데이터 신뢰성: PostgreSQL 집계 + ON CONFLICT upsert로 주간 리포트 생성의 중복/정합성 문제를 줄였다.
  4. 확장성: Express 라우트 분리와 서비스 모듈화 덕분에 숏폼/롱폼/리포트/업로드 기능을 독립적으로 진화시키기 좋았다.
  5. 실험 속도: AI 실험 영역은 Python으로, 운영 API는 TypeScript로 분리해 개발 속도와 안정성의 균형을 맞췄다.

마무리

이번 작업으로 guardian-server는 단순 훈련 제공 백엔드에서, "학습 결과를 자동으로 요약하고 다음 행동까지 제시하는 피드백 백엔드"로 한 단계 올라갔다.

다음 단계로는 리포트 정확도 개선(카테고리 정규화), 장기 추세 리포트(4주/8주), 사용자별 개인화 코칭 템플릿을 확장해볼 계획이다.

profile
스위트아메리카노

0개의 댓글