FitBack 프로젝트 이미지
← SELECTED PROJECTS

FitBack

상담 후 미등록 고객의 이탈 사유를 AI로 분석하고 재연락 시점과 메시지를 제안하는 피트니스 센터 후속관리 서비스

TECH STACK
Java 21Spring BootPostgreSQLRedisAWS (EC2, RDS)DockerGitHub ActionsNginxFastAPIOpenAINeo4j
01

IMPACT

02

BACKGROUND

헬스장·PT 상담 및 운영 경험자 5명을 인터뷰한 결과, 상담 기록의 번거로움과 재연락 우선순위 기준의 부재로 미등록 잠재고객이 관리에서 누락되는 문제를 확인했습니다.

핵심 기능

AI 상담 분석재연락 우선순위맞춤 메시지 초안후속관리 전환 리포트

주요 경험
  1. 모호한 화면 표현값을 데이터 출처·상태·갱신 트리거로 구체화
  2. PM·Design·Frontend·AI 간 API 계약과 업무 흐름 정렬
  3. 외부 AI 장애를 격리하는 비동기 분석 생명주기 설계
  4. 상태 전이·DB 제약·잠금을 통한 고객 데이터 정합성 보장
03

ARCHITECTURE

01
System Architecture

Spring Boot·FastAPI와 AWS 인프라, AI 서비스 연동 구조

FitBack 시스템 아키텍처 다이어그램
04

CONTRIBUTIONS

01

DOMAIN MODELING

화면 표현값을 데이터 규칙으로 구체화

AI 미전환 사유의 판단 근거, 후속 연락 우선순위, Next Best Action 갱신 시점처럼 모호했던 요구를 데이터 출처·상태·트리거·이력 보존 규칙으로 변환했습니다.

02

SPECIFICATION WORKFLOW

분야 간 소통을 실행 가능한 계약으로 정렬

PM·Design·Frontend·AI가 서로 다른 기준을 참조하지 않도록 Issue·화면·시퀀스·API·스키마의 우선순위를 정하고, AI coding agent도 같은 SSOT와 충돌 보고 규칙을 따르게 했습니다.

03

ASYNC AI LIFECYCLE

상담 저장과 AI 분석의 생명주기 분리

트랜잭션 커밋 이후 @Async로 FastAPI 분석을 실행하고 PROCESSING·COMPLETED·FAILED 상태를 제공해, AI 장애와 지연이 상담 등록을 막지 않도록 구성했습니다.

04

DATA INTEGRITY

고객 라이프사이클의 상태 정합성 보장

문의→상담→AI 분석→후속 연락→재상담·등록 흐름을 상태 전이로 연결하고, 비관적 잠금과 PostgreSQL 제약으로 중복 전환과 복수 활성 후속관리를 방지했습니다.

05

TROUBLE SHOOTING

01

REQUIREMENT CLARIFICATION

모호한 화면 표현값을 상태와 트리거 계약으로 변환

P
Problem

B2B 화면에 많은 정보를 담는 과정에서 AI 미전환 사유의 근거, 후속 연락 우선순위, Next Best Action의 동기화 시점이 명확하지 않아 분야마다 다르게 해석했습니다.

A
Analyze

화면 단위 요청을 그대로 구현하면 변경 때마다 API와 AI 계약이 흔들렸습니다. 각 표현값마다 원천 데이터·계산 책임·갱신 이벤트·이력 보존 여부를 먼저 확정해야 했습니다.

A
Action

PM과 화면 의도를 확인한 뒤 Issue·디자인·시퀀스·API·스키마 순으로 계약을 정렬하고, 모순은 선택지와 영향 범위를 문서화해 결정 이후에만 구현했습니다.

R
Result

Next Best Action 갱신을 신규 상담 분석·재상담 분석·명시적 재생성으로 한정하고, 단순 정보 수정과 메시지 작업이 불필요한 재분석을 만들지 않도록 분리했습니다.

02

FAILURE ISOLATION

외부 AI 장애가 상담 등록을 실패시키지 않도록 분리

P
Problem

상담 저장 트랜잭션 안에서 FastAPI와 LLM 응답을 기다리면 지연이나 장애가 고객·상담 데이터 저장까지 롤백시킬 수 있었습니다.

A
Analyze

동기 호출, 커밋 전 비동기 호출, 커밋 후 이벤트 실행을 비교했습니다. 핵심 데이터의 영속화를 먼저 보장하면서 AI 결과는 최종 일관성으로 처리하는 방식을 선택했습니다.

A
Action

ApplicationEventPublisher와 AFTER_COMMIT 리스너, @Async를 조합하고 분석 상태를 PROCESSING·COMPLETED·FAILED로 관리했습니다.

R
Result

상담 등록은 AI 완료를 기다리지 않고 201 Created를 반환하며, AI 실패 시에도 상담 데이터는 유지하고 FAILED 상태를 통해 프론트가 결과를 처리하도록 했습니다.

03

CONCURRENCY CONTROL

동일 문의가 두 개의 상담으로 전환되는 경쟁 조건 방지

P
Problem

상담 전환 버튼을 빠르게 누르거나 동일 문의에 요청이 동시에 들어오면 상태 확인을 모두 통과해 상담이 중복 생성될 가능성이 있었습니다.

A
Analyze

애플리케이션의 선조회만으로는 경쟁 조건을 막을 수 없었습니다. 충돌 빈도보다 중복 생성의 비용이 커서 동일 inquiry row를 직렬화하는 비관적 잠금을 선택했습니다.

A
Action

PESSIMISTIC_WRITE로 문의를 조회하고 잠금 획득 후 CONVERTED 상태를 다시 검사했으며, 고객·상담 식별자에는 DB Unique Constraint를 추가 방어선으로 뒀습니다.

R
Result

두 트랜잭션을 동시에 실행한 PostgreSQL 통합 테스트에서 두 번째 요청이 첫 커밋까지 대기한 뒤 CONVERTED 상태를 확인하는 것을 검증했습니다.