docs: [changes] 운영 코드 안전성 검토 결과 추가
- 수정 2개 파일의 동작 동등성 검증 (수정 전 = 수정 후) - 엣지 케이스 5건 검증 (null, 빈 배열, 없는 ID 등) - 전체 256개 테스트 결과, 수정으로 인한 실패 0건 확인 - 기존 문제 발견: process_items tenant_id 필터 누락
This commit is contained in:
@@ -231,6 +231,77 @@ foreach ($bendingItems as $item) {
|
||||
|
||||
---
|
||||
|
||||
## 4. 운영 코드 안전성 검토
|
||||
|
||||
배포 후 수정된 운영 코드(테스트 파일 제외)가 기존 API 동작에 영향을 미치는지 코드 리뷰 + 전체 테스트로 검증했다.
|
||||
|
||||
### 4.1 검토 대상
|
||||
|
||||
실제 운영 코드를 수정한 파일은 **2개뿐**이다. 나머지 22개는 모두 테스트/Factory 파일이다.
|
||||
|
||||
| 파일 | 수정 메서드 | 수정 내용 |
|
||||
|------|-----------|----------|
|
||||
| `WorkOrderService.php` | `getMaterials()` | BOM 루프 내 `find()` → 배치 사전 로드 |
|
||||
| `OrderService.php` | `createWorkOrderFromOrder()` | fallback 루프 내 DB 쿼리 → 배치 사전 조회 |
|
||||
| `OrderService.php` | `checkBendingStockForOrder()` | StockService 루프 호출 → 배치 조회 |
|
||||
|
||||
### 4.2 동작 동등성 검증 (수정 전 = 수정 후)
|
||||
|
||||
| 수정 | 판정 | 근거 |
|
||||
|------|:----:|------|
|
||||
| `getMaterials()` BOM 배치 | **동등** | null 처리, 빈 배열, BOM 없는 경우 모두 동일. `$bomItemsMap[$id] ?? null`이 `find($id)`와 동일한 null 반환 |
|
||||
| `createWorkOrderFromOrder()` fallback | **동등** | 사전 배치 조회 결과가 즉석 조회와 동일. `DB::transaction` 내부이므로 중간 데이터 변경 없음. 캐시(`codeToIdMap`) 동작도 동일 |
|
||||
| `checkBendingStockForOrder()` Stock | **동등** | `Stock::whereIn()` 결과가 `StockService::getAvailableStock()` 결과와 동일. `BelongsToTenant` 스코프 + 명시적 `tenant_id` 조건으로 격리 보장 |
|
||||
|
||||
### 4.3 엣지 케이스 검증
|
||||
|
||||
| 케이스 | 수정 전 | 수정 후 | 동일? |
|
||||
|--------|--------|--------|:-----:|
|
||||
| `item_id`가 null인 품목 | `if ($woItem->item_id)` skip | 맵에 포함되지 않아 동일하게 skip | ✅ |
|
||||
| BOM JSON이 비어있는 품목 | `empty($item->bom)` skip | 동일 | ✅ |
|
||||
| DB에 없는 `item_code` | `find()` → null | `$map[$code] ?? null` → null | ✅ |
|
||||
| 재고가 0인 품목 | Stock 없음 → available_qty=0 | `$stocksMap->get($id)` → null → 0 | ✅ |
|
||||
| 빈 주문 (items 0건) | 루프 미실행 | 배치 조회도 빈 배열, 루프 미실행 | ✅ |
|
||||
|
||||
### 4.4 전체 테스트 실행 결과
|
||||
|
||||
```
|
||||
PHPUnit 11.5.27 / PHP 8.4.18
|
||||
|
||||
전체: 256개 테스트 실행
|
||||
통과: 243개
|
||||
실패: 7개 (모두 수정 전부터 존재하던 기존 문제)
|
||||
Skip: 6개
|
||||
|
||||
이번 수정으로 인한 실패: 0건
|
||||
```
|
||||
|
||||
**실패 7건 상세 (모두 기존 문제):**
|
||||
|
||||
| 테스트 | 원인 | 이번 수정과 관계 |
|
||||
|--------|------|:--------------:|
|
||||
| `PrefixResolverTest` (1건) | Unit 로직 불일치 (XX vs CF) | 무관 |
|
||||
| `BendingLotPipelineTest` (3건) | TENANT_ID=287 고정, 로컬 DB 데이터 없음 | 무관 |
|
||||
| `ItemMasterApiTest` (3건) | `section_id` 컬럼 미존재 (마이그레이션 불일치) | 무관 |
|
||||
|
||||
### 4.5 발견된 기존 문제 (수정과 무관, 별도 대응 필요)
|
||||
|
||||
`process_items` 테이블 조회에 `tenant_id` 필터가 없다. 수정 전부터 존재하던 문제이며 이번 수정으로 악화되지 않았다. 멀티테넌트 격리가 필요하면 별도 수정이 필요하다.
|
||||
|
||||
```php
|
||||
// OrderService.php — tenant_id 조건 누락 (수정 전/후 동일)
|
||||
DB::table('process_items')
|
||||
->whereIn('item_id', $ids)
|
||||
->where('is_active', true) // tenant_id 없음
|
||||
->get();
|
||||
```
|
||||
|
||||
### 4.6 결론
|
||||
|
||||
**이번 수정으로 기존 API 동작이 깨지는 경우는 없다.** 수정 전과 후의 결과가 정확히 동일하며, 쿼리 수만 줄어든 순수 성능 개선이다.
|
||||
|
||||
---
|
||||
|
||||
## 테스트 체크리스트
|
||||
|
||||
- [x] TestCase 공통 헬퍼 작성 및 기존 11개 테스트 호환 확인
|
||||
|
||||
Reference in New Issue
Block a user