SK Networks Family AI 캠프 팀 프로젝트

WorkShield Web — 실패 경계를 설계한 AI 서비스 백엔드

계약서 비교 MCP를 FastAPI 웹 API와 LLM 설명 계층, AWS 배포 환경에 연결했습니다. 검토 상태와 질문 대상·출처를 백엔드가 관리하고, API와 배포 구조의 자동 검증을 구성했습니다.

30초 요약

맥락
사용자가 계약서를 올리고 오래 걸리는 검토의 진행과 근거를 확인할 수 있도록 선행 비교 엔진을 웹 서비스 흐름에 연결한 출시 전 5인 팀 프로젝트입니다.
문제
외부 서비스를 거치는 검토에서 같은 요청의 반복, 취소와 완료의 경쟁, 서버 중단과 부분 응답 실패를 상태로 다뤄야 했습니다.
판단
백엔드가 검토 상태를 관리하고, 질문 대상과 실제 출처를 모델 응답에 맡기지 않도록 했습니다. 중복 요청과 동시 변경은 서로 다른 저장 규칙으로 방어했습니다.
역할
5인 팀에서 백엔드 API와 AI 서비스 경계, AWS 인프라와 배포 자동화를 담당했습니다.
결과
검증된 근거의 실제 ID를 백엔드가 결합하도록 바꾸고, 고정 합성 fixture 16회 최종 gate를 통과한 모델을 답변·Suggestions 후보로 선정했습니다.
검증
API와 연동 테스트, 화면 빌드, 컨테이너 이미지 빌드와 배포 설정 검사를 자동화했습니다.
한계
파일형 데이터베이스와 단일 실행 프로세스·단일 서버를 사용하는 출시 전 구조로, 여러 서버의 동시 실행과 중단 지점 자동 재개를 지원하지 않습니다.
증명하는 역량
오래 걸리는 AI 작업의 상태와 모델·배포 영역의 책임을 백엔드에서 구분한 역량을 보여줍니다.

검증과 근거

확인 가능한 근거

주장의 적용 범위와 측정 조건을 함께 표시합니다.

  1. 코드비동기 검토 상태

    Review Aggregate는 QUEUED, REVIEWING, COMPLETED, FAILED, CANCELLED, EXPIRED 상태와 단조 진행률 규칙을 관리한다.

    중단된 작업은 중단 지점부터 재개하지 않고 재시도 가능한 실패로 정리한다.원문 근거 보기
  2. 코드LLM 출력과 출처 무결성

    Suggestions 모델은 닫힌 집합의 근거 종류만 선택하고, 실제 출처 ID는 백엔드가 현재 요청의 검증된 근거에 결합한다.

    source key 선택 자체의 정확성이나 환각 제거를 보장하지 않는다.원문 근거 보기
  3. 코드인프라와 배포 권한

    AWS CDK와 GitHub Actions로 배포를 구성하고, GitHub OIDC 배포 역할과 고권한 인프라·비밀·RunPod 수명주기를 분리했다.

    단일 EC2 구조이며 고가용성·무중단 배포로 표현하지 않는다.원문 근거 보기

사용 기술

구현에 직접 연결된 기술

보조 기술 보기
  • SQLAlchemy
  • SSE
  • Pydantic
  • SQLite
  • vLLM
  • React
  • TypeScript
  • Docker Compose
  • GitHub Actions

법률 판단을 자동화하는 서비스가 아니라, 표준계약서 대비 검토 후보와 근거를 사람이 확인할 수 있도록 기존 MCP를 웹 사용자 흐름에 연결한 프로젝트입니다.

1. MCP를 서비스로 연결하며 생긴 문제

선행 프로젝트인 WorkShield MCP는 문서 파싱, 조항 검색·재정렬, 대응 상태 분류와 법령 조회를 결정론적으로 수행합니다. 이번 프로젝트에서는 이 엔진을 사용자가 계약서를 업로드하고 검토 진행 상황과 결과를 확인한 뒤, 근거 범위 안에서 질문할 수 있는 웹 서비스로 연결했습니다.

서비스 계층이 추가되면서 검색 품질과는 다른 문제가 생겼습니다.

따라서 핵심 메시지를 새로운 RAG 엔진 개발이 아니라 비동기 작업의 상태 일관성외부 AI 구성 요소의 책임 경계에 두었습니다.

2. 역할과 프로젝트 경계

직접 담당

  • FastAPI API 기반과 MCP Client·LLM provider 추상화
  • Review 상태 머신, 진행률과 동시 변경 처리
  • 익명 세션·임시 파일 수명주기와 안전한 로그 정책
  • Chat·Suggestions의 근거 제한과 SSE 스트리밍
  • AWS CDK 인프라와 GitHub Actions 배포·롤백

  • React 웹 애플리케이션과 전체 사용자 흐름
  • 프로젝트 요구사항·데모·문서화 협업

외부 구성

  • 선행 프로젝트의 WorkShield MCP가 문서 처리·검색·상태 분류 담당
  • RunPod가 embedding·rerank와 vLLM 모델 실행 담당
  • CloudFront·S3·EC2·SSM 등 AWS 관리형 기능 사용

3차 프로젝트에서 확인한 RRF 점수 계약 오류와 골든 데이터 F1은 MCP의 결과입니다. Web Platform에서는 이를 새 성과로 중복 계산하지 않고, MCP 결과를 API 상태와 사용자용 응답으로 연결한 범위만 다룹니다.

3. 시스템 책임 경계

WorkShield Web 시스템 책임 경계브라우저 요청이 CloudFront를 거쳐 정적 웹 또는 EC2의 FastAPI로 전달되고 API가 SQLite, MCP와 RunPod vLLM을 조율하는 구조

사용자 브라우저

CloudFront

Private S3
React Web

EC2 Nginx

FastAPI API

SQLite
세션·Review 상태

WorkShield MCP
검색·분류·법령

RunPod vLLM
답변·Suggestions

RunPod
embedding·rerank

API 내부에서는 Router가 HTTP 입출력을, Application Service가 사용 사례와 트랜잭션을, Domain이 상태 전이 규칙을 담당하도록 나눴습니다. MCP와 LLM을 호출하는 동안에는 DB 트랜잭션을 열어두지 않고, 외부 응답을 받은 뒤 현재 상태를 다시 확인합니다.

4. 비동기 Review 상태와 진행률

검토 상태는 다음과 같이 구분했습니다.

WorkShield Review 상태 전이검토가 생성된 뒤 실행·완료·실패·취소 상태를 거쳐 만료되는 흐름

검토 생성

실행 시작

MCP OK 결과 확정

취소

취소

실행 실패·서버 중단 정리

실행 실패·서버 중단 정리

세션 만료

세션 만료

세션 만료

QUEUED

REVIEWING

COMPLETED

CANCELLED

FAILED

EXPIRED

진행 단계는 PREPARE → BATCH_SEARCH → RERANK → CLAUSE_REVIEW → MISSING_DETECTION → RESULT_ASSEMBLY 순서를 가집니다. 오래된 이벤트가 뒤늦게 도착해도 화면이 되돌아가지 않도록 다음 규칙을 적용했습니다.

서버 재시작으로 중단된 active review는 이어서 실행한 것처럼 만들지 않고 REVIEW_INTERRUPTED의 재시도 가능한 실패로 정리합니다.

5. 중복 요청과 상태 경쟁을 나눈 방어선

하나의 장치로 전체 멱등성을 주장하지 않고 실패 원인에 따라 방어선을 나눴습니다.

실패 가능성방어선책임 범위
같은 요청 재전송Idempotency-Key와 request fingerprint같은 요청의 저장된 응답 재생
한 세션의 검토 중복 생성active review partial UNIQUE indexQUEUED·REVIEWING 동시 존재 차단
취소와 완료의 동시 상태 변경Review version 기반 낙관적 잠금오래된 상태를 기준으로 한 갱신 충돌 감지
충돌 뒤 재처리현재 상태 재조회와 제한된 재시도이미 확정된 종료 상태를 덮어쓰지 않음
DB commit 뒤 파일 삭제 실패반복 가능한 파일 삭제DB와 파일시스템 사이의 비원자적 경계 처리

이 구조는 단일 SQLite·단일 실행 프로세스 환경의 경쟁 조건을 다루며, 분산 큐나 다중 API 인스턴스의 Exactly-once 실행을 보장하지 않습니다.

6. 익명 세션과 임시 파일 수명주기

로그인 기능 없이 업로드 파일의 소유권을 확인하기 위해 익명 세션을 사용했습니다.

로그에는 request ID, 세션 ID 해시, review ID, 상태와 처리 시간만 남길 수 있습니다. 계약서·조항·프롬프트·검토 결과·대화 본문과 Cookie·API key는 기록하지 않습니다.

7. MCP 연결과 실패 경계

로컬과 배포 환경은 MCP에 문서를 전달할 수 있는 조건이 다릅니다.

실행 환경연결문서 전달
로컬FastAPI lifespan이 stdio 자식 프로세스 실행검증된 file_path
배포Docker Compose 내부 streamable HTTPfile_name과 base64 file_content

요청마다 MCP 프로세스와 연결을 다시 만들지 않고 ClientSession을 유지해 재사용했습니다. API 시작 시 capabilities handshake로 필요한 도구 계약을 확인하고, 실패하면 readiness를 통과시키지 않습니다.

timeout, 네트워크 오류, corpus 미준비와 파이프라인 실패는 같은 오류로 숨기지 않고 API 오류 계약에서 구분합니다. 다만 최종 streamable HTTP 전체 E2E와 장애 주입 완료 여부는 별도 실행 기록이 확인되지 않아 성과로 사용하지 않았습니다.

8. LLM보다 먼저 근거를 확정하는 Chat

현행 Chat은 LangGraph 그래프가 아니라 애플리케이션 서비스 파이프라인을 사용합니다.

Review·focus 검증
→ 서버가 답할 수 있는 상태·목록·정책 질문 처리
→ 질문 유형과 대상 조항 선택
→ AnswerPlan 확정
→ 필요한 근거만 추가
→ token 예산에 따라 분할 생성
→ 본문과 출처·제한 metadata 분리 반환

LLM을 호출하기 전에 AnswerPlan에서 질문 유형, 대상 조항과 사용할 근거를 확정합니다. 이전 답변 원문 전체를 장기 문맥으로 저장하지 않고, 검증된 conversation_token에 직전 질문 유형·대상 ID·다음 offset과 같은 의미 상태만 임시 저장합니다.

긴 결과는 최대 3개 항목씩 순차 생성하며 SSE의 progress, delta, segment_complete, completed, failed 이벤트로 전달합니다. 중간 묶음이 실패하면 이미 전달한 답변과 출처를 보존하고 continuation offset으로 남은 항목을 이어서 요청할 수 있습니다.

9. LLM 출처를 백엔드 책임으로 변경

초기에는 LLM이 실제 사용자 조항 ID와 표준조항 ID를 문자열로 생성했습니다. 작은 모델이 설명을 생성하고도 ID 복사에 실패해 전체 결과가 차단되는 문제가 있어 책임을 바꿨습니다.

LLM은 SRC_USER, SRC_STANDARD, SRC_GROUNDING 중 근거 종류만 선택합니다. 백엔드는 현재 세션과 요청에서 확인한 실제 ID를 선택된 종류에 결합합니다. 구조화 출력 뒤에는 다음 항목을 결정론적으로 검사합니다.

이 검사는 출처 종류 선택 자체의 의미가 정확하거나 환각이 사라졌음을 보장하지 않습니다. 모델이 생성해야 할 식별자와 백엔드가 보장할 수 있는 참조 무결성을 분리한 것입니다.

10. 후보 모델 검증

동일한 합성 검증 데이터 8개를 각 모델에 2회씩 실행했습니다. JSON Schema, temperature 0, seed 42와 동시 요청 1개를 공통 조건으로 두고 최종 검사 통과 여부, 응답 시간, 토큰, 종료 이유와 보정 여부를 실행 기록으로 남겼습니다.

최종 통과
16 / 16
합성 검증 데이터 8개 × 2회
응답 시간 p50
7.102초
응답 시간 p95
16.416초
언어 보정
2건
최초 출력의 중국어 혼입

이 결과를 기준으로 RedHatAI/Qwen3.5-9B-FP8-dynamic을 답변·Suggestions 후보로 선정했습니다. 16/16은 보정을 포함한 최종 결과이며, 법률 전문가 평가나 실제 계약서 품질, 통계적인 실패율 0%를 뜻하지 않습니다.

11. 배포와 권한 경계

정적 Web은 Private S3와 CloudFront OAC로 제공하고, API와 MCP는 단일 EC2에서 Nginx와 Docker Compose로 실행하도록 구성했습니다. 사용자 임시 데이터는 암호화된 EBS에 저장하고 운영 접속은 SSM Session Manager를 사용합니다.

GitHub Actions의 배포 권한과 고권한 인프라 수명주기를 분리했습니다.

실제 배포 시간이나 비용 절감 수치는 측정하지 않았습니다. 단일 EC2 구조이므로 고가용성이나 무중단 배포로 표현하지 않습니다.

12. 검증 범위

영역자동 검증
APIPytest, Ruff, OpenAPI schema 동기화
MCPPytest
WebTypeScript typecheck, Vitest·Testing Library, production build
InfraPython helper test, Docker Compose config, AWS CDK synth
컨테이너API·MCP·Embed/Rerank 실행 프로세스 이미지 빌드

테스트 개수는 변경될 수 있어 성과 수치로 사용하지 않았습니다. 자동 테스트 통과도 법률적 품질, 보안 완전성이나 실제 운영 안정성을 의미하지 않습니다.

13. 근거