docs: Copy/Rename 위험도 재평가 반영 (ISSUE-260904-02)

This commit is contained in:
노도연 2026-09-04 15:35:56 +09:00
parent 3584cacc6e
commit 468499d559

View File

@ -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 가 **의도적으로** 신원을 위반하므로