From a8b05fa62842cfc7aaa659a2b126ca74cdef57e9 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Sun, 23 Nov 2025 14:30:06 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20Phase=202=20Step=201-2=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=83=81=ED=83=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...b8001_계층_분리_리팩토링_계획.md | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 journey/plans/251123_rb8001_계층_분리_리팩토링_계획.md diff --git a/journey/plans/251123_rb8001_계층_분리_리팩토링_계획.md b/journey/plans/251123_rb8001_계층_분리_리팩토링_계획.md new file mode 100644 index 0000000..6a73eec --- /dev/null +++ b/journey/plans/251123_rb8001_계층_분리_리팩토링_계획.md @@ -0,0 +1,178 @@ +# rb8001 계층 분리 리팩토링 계획 + +**날짜**: 2025-11-23 +**작성자**: admin +**관련 파일**: `rb8001/main.py`, `rb8001/app/router/router.py` +**참고**: `DOCS/book/300_architecture/311_FastAPI_구조_원칙.md` + +--- + +## 목적 + +rb8001의 중복 대화 저장 문제를 해결하고, FastAPI 구조 원칙(311_FastAPI_구조_원칙.md)을 준수하는 계층 분리 구조로 리팩토링 + +### 즉시 해결 필요 문제 +- 대화가 DB에 2번 저장되는 중복 저장 버그 (1회 요청 → 2회 DB INSERT) + +### 장기 개선 목표 +- 계층 분리 원칙 위반 15건 해결 +- 유지보수성 및 확장성 향상 + +--- + +## 현재 문제 + +### 1. 중복 저장 (긴급) + +**문제 상황:** +- router.py:876 - `_call_internal_llm`에서 1차 저장 (router → state 직접 호출) +- main.py:110 - `save_message_conversation`에서 2차 저장 (이미 제거됨) +- 결과: conversation_log 테이블에 동일 대화 2번 삽입 + +**원칙 위반:** +- 311_FastAPI_구조_원칙.md:92 - 계층 건너뛰기 (router → state 직접 호출) +- DRY 원칙 위반 (같은 로직 2곳 실행) + +### 2. 계층 구조 위반 (15건) + +#### 계층 건너뛰기 +1. router.py:876 - router → state 직접 호출 (원칙:92) +2. router/feedback_handler.py:58 - SessionLocal() 직접 사용 (원칙:21, 164) +3. router/intent_review_endpoint.py:21 - SessionLocal() 직접 사용 +4. router/slack_handler.py:77,202,361 - SessionLocal() 직접 사용 +5. services/startup_valuation.py:475 - asyncpg.connect() 직접 사용 (원칙:164) +6. services/intent_bayes.py:57,117,160 - psycopg2.connect() 직접 사용 +7. services/coldmail_filter.py:182,208,255 - asyncpg.connect() 직접 사용 +8. main.py:694,711 - state/database 직접 호출 (원칙:92) + +#### main.py 원칙 위반 +9. main.py:84-176 - 엔드포인트 직접 정의 (원칙:30 - "앱 실행, 라우터 등록만") +10. main.py:118-137 - 비즈니스 로직 포함 (원칙:21) +11. main.py:211,620 - router 내부 메서드(_call_internal_llm) 직접 호출 + +#### 비즈니스 로직 배치 오류 +12. router.py:128-682 - route_message()는 비즈니스 로직, services/에 있어야 함 (원칙:21) +13. app/brain/, app/llm/, app/memory/ - services/brain/, services/llm/로 이동 필요 (원칙:28-42) + +#### 구조 누락 +14. schemas/ 폴더 없음 (원칙:49) +15. models와 state 미분리 - state/database.py에 ORM 모델 + DB 접근 혼재 (원칙:36,47) + +#### 파일 크기 초과 +- 24개 파일이 300줄 초과 (router.py 915줄, main.py 747줄 등) + +--- + +## 해결 방안 + +### Phase 1: 중복 저장 해결 (긴급, 완료) + +**수정 완료:** +- router.py:873-884 - `_save_conversation` 호출 제거 +- router.py:628-638, 670-680 - services 호출 추가 +- main.py:108-115 - `save_message_conversation` 호출 제거 + +**결과:** +- 대화 저장 1회로 축소 +- 하지만 router에서 services 호출 (임시) + +### Phase 2 Step 1-2: 엔드포인트 및 비즈니스 로직 분리 (완료) + +**수정 완료:** +- app/router/message_endpoint.py 생성 - 엔드포인트 분리 +- main.py:84-176 제거 → message_endpoint.py로 이동 +- main.py에 include_router 추가 +- app/services/message_service.py 생성 - route_message 이동 +- router.py:128-682 (route_message) → message_service.py로 이동 +- router.py는 message_service 호출만 (~10줄) + +**결과:** +- 계층 분리 원칙 준수 (router → services → state) +- 중복 저장 문제 해결 (services 레이어에서 한 번만 저장) +- router.py 크기 927줄 → 366줄로 축소 + +### Phase 2: 계층 분리 리팩토링 (대규모) + +#### Step 1: 엔드포인트 분리 +**생성:** +- app/router/message_endpoint.py (~100줄) + +**수정:** +- main.py:84-176 제거 → message_endpoint.py로 이동 +- main.py에 include_router 추가 + +#### Step 2: 비즈니스 로직 분리 +**생성:** +- app/services/message_service.py (~550줄) + +**수정:** +- router.py:128-682 (route_message) → message_service.py로 이동 +- router.py는 message_service 호출만 (~10줄) +- slack_handler.py:424,437,448,893 - message_service 호출로 변경 + +#### Step 3: 폴더 구조 정리 +**이동:** +- app/brain/ → app/services/brain/ +- app/llm/ → app/services/llm/ +- app/memory/ → app/services/memory/ +- app/skills/ → app/services/skills/ +- app/notifications/ → app/services/notifications/ +- app/pipelines/ → app/services/pipelines/ + +**생성:** +- app/schemas/ - API 요청/응답 스키마 분리 + +#### Step 4: DB 접근 정리 +**생성:** +- app/models/{domain}_model.py - ORM 모델 분리 + +**수정:** +- state/database.py - models 제거, Repository만 남김 +- router/feedback_handler.py, intent_review_endpoint.py, slack_handler.py - state 통해서만 DB 접근 +- services 파일들 - asyncpg.connect() 제거, state 호출로 변경 + +--- + +## 기대효과 + +### 즉시 효과 +- 중복 저장 버그 해결 → DB 용량 절약, 데이터 정합성 확보 + +### 장기 효과 +1. **유지보수성**: 계층별 책임 명확 → 수정 영향 범위 최소화 +2. **확장성**: 새 기능 추가 시 어느 계층에 넣을지 명확 +3. **테스트**: 계층별 단위 테스트 작성 용이 +4. **협업**: 원칙 준수로 코드 가독성 향상 +5. **기술부채 감소**: 15개 위반 사항 해결 + +--- + +## 구현 규모 + +### 최소 수정 (Phase 1만) +- 영향 파일: 2개 (router.py, main.py) +- 수정 라인: ~50줄 +- 소요 시간: 완료 + +### 전체 리팩토링 (Phase 2) +- 영향 파일: 최소 30개 +- 신규 생성: ~650줄 +- 수정/제거: ~1,300줄 +- 총 변경: ~2,000줄 +- 예상 소요: 1-2일 + +--- + +## 우선순위 + +1. **긴급 (완료)**: 중복 저장 버그 해결 +2. **높음**: 엔드포인트 분리 (main.py 원칙 준수) +3. **중간**: 비즈니스 로직 분리 (route_message → service) +4. **낮음**: 폴더 구조 정리, 파일 크기 축소 + +--- + +## 참고 + +- 311_FastAPI_구조_원칙.md - 계층 분리 원칙 +- 312_문서_작성_원칙.md - 문서 작성 규칙