Files
jarca-ledger-mcp/docs/discovery/dcy-010_20260702_backend-core-layering-mcp-adapter-realignment.md
T

19 KiB

0. 문서 상태

이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.

  • 상태: confirmed
  • 문서 ID: dcy-010_20260702_backend-core-layering-mcp-adapter-realignment
  • 이슈명: Jarca Ledger 백엔드 코어 분리 및 layered 아키텍처(application/domain/infrastructure/adapters) 재편, MCP adapter 재정렬
  • 작성 시각(KST): 2026-07-02 23:32
  • 마지막 갱신 시각(KST): 2026-07-02 23:56
  • 대체됨: 없음
  • 후속 Discovery 참조: 없음
  • 생성된 REQ 참조: REQ-013, REQ-014

1. 계획 상태 요약

현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.

  • 연계 문서 현황:
    • 관련 blueprint: .hermes/plans/2026-07-02_jarca-ledger-backend-refactor-blueprint.md (근거 리팩터링 청사진)
    • 관련 baseline 문서: docs/project-structure.md, docs/runtime-flows.md
  • 해석:
    • jarca_ledger_mcp/service.py가 약 3,378줄로 비대해져 MCP/Streamlit/SQLite 접근/import/reporting/reconciliation/asset 워크플로우가 하나의 함수 네임스페이스에 과결합된 상태이며, 향후 HTTP 등 인터페이스 확장 전에 layered backend 경계 도입이 필요하다.
    • 이번 Discovery는 MCP를 제거하지 않고 adapter로 재정의하면서 application/domain/infrastructure/adapters 경계로 단계적(strangler-fig) 재편하는 구조 개선 주기를 신규로 시작할지 판정하고, baseline 문서(project-structure/runtime-flows) 갱신 요구까지 포함한 초안을 만든다.

2. 요구사항 판정 결과

이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.

  • 판정: 신규
  • 근거
    • 기존 dcy-001~009는 기능/운영 워크플로우(분류·환급, 백업·복구, 잔액대조, E2E evidence, 대시보드, CI, MCP 응답 계약, 자산 스냅샷/CRUD)를 다루며, service.py 분해와 layered backend 아키텍처 재편이라는 구조 리팩터링 주제를 다룬 Discovery는 없다.
    • dcy-007(MCP response contract)은 응답 계약의 안정성을 다루지만 내부 계층 구조 분해나 persistence 분리를 정의하지 않아 문제 정의·범위·성공 기준이 실질적으로 다르다.

판정이 완전 중복인 경우: 이하 섹션 작성을 중단하고 # 9. 파일 처리 결과에 중복 판정 사유와 참조 문서 경로를 기록한 뒤 문서를 닫는다. REQ 초안 작성으로 넘기지 않는다.

3. 문제점의 요약

문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.

  • 현재 상태
    • jarca_ledger_mcp/service.py(약 3,378줄, blueprint 기준 약 126 함수)가 사실상 애플리케이션 전체 역할을 하며 비즈니스 규칙·오케스트레이션·SQL·mutation 안전·import·reporting·cross-transfer가 한 모듈에 집중되어 있다.
    • jarca_ledger_mcp/server.py(약 296줄, 약 57개 MCP tool wrapper)와 dashboard/app.py(약 1,811줄)가 모두 from jarca_ledger_mcp import service로 동일한 넓은 함수 네임스페이스에 직접 결합되어 있다.
    • jarca_ledger_mcp/db.py(약 333줄)에 schema·connection·additive migration helper가 한 파일에 섞여 있어 persistence 경계가 비즈니스 규칙과 분리되어 있지 않다.
    • baseline 문서는 이미 존재한다(docs/project-structure.md, docs/runtime-flows.md). 다만 이번 구조 재편은 패키지 레이아웃과 런타임 호출 흐름을 크게 바꾸므로 두 baseline 문서의 갱신 갭이 발생한다.
  • 기대 상태
    • MCP는 유지하되 adapters/mcp로 위치를 재정의하고, Streamlit은 adapters/streamlit gateway를 통해 좁은 표면에만 의존하는 thin adapter가 된다.
    • domain/application/infrastructure/adapters 경계가 명시되고, service.py는 호환 facade로 축소되거나 호출부 이관 후 제거되며, 각 도메인 영역이 독립적으로 이해·테스트 가능해진다.
  • 이해관계자
    • 문서 작성자(AI agent) 및 리팩터링 실행 subagent
    • 리뷰어/승인자(Hermes 및 저장소 소유자)
    • MCP/Streamlit 사용자(마이그레이션 중 동작 유지가 보장되어야 하는 소비자)
  • 제약사항
    • 마이그레이션 전 구간에서 MCP tool 이름/주요 응답 필드/카테고리·현금흐름 의미/import 증빙 필드/additive-only migration/Streamlit 페이지 동작이 호환 계약으로 유지되어야 한다.
    • big-bang rewrite 금지, 금융 데이터 특성상 destructive migration은 승인 없이 금지하고 fixture/복사 DB만 사용한다.

주요 사용자 시나리오

사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.

  • 개발자가 특정 도메인(예: 자산 스냅샷) 로직을 수정할 때 3,378줄 service.py 전체를 탐색하지 않고 해당 application service와 repository만 열어 변경·테스트하려는 상황.
  • 운영자가 DB I/O/integrity 장애를 진단할 때, persistence 계층이 분리되어 있어 문제를 전체 애플리케이션 경로가 아닌 infrastructure/sqlite 경계로 국소화하려는 상황.
  • 향후 HTTP/FastAPI adapter를 추가하려는 개발자가 비즈니스 로직을 다시 이동시키지 않고 application/* 위에 adapter 패키지만 추가하려는 상황.

4. 이번에 정의할 변경

이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.

  • service.py 분해: 비즈니스 로직을 domain(types/invariants/validation), application(use case/orchestration), infrastructure(sqlite repo/parsers)로 이관하고 service.py는 임시 호환 facade로 축소한다.
  • persistence 분리: db.py의 schema/connection/migration을 infrastructure/sqlite로 분리하고 테이블/use-case별 repository를 도입한다.
  • MCP/Streamlit thin adapter화: MCP tool 등록을 adapters/mcp/server.py로 이동해 top-level server.py는 shim으로 남기고, Streamlit은 adapters/streamlit/service_gateway.py의 좁은 gateway 호출로 전환한다.
  • baseline 문서 갱신 요구: 새 패키지 레이아웃과 런타임 호출 경로 변화를 반영해 docs/project-structure.md와 docs/runtime-flows.md를 갱신한다.
  • 단계적 migration 원칙 확정: strangler-fig 순서(foundations → read-only/reporting → write CRUD → import → cross-transfer/reconciliation/assets → adapter narrowing)로 blast radius를 최소화한다.

영향 범위

변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.

  • 코드 영향:
    • jarca_ledger_mcp/service.py, db.py, server.py 분해 및 호환 facade/shim화
    • 신규 패키지 jarca_ledger_mcp/{domain,application,infrastructure,adapters}/* 도입
    • dashboard/app.py의 service.* 광범위 의존을 gateway 호출로 축소, pyproject.toml 패키지 discovery/entrypoint 정합성 유지
    • 테스트를 repository/application-service/adapter 계층으로 재배치(Layer A/B/C)
  • 문서 영향:
    • docs/project-structure.md, docs/runtime-flows.md 갱신 요구
    • 신규 Discovery 및 docs/discovery/index.md 행 추가
  • 운영 영향:
    • 마이그레이션 중 MCP/Streamlit 동작 유지 필요, 배포 절차 자체 변경은 없음(entrypoint 호환 유지)
    • destructive migration 금지, DB 안전 정책(복사/fixture DB) 유지

5. 요구사항 목록

실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.

기능 요구사항

  • FR-1: jarca_ledger_mcp에 domain/application/infrastructure/adapters 경계를 도입하고 service.py의 로직을 도메인별 application service와 repository로 이관하되, service.py는 호환 facade로 남겨 기존 호출부가 깨지지 않게 한다.
  • FR-2: db.py의 schema/connection/additive migration을 infrastructure/sqlite(connection/schema/migrations/row_mapping + 테이블별 repo)로 분리하고, db.py는 호환 shim으로 유지한다.
  • FR-3: MCP tool 등록을 adapters/mcp로 이동해 top-level server.py를 thin shim으로 만들고, Streamlit이 adapters/streamlit/service_gateway.py의 좁은 gateway에만 의존하도록 전환한다.
  • FR-4: 구조/런타임 baseline 갭을 해소하기 위해 docs/project-structure.md와 docs/runtime-flows.md에 신규 계층 구조와 호출 흐름 갱신 요구를 반영한다.

비기능 요구사항

성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.

  • NFR-1: 호환 계약 안정성 — MCP tool 이름, 주요 응답 필드(success, count, items, error, validation, matched_count 등), 카테고리·현금흐름 의미, import 증빙 필드(raw_summary/counterparty/raw_payload/external_id/import_batch_id), additive-only migration, Streamlit 페이지 동작/순서가 의도적 버전 변경·승인 없이 바뀌지 않는다.
  • NFR-2: 단계적 안전성 — 각 phase는 독립적으로 검증 가능해야 하고(pytest 회귀 + py_compile), 한 번에 하나의 도메인 슬라이스만 이관해 blast radius를 최소화한다.
  • NFR-3: DB 안전성 — 리팩터링 중 fixture/복사 DB만 사용하고 승인 없는 destructive migration을 수행하지 않는다.

범위 경계

이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.

  • In Scope
    • blueprint 기준 Phase 0~3 우선: behavioral baseline 고정 → 새 skeleton/compat seam 도입 → persistence 분리 → read-only application service 추출
    • baseline 문서(project-structure/runtime-flows) 갱신 요구
    • 단계적(strangler-fig) migration 원칙 정의
  • Out of Scope
    • 즉시 FastAPI/HTTP 전환(향후 adapter 준비만, 강제하지 않음)
    • Postgres/원격 DB 이관
    • 멀티유저/권한 체계 도입
    • 원격 운영(remote ops) 재설계
    • Phase 4 이후의 write/import/advanced workflow/adapter narrowing 구현(별도 후속 REQ·Batch·GitHub Project TODO로 추적)

6. 리스크/가정 목록

불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.

리스크

  • R-1 (High): service.py 내부 숨은 결합 — 공유 helper 이관 시 예상치 못한 호출부가 깨질 수 있다.
    • 완화 방안: 리팩터링 전에 characterization/contract 회귀 테스트를 먼저 추가하고, helper는 첫 소비자와 함께 이동한다.
  • R-2 (High): MCP/Streamlit 계약 drift — tool 응답 형태나 페이지 동작이 조용히 바뀔 수 있다.
    • 완화 방안: 리팩터링 전 응답 형태(shape) 테스트와 Streamlit 페이지/서비스 통합 테스트를 확보하고 adapter gateway로 페이지 단위 점진 이관한다.
  • R-3 (Medium): 신규 repository 간 SQL/row mapping 중복으로 유지보수성 저하.
    • 완화 방안: row mapping과 공통 predicate를 중앙화(row_mapping.py)하고 repository 규칙(메시지 포매팅 금지, dict/dataclass 반환)을 강제한다.

가정

아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.

  • A-1: 기존 pytest 스위트(transaction/import/rules/dashboard 회귀 등)가 동작하며 baseline 고정과 회귀 검증의 기준으로 사용할 수 있다.
  • A-2: 현재 SQLite schema가 additive-oriented이므로 destructive 변경 없이 계층 분리를 진행할 수 있다.
  • A-3: MCP는 이미 spirit 상 adapter(server.py가 대부분 thin wrapper)이므로 adapter 재정렬이 큰 동작 변경 없이 가능하다.

오픈 질문

답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.

  • OQ-1: 이번 리팩터링을 전체 phase(17)를 한 주기로 다룰지, blueprint Batch A(Phase 03)만 첫 배치로 축소해 시작할지?
    • 상태: Answered
    • 처리 방안: 사용자 승인에 따라 Discovery 범위를 Phase 0~3 우선 배치로 고정하고, Phase 4+는 GitHub Project TODO와 후속 REQ/Batch로 분리 추적한다.
    • 종료 조건: # 5. 요구사항 목록 > 범위 경계에 1차 범위가 Phase 0~3으로 반영되었으므로 종료한다.
  • OQ-2: 마이그레이션 완료 판정 기준(service.py 목표 라인 수 400600줄 축소 vs 완전 제거) 중 어느 것을 Definition of Done으로 채택할지?
    • 상태: Answered
    • 처리 방안: 사용자 승인에 따라 1차 완료 기준을 service.py 호환 facade 수준(400600줄) 축소로 채택하고, 완전 제거는 후속 단계 최적화로 남긴다.
    • 종료 조건: 성공 기준 S-2와 REQ handoff 기준에 facade 축소 DoD가 반영되었으므로 종료한다.

오픈 질문 처리 기준

  • Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.
  • Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.
  • Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.
  • Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.
  • 처리 원칙 1: 질문만 남기지 말고 반드시 상태, 처리 방안, 종료 조건을 함께 적는다.
  • 처리 원칙 2: 답이 나온 질문은 본문 반영 없이 단순 삭제하지 않는다. 반영 위치를 먼저 갱신한다.
  • 처리 원칙 3: High 영향 질문은 Deferred 처리 후 처리 방안에 REQ 인계 추적 방식을 명시한다.

7. 초기 성공 기준

이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.

  • S-1: 마이그레이션 전 구간에서 MCP와 Streamlit이 동작하며 기존/대체 회귀 테스트가 통과한다.
  • S-2: 1차 리팩터링 완료 시 service.py가 호환 glue/facade 수준(blueprint §11 기준 400600줄)으로 축소되고, db.py는 shim 또는 얇은 compatibility entry로 축소된다.
  • S-3: 각 주요 도메인 영역이 자체 application service와 persistence 경계를 갖고, docs/project-structure.md·docs/runtime-flows.md가 신규 계층 구조를 반영하도록 갱신되어 이후 REQ/Batch 산출물이 baseline 문서를 참조할 수 있다.

측정 방식 및 데이터 출처

각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.

  • S-1 측정 방식: 각 phase 종료 시 pytest 회귀 스위트 + MCP tool contract 테스트 전부 통과 확인 / 데이터 출처: tests/ 실행 결과, docs/discovery/dcy-007 응답 계약
  • S-2 측정 방식: wc -l jarca_ledger_mcp/service.py, db.py 라인 수와 import 의존성 그래프를 확인하고 1차 목표를 facade 수준 축소로 검증 / 데이터 출처: 리팩터링 후 소스 파일, blueprint §11 DoD
  • S-3 측정 방식: 각 도메인 application service/repository 존재 여부 및 baseline 문서 diff 확인 / 데이터 출처: jarca_ledger_mcp/{application,infrastructure}/*, docs/project-structure.md, docs/runtime-flows.md

8. REQ로 넘기기 전 확인 체크

REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.

  • 범위(In Scope/Out of Scope) 확정
    • 기준: 사용자 승인에 따라 Phase 0~3 우선 범위와 Out of Scope 항목이 문서에 반영되어 있으며, Phase 4+는 별도 TODO/후속 REQ로 추적한다.
  • 성공 지표의 측정 방식/데이터 출처 확정
    • 기준: S-2의 1차 DoD를 service.py facade 수준 축소로 채택했고, 세부 baseline 테스트 목록은 REQ/Phase 0 planning에서 계측 대상으로 명시한다.
  • High 영향 리스크 우선순위 및 해소 책임자 지정
    • 기준: R-1, R-2는 REQ/Batch planning 단계에서 characterization/contract 테스트 선행 책임자를 지정하는 비차단 항목으로 정리되었고, Discovery 범위·성공 기준·검증 시나리오 확정은 완료되었다.
  • 모든 오픈 질문(OQ) Open 상태 없음 확인
    • 기준: OQ 목록의 항목이 모두 Answered이거나 Deferred 처리 완료
  • Freeze 확정 담당자(CONFIRMED_BY) 지정
    • 기준: 사용자 승인에 따라 저장소 소유자 진환 고가 Confirmed By로 기록되었다.

9. 파일 처리 결과

이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.

  • 처리 결과: 갱신
  • 생성 경로: docs/discovery/dcy-010_20260702_backend-core-layering-mcp-adapter-realignment.md
  • 참조 문서:
    • .hermes/plans/2026-07-02_jarca-ledger-backend-refactor-blueprint.md (근거 blueprint)
    • stage-pilot/templates/project-structure.md (baseline 갱신 논리 템플릿 참조)
    • stage-pilot/templates/runtime-flows.md (baseline 갱신 논리 템플릿 참조)

10. 사용자 결정 필요 항목 요약

사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.

DECIDE

  • 없음 — 이번 반복 범위는 blueprint 기준 Phase 0~3 우선으로 고정한다.
  • 없음 — 1차 완료 기준은 service.py를 400600줄 호환 facade 수준으로 축소하는 것으로 채택한다.

CONFIRM

  • 없음 — MCP tool 이름/주요 응답 필드/import 증빙 필드/Streamlit 페이지 동작은 이번 리팩터링 동안 호환 계약으로 동결한다.

DATA

  • REQ 단계 계측: Phase 0 baseline 고정용 현재 통과 pytest 스위트 목록과 커버 대상 MCP tool 집합은 REQ/Phase 0 planning 산출물에서 명시한다.

11. Discovery Freeze

REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.

섹션 참조

Freeze 플래그

  • Handoff Decision: 승인
  • Handoff Rationale: 사용자 승인에 따라 1차 범위를 Phase 0~3으로 축소하고 1차 완료 기준을 service.py facade 수준 축소로 확정했다. 호환 계약 동결 정책도 반영되었고, 남은 baseline 테스트 상세 목록과 리스크 책임자 지정은 REQ/Phase 0 planning 단계 비차단 계측·할당 항목으로 정리되었다.
  • Ready for REQ Drafting: true
  • Confirmed By: 진환 고
  • Confirmed At (KST): 2026-07-02 23:56 KST