# P&ID 재설계 - 코딩 계획 > 작성일: 2026-05-04 > 상태: 진행 중 > 목표: `No-10_Plant_PID.dxf`(28,819 엔티티) 처리 시 30분 타임아웃 해결 --- ## 현황 요약 | 단계 | 내용 | 상태 | |------|------|------| | Step 1 | 현황 분석 (DXF 구조 파악) | ✅ 완료 | | Step 2 | 성공 테스트 분석 (분할+병렬 성공 요인) | ✅ 완료 | | Step 3 | 레전드 페이지 분석 (legend_parser.py 생성) | ✅ 완료 | | Step 4 | 해결 방향 정의 | ✅ 완료 | | Step 5~10 | 구현 (아래 상세 계획) | 🔲 미시작 | --- ## 핵심 전략 1. **도면 분할** — 한 DXF 파일 내 여러 도면을 좌표 기반으로 분리 (9개 도면 → 각각 독립 처리) 2. **계측기 유형별 병렬 LLM 호출** — Sensor/Valve/System/Gauge/Pump 동시 처리 3. **위치 정보 저장** — 태그의 DXF 상 좌표 + 근처 텍스트 4. **AREA 그룹핑** — 태그명에서 플랜트 번호 유추 --- ## 변경 대상 파일 | 파일 | 변경 내용 | |------|-----------| | `mcp-server/pipeline/extractor.py` | 도면 분할 로직 추가 | | `mcp-server/worker/pid_worker.py` | 도면 분할 + 병렬 LLM 호출 | | `mcp-server/pipeline/mapper.py` | 기존 유지 (이미 배치 처리 구현됨) | | `mcp-server/pipeline/topology.py` | 기존 유지 (이미 SpatialGrid 구현됨) | | `mcp-server/pipeline/legend_parser.py` | 기존 유지 (이미 계측기 그룹 정의됨) | --- ## 상세 코딩 계획 ### Phase 1: 도면 분할 로직 (extractor.py) #### 1-1. 도면 분할 테스트 스크립트 작성 - **파일**: `test_drawing_split.py` (신규) - **목표**: `No-10_Plant_PID.dxf`를 TITLE 레이어 LINE으로 분할하는 로직 프로토타입 - **작업 내용**: - ezdxf로 DXF 로드 - TITLE 레이어의 LINE 엔티티 탐색 - 수직 LINE(X 좌표가 일정)을 도면 경계로 감지 - 각 도면별 X/Y 범위 출력 - **검증**: 9개 도면 영역이 올바르게 분리되는지 확인 - **완료 기준**: 콘솔에 9개 도면의 X/Y 범위가 출력됨 #### 1-2. PidGeometricExtractor에 도면 분할 메서드 추가 - **파일**: `mcp-server/pipeline/extractor.py` - **목표**: `split_drawings()` 메서드 추가 - **작업 내용**: - `split_drawings() -> List[DrawingRegion]` 메서드 추가 - DrawingRegion 데이터클래스 정의 (drawing_no, x_min, x_max, y_min, y_max) - TITLE 레이어 LINE 기반 경계 감지 - 레전드 페이지(X < 2000) 제외 - FFD 페이지도 제외 (최상단 텍스트 기반) - **완료 기준**: `split_drawings()` 호출 시 9개 DrawingRegion 반환 #### 1-3. 영역별 추출 메서드 추가 - **파일**: `mcp-server/pipeline/extractor.py` - **목표**: `extract_region()` 메서드 추가 - **작업 내용**: - `extract_region(region: DrawingRegion) -> List[GeometricEntity]` 메서드 추가 - bbox가 region 범위 내에 있는 엔티티만 필터링 - 기존 `extract_and_save()` 로직 재사용 - **완료 기준**: 각 도면별 엔티티 수 합계가 전체 엔티티 수와 일치 #### 1-4. 도면 분할 통합 테스트 - **파일**: `test_drawing_split.py` - **목표**: 전체 파이프라인 테스트 - **작업 내용**: - DXF 로드 → 분할 → 영역별 추출 → 결과 검증 - 각 도면별 엔티티 수, 태그 수 확인 - 처리 시간 측정 - **완료 기준**: 9개 도면 모두 정상 추출, 총 처리 시간 < 30초 --- ### Phase 2: 계측기 유형별 병렬 LLM 호출 (pid_worker.py) #### 2-1. 계측기 유형별 프롬프트 정의 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: 각 유형별 전용 프롬프트 상수 정의 - **작업 내용**: - `_SENSOR_EXTRACT_SYSTEM` — FT, FIT, LT, PT, TE, PG, LG, TG 추출 - `_VALVE_EXTRACT_SYSTEM` — FCV, TCV, LCV, PCV, XV, FV, LV, PV, TV 추출 - `_SYSTEM_EXTRACT_SYSTEM` — LI, PI, TI, FIQ, FICQ, TICA, PICA, LICA 추출 - `_GAUGE_EXTRACT_SYSTEM` — PG, TG, LG 추출 - `_PUMP_EXTRACT_SYSTEM` — P-10101, VP-10117, DP-10101 등 펌프 추출 - 각 프롬프트는 `max_tokens=65536` 적용 - **완료 기준**: 5개 프롬프트 상수 정의 완료 #### 2-2. 유형별 추출 함수 작성 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: `_extract_tags_by_type()` 함수 추가 - **작업 내용**: - `_extract_tags_by_type(text: str, type_name: str, system_prompt: str) -> List[dict]` 함수 - LLM 호출 → JSON 파싱 → 태그 목록 반환 - `max_tokens=65536` 적용 - finish_reason=length 복구 로직 포함 - **완료 기준**: 단일 유형 추출 테스트 통과 #### 2-3. 병렬 호출 로직 구현 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: `_extract_all_types_parallel()` async 함수 추가 - **작업 내용**: - `asyncio.gather()`로 5개 유형 동시 호출 - 각 유형별 결과 통합 - 중복 태그 제거 (tagNo 기준) - **완료 기준**: 5개 유형 병렬 호출 테스트, 총 처리 시간 < 120초 #### 2-4. `_build_pid_graph_parallel()` 리팩토링 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: 기존 함수를 도면 분할 + 병렬 LLM 호출로 변경 - **작업 내용**: - Phase 1: 도면 분할 (extractor.split_drawings()) - Phase 2: 각 도면별 기하 추출 (extractor.extract_region()) - Phase 3: 각 도면별 유형별 병렬 LLM 호출 - Phase 4: 결과 통합 + 그래프 빌드 - Phase 5: 저장 - **완료 기준**: 기존 API 호환 유지, 처리 시간 30분 → 5분 이내 #### 2-5. 병렬 처리 통합 테스트 - **파일**: `test_parallel_extraction.py` (신규) - **목표**: 전체 병렬 처리 파이프라인 테스트 - **작업 내용**: - `No-10_Plant_PID.dxf` 전체 처리 - 각 단계별 시간 측정 - 추출된 태그 수, 매핑 수 확인 - **완료 기준**: 전체 처리 < 5분, 태그 추출 수 > 기존 --- ### Phase 3: 위치 정보 저장 #### 3-1. 위치 정보 스키마 정의 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: 태그 추출 결과에 위치 정보 포함 - **작업 내용**: - 각 태그에 `bbox` (min_x, min_y, max_x, max_y) 필드 추가 - `drawing_no` (도면 번호) 필드 추가 - `nearby_text` (근처 텍스트) 필드 추가 - **완료 기준**: 추출 결과 JSON에 위치 정보 포함 #### 3-2. 근처 텍스트 추출 로직 - **파일**: `mcp-server/pipeline/extractor.py` - **목표**: `get_nearby_text()` 메서드 추가 - **작업 내용**: - 특정 좌표 주변 threshold 이내 TEXT 엔티티 검색 - SpatialGrid 활용 (O(1) 조회) - 상하좌우 위치 파악 (direction 필드) - **완료 기준**: 태그 주변 텍스트 정상 추출 #### 3-3. 위치 정보 통합 테스트 - **파일**: `test_location_info.py` (신규) - **목표**: 위치 정보 정확도 검증 - **작업 내용**: - 알려진 태그 위치와 추출된 위치 비교 - 근처 텍스트 정확도 확인 - **완료 기준**: 위치 정보 정확도 > 90% --- ### Phase 4: AREA 그룹핑 #### 4-1. AREA 추출 로직 개선 - **파일**: `mcp-server/pipeline/legend_parser.py` - **목표**: `extract_area_from_tag()` 정확도 향상 - **작업 내용**: - FICQ-6113 → "6" (6호 플랜트) - FICQ-10113 → "10" (10호 플랜트) - 패턴 매칭 개선 (정규식 튜닝) - **완료 기준**: 테스트 케이스 10개 모두 정확 #### 4-2. AREA별 그룹핑 함수 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: `_group_by_area()` 함수 추가 - **작업 내용**: - 추출된 태그 목록을 AREA별로 그룹핑 - AREA 번호가 없는 태그는 "unknown" 그룹 - 그룹별 통계 출력 - **완료 기준**: AREA별 그룹핑 결과 정상 출력 --- ### Phase 5: Experion 태그 매핑 #### 5-1. 기존 매핑 로직 확인 - **파일**: `mcp-server/pipeline/mapper.py` - **목표**: 기존 IntelligentMapper 동작 확인 - **작업 내용**: - `_batch_gather()` 배치 처리 확인 (이미 구현됨) - RapidFuzz 기반 후보 추출 확인 - LLM 기반 최종 매핑 확인 - **완료 기준**: 기존 매핑 정확도 확인 #### 5-2. 매핑 결과 통합 - **파일**: `mcp-server/worker/pid_worker.py` - **목표**: `_build_pid_graph_parallel()`에 매핑 결과 통합 - **작업 내용**: - Phase 3 결과 (추출된 태그)를 IntelligentMapper에 전달 - 매핑 결과를 그래프에 추가 - 매핑 통계 출력 - **완료 기준**: 매핑 결과 그래프에 정상 반영 --- ### Phase 6: UI 연동 #### 6-1. API 엔드포인트 확인 - **파일**: `src/Web/Controllers/PidController.cs` - **목표**: 기존 API 엔드포인트 확인 - **작업 내용**: - 태그 검색 API 확인 - 위치 정보 반환 여부 확인 - **완료 기준**: API 스펙 파악 #### 6-2. 위치 정보 API 추가 - **파일**: `src/Web/Controllers/PidController.cs` - **목표**: 태그 위치 조회 API 추가 - **작업 내용**: - `GET /api/pid/tags/{tagName}/location` 엔드포인트 추가 - DXF 좌표, 도면 번호, 근처 텍스트 반환 - 현재 실시간 값 연동 - **완료 기준**: API 테스트 통과 #### 6-3. 프론트엔드 UI 수정 - **파일**: `src/Web/wwwroot/js/app.js` - **목표**: 태그 검색 시 위치 표시 - **작업 내용**: - 태그 검색 결과에 위치 정보 표시 - "6호 정제탑, 밑에서 3번째 온도 센서입니다. 현재 온도 105도" 형식 - DXF 도면 상 위치 시각화 (선택사항) - **완료 기준**: UI에서 위치 정보 확인 가능 --- ## 실행 순서 및 의존성 ``` Phase 1 (도면 분할) ├── 1-1 → 1-2 → 1-3 → 1-4 (순차) │ Phase 2 (병렬 LLM) ├── 2-1 → 2-2 → 2-3 → 2-4 → 2-5 (순차, Phase 1 완료 후) │ Phase 3 (위치 정보) ├── 3-1 → 3-2 → 3-3 (순차, Phase 2 완료 후) │ Phase 4 (AREA 그룹핑) ├── 4-1 → 4-2 (순차, 독립 실행 가능) │ Phase 5 (매핑 통합) ├── 5-1 → 5-2 (순차, Phase 2+3 완료 후) │ Phase 6 (UI 연동) ├── 6-1 → 6-2 → 6-3 (순차, Phase 5 완료 후) ``` --- ## 각 단계 완료 기준 | 단계 | 완료 기준 | 예상 시간 | |------|-----------|-----------| | 1-1 | 9개 도면 영역 콘솔 출력 | 30분 | | 1-2 | `split_drawings()` 9개 Region 반환 | 1시간 | | 1-3 | `extract_region()` 정상 동작 | 30분 | | 1-4 | 전체 분할 테스트 통과 | 30분 | | 2-1 | 5개 프롬프트 상수 정의 | 30분 | | 2-2 | 단일 유형 추출 테스트 통과 | 1시간 | | 2-3 | 5개 유형 병렬 호출 테스트 | 1시간 | | 2-4 | `_build_pid_graph_parallel()` 리팩토링 완료 | 2시간 | | 2-5 | 전체 병렬 처리 테스트 통과 | 1시간 | | 3-1 | 위치 정보 JSON 필드 추가 | 30분 | | 3-2 | `get_nearby_text()` 구현 | 1시간 | | 3-3 | 위치 정보 정확도 검증 | 30분 | | 4-1 | AREA 추출 테스트 10개 통과 | 30분 | | 4-2 | AREA별 그룹핑 결과 출력 | 30분 | | 5-1 | 기존 매핑 정확도 확인 | 30분 | | 5-2 | 매핑 결과 그래프 반영 | 1시간 | | 6-1 | API 스펙 파악 | 30분 | | 6-2 | 위치 조회 API 추가 | 1시간 | | 6-3 | UI 수정 완료 | 1시간 | **총 예상 시간: 약 18시간** --- ## 체크리스트 ### Phase 1: 도면 분할 - [ ] 1-1. 도면 분할 테스트 스크립트 작성 - [ ] 1-2. PidGeometricExtractor에 도면 분할 메서드 추가 - [ ] 1-3. 영역별 추출 메서드 추가 - [ ] 1-4. 도면 분할 통합 테스트 ### Phase 2: 계측기 유형별 병렬 LLM 호출 - [ ] 2-1. 계측기 유형별 프롬프트 정의 - [ ] 2-2. 유형별 추출 함수 작성 - [ ] 2-3. 병렬 호출 로직 구현 - [ ] 2-4. `_build_pid_graph_parallel()` 리팩토링 - [ ] 2-5. 병렬 처리 통합 테스트 ### Phase 3: 위치 정보 저장 - [ ] 3-1. 위치 정보 스키마 정의 - [ ] 3-2. 근처 텍스트 추출 로직 - [ ] 3-3. 위치 정보 통합 테스트 ### Phase 4: AREA 그룹핑 - [ ] 4-1. AREA 추출 로직 개선 - [ ] 4-2. AREA별 그룹핑 함수 ### Phase 5: Experion 태그 매핑 - [ ] 5-1. 기존 매핑 로직 확인 - [ ] 5-2. 매핑 결과 통합 ### Phase 6: UI 연동 - [ ] 6-1. API 엔드포인트 확인 - [ ] 6-2. 위치 정보 API 추가 - [ ] 6-3. 프론트엔드 UI 수정 --- ## 주의 사항 1. **백업 필수**: 각 파일 수정 전 `.rooBackup/`에 백업 2. **diff 제시**: 변경 내용 diff 형식으로 제시 후 확인 3. **작은 단계**: 각 단계를 독립적으로 완료하고 검증 4. **테스트 우선**: 테스트 스크립트 먼저 작성 후 구현 5. **기존 코드 유지**: topology.py, mapper.py는 기존 유지 (이미 잘 구현됨) --- ## 다음 시작 시 1. 이 파일의 체크리스트에서 첫 번째 미완료 항목부터 시작 2. 각 단계 완료 시 체크리스트 업데이트 3. 문제가 발생하면 해당 단계에서 중단하고 원인 분석 4. 완료 기준을 충족해야 다음 단계로 진행