diff --git a/Doc/인수인계/260904_레시피저장_교차오염_트리거차단.md b/Doc/인수인계/260904_레시피저장_교차오염_트리거차단.md index 59b1ca8..3d74477 100644 --- a/Doc/인수인계/260904_레시피저장_교차오염_트리거차단.md +++ b/Doc/인수인계/260904_레시피저장_교차오염_트리거차단.md @@ -192,7 +192,7 @@ if (string.Equals(activeRecipe.Name, selectedNameOnActivate, StringComparison.Or | 모달에 선택/활성 값 표시 | 🟦 정상 (`FindStrToken` 통과 확인) | | **`PreSaved`=false 시 Aurora 가 실제로 저장 중단** | 🟦 **확증** — 소스 부재로 추정만 하던 사항 | | 평소 저장(활성=선택)이 막히지 않는지 | 🟨 미확인 | -| **레시피 복사·이름변경 → 활성화** | 🟨 **미확인 (최우선)** | +| 레시피 복사·이름변경 → 활성화 | 🟨 미확인 (§9-2 재평가로 **우선순위 하향**) | | 자동 사이클 페이지 전환 | 🟨 미확인 | > `PreSaved` 가 `false` 를 반환하면 Aurora 가 **`Save Failed` 모달을 추가로 띄운다** @@ -207,7 +207,43 @@ if (string.Equals(activeRecipe.Name, selectedNameOnActivate, StringComparison.Or Aurora 가 **활성화 없이 뷰어만 전환**하는 흐름을 가졌다면, 정상 상황인데도 저장이 막힌다. 막히면 판정 조건을 **로드 파일 신원**(`DB.Recipe.Recipe.SelectedRecipeFile`) 기준으로 바꾸면 된다. 그 비교 코드는 `RecipeHelper.cs:48-55` 에 `[관측]` 로그로 **이미 들어가 있다**(차단만 안 할 뿐). -2. **Copy/Rename 분기 공백** — 위 §7 ① 참조. 배포 상태에서 반드시 1회 시험할 것. +2. **Copy/Rename 분기 공백** — 위 §7 ① 참조. 아래 2.1 에서 재평가했다. + +### 9.1 파일 부재 시 예외는 확실히 던져진다 🟩 + +`DB.Recipe.Recipe.Load(string)` (`LASA/GUI/DB/Recipe.cs:42-73`) 는 `.json` 이면 `File.ReadAllText`, +아니면 `new StreamReader` 로 읽고 **`catch` 에서 `throw ex;` 로 재전파**한다. +`MainPage.ReloadRecipe` 는 잡지 않고 `RecipeHelper.ReloadRecipe:116` 도 `throw;` 로 다시 던진다. +`OnActiveReloaded` 호출부가 전부 Rx `Subscribe` 안이므로(`UCMainAutoRunViewModel:174`, +`EquipmentSetup:286`, `RMSHandlerForPTOP:64`) **구독이 종료된다.** + +### 9.2 종전 코드는 파일 존재를 "보증"하고 있었다 🟩 + +`OnActivatedRecipe` 의 순서가 이렇다. + +``` +① SaveRecipe(활성) ← 파일 생성 (GetTeachingEditorFullPath 가 폴더도 만듦) +② EVENT_CHANGE_RECIPE_INFO 발행 +③ 구독자가 ReloadRecipe 수행 +``` + +**저장이 reload 보다 먼저다.** 즉 무조건 저장은 교차오염의 원인이면서 동시에 **파일 생성 보증**을 +겸하고 있었고, 이번 조건부 변경이 그 보증을 걷어냈다. + +### 9.3 그럼에도 위험도를 낮게 본 이유 🟨 + +남은 미지수는 **"Aurora 가 Copy/Rename 시 레시피 폴더를 통째로 복사하는가"** 하나뿐이다. +복사한다면 파일이 이미 있으므로 문제가 성립하지 않는다. + +- **Aurora 는 레시피를 폴더 단위로 관리하므로 폴더째 복사하는 것이 정상 동작이라고 판단**했다 + (2026-09-04 협의). 다만 **Aurora 소스가 없어 코드로 확인한 것은 아니다 — 합리적 추정이다.** +- 설령 예외가 나더라도 **재기동하면 구독이 다시 걸려 복구된다.** 데이터 손상이 아니라 + 그 세션 동안 레시피 전환만 막히는 상태다. +- 위 두 가지로 "발생 시 즉시 중단" 에서 **일반 검증 항목으로 하향**했다. + +> 선제 방어(조건에 "대상 파일 없으면 저장 허용" 을 OR 로 추가)는 **넣지 않기로 했다.** +> `GetTeachingEditorFullPath` 가 `private` 이라 공용 `RecipeHelper` 를 손대야 하는데, +> 비용 대비 이득이 크지 않다고 판단했다. 필요해지면 이 방법이 가장 작은 조치다. 3. **근본 원인 미해결** — `SaveRecipe` 가 목적지와 내용을 묶어 검증하지 않는다. 가드를 안 거치는 S3(신규생성)·S4(RMS)에는 같은 구멍이 남는다. 근본 대응은 `SaveRecipe` 에 불변식을 넣는 것인데, S3 가 **의도적으로** 신원을 위반하므로