# 진단계측 변경 파일 목록 (배포용) — 2026-08-04
| 항목 | 내용 |
|---|---|
| 대상 | LGES-OC5-PtoP-Welder / ILSOS_PrismaticRD_PTOP |
| 목적 | 진단계측이 들어간 **파일 5개**를 현장/작업 PC로 옮기기 위한 목록 |
| 마커 | `[진단계측 2026-08-04]` |
| 적용 문서 | `docs/작업지시서/2026-08-04_Laser_Recipe_Save_진단계측.md` |
| 원복 문서 | `docs/작업지시서/2026-08-04_Laser_Recipe_Save_진단계측_원복.md` |
| 브랜치 | `feature/ubisam-pptx-integration` |
## 마커 규칙
계측으로 넣은 코드는 **전부** 아래 문자열을 포함합니다. 저장소에서 이 문자열만 검색하면 손댄 곳을 빠짐없이 찾을 수 있습니다.
```
[진단계측 2026-08-04]
```
소스 안에서는 시작/끝이 쌍을 이룹니다.
```csharp
// ═══ [진단계측 2026-08-04] 시작 ═══
… 이 사이가 전부 계측 코드 …
// ═══ [진단계측 2026-08-04] 끝 ═══
```
각 블록 머리 주석에 **원본 코드가 그대로 적혀 있습니다.** 문서 없이 소스만 보고도 되돌릴 수 있습니다.
---
## 변경 파일 5개
경로는 저장소 루트(`E:\Work\GIT\LGES-OC5-PtoP-Welder`) 기준입니다.
| # | 파일 | 구분 | 마커 쌍 | 요지 |
|---|---|---|---|---|
| 1 | `WeldingComponents\WeldingCommon\Utils\RecipeTrace.cs` | **신규** | 파일 전체 | 계측 본체. 흔적 기록·지문·팝업 |
| 2 | `WeldingComponents\WeldingCommon\WeldingCommon.csproj` | 수정 | 1 (주석) | 위 신규 파일 빌드 등록 |
| 3 | `WeldingComponents\WeldingCommon\Utils\RecipeHelper.cs` | 수정 | 3 | 대상 변경·저장·내용 전환 계측 |
| 4 | `WeldingComponents\LASA\GUI\Page\MainPage.cs` | 수정 | 2 | Page(FieldHelper.json) 기록 훅 |
| 5 | `WeldingComponents\WeldingCommon\Utils\CommonHelper.cs` | 수정 | 1 | 위 훅 연결 |
프로젝트는 2개(`WeldingCommon`, `LASAGUI`)에 걸칩니다. **`ILSOS_PrismaticRD_PTOP` 소스는 손대지 않았습니다.**
---
## 파일별 상세
### 1. `WeldingComponents\WeldingCommon\Utils\RecipeTrace.cs` — 신규
파일 전체가 진단 전용입니다. 원복 시 **파일째 삭제**합니다.
| 공개 멤버 | 역할 |
|---|---|
| `Mark(evt, detail)` | 한 줄 흔적 기록. 호출 시점의 선택/메모리/LASA마커/활성/설비상태/스레드/호출자를 함께 남김 |
| `BeforeSave(recipeName, targetPath)` | 저장 **직전** 스냅샷. 신원 어긋남 3종(`arg`/`path`/`marker`) 판정 |
| `AfterSave(snap)` | 저장 **직후** 재측정. 무엇이 무엇으로 바뀌었는지 판정 + 팝업 |
| `MemFingerprint()` | 메모리(`ScannerCanvasUserCtrl.ScannerParams`) 지문 |
| `FileFingerprint(path)` | 레시피 파일 지문 |
| `Attach()` | `MainPage.Tracer` 에 `Mark` 연결 (4번 파일용) |
**동작 스위치** (파일 상단 상수)
| 상수 | 기본값 | 의미 |
|---|---|---|
| `ALWAYS_SHOW_ON_SAVE` | `false` | `true` 면 **저장할 때마다** 팝업. 흐름을 눈으로 볼 때만 사용 |
| `SHOW_IN_AUTO` | `false` | `true` 면 Auto 중에도 팝업. **양산 중에는 켜지 말 것** (모달이 시퀀스를 세움) |
**출력** — `D:\ILSOSConfig\ILSOS_PrismaticRD_PTOP\RecipeTrace.txt` (append). 팝업을 놓쳐도 여기 남습니다.
### 2. `WeldingComponents\WeldingCommon\WeldingCommon.csproj` — 수정
**위치**: `Utils\RecipeHelper.cs` 항목 바로 뒤 (≈273행)
```xml
```
구식 csproj 라 **이 등록이 없으면 신규 파일이 빌드에 포함되지 않습니다.**
### 3. `WeldingComponents\WeldingCommon\Utils\RecipeHelper.cs` — 수정 (마커 3쌍)
| 블록 | 위치(현재) | 원본 | 넣은 것 |
|---|---|---|---|
| 3-1 | **18~32행** `SelectedRecipe` | 필드 1줄 | **필드 → 프로퍼티** 전환. setter 에서 `Mark("대상변경 SELECTED")` |
| 3-2 | **51~65행** `SaveRecipe` | 본문 1줄 | 저장 전 `BeforeSave` / 저장 후 `AfterSave` |
| 3-3 | **90~115행** `ReloadRecipe` | 본문 3줄 | `try/catch` 로 감싸 성공·실패·**무변화** 구분 기록. `throw;` 로 예외 전파 보존 |
**3-1이 핵심입니다.** `SelectedRecipe` 대입은 저장소 전체에 4곳뿐이고 나머지는 전부 읽기라, setter 한 곳에서 **4개 지점이 호출자까지 자동으로** 잡힙니다.
| 대입 지점 | 경로 |
|---|---|
| `UCScannerObjectTeachingViewModel.cs:114` | 신규 레시피 생성 |
| `UCScannerObjectTeachingViewModel.cs:165` | `OnChanged` |
| `UCScannerObjectTeachingViewModel.cs:172` | `Reloaded` |
| `RecipeHelper.cs:76`(원본 기준) | `OnActiveReloaded` |
**3-3에서 나오는 두 문구가 원인 확정의 근거입니다.**
| 문구 | 의미 |
|---|---|
| `*** RELOAD 실패 ***` | 선행문서 **원인 (1)** 확정. 대상만 바뀌고 내용은 직전 레시피에 남음 |
| `RELOAD 완료(내용무변화!)` | `Recipe.cs:64` **무동작 가설** 확정. 경로 비교로는 못 잡는 케이스 |
### 4. `WeldingComponents\LASA\GUI\Page\MainPage.cs` — 수정 (마커 2쌍)
**왜 필요한가** — `FieldHelper.json`(Page 데이터)을 실제로 쓰는 건 `SaveAndLoadFieldScanFromLasaDb()` 이고, 호출처 4곳 중 `SaveRecipe` 안에 있는 건 **1곳뿐**입니다. 나머지는 Save 없이도 파일을 씁니다.
| 호출처 | Save 경로 안인가 |
|---|---|
| `MainPage.cs:433` — `SaveRecipe` | ✓ |
| `MainPage.cs:448,452` — `ReloadSetting()` | ✗ |
| `MainPage.cs:502,505` — `UpdateScoutField()` (Scout 필드 조작) | ✗ |
| `MainPage.cs:1433` — 콤보박스 `SelectedIndexChanged` (**페이지 바꿀 때마다**) | ✗ |
게다가 경로를 `WorkRecipeFile` 기준으로 정합니다(원본 `:537`). 즉 **`WorkRecipeFile` 이 어긋난 상태에서 페이지를 넘기기만 해도** 엉뚱한 레시피 폴더의 `FieldHelper.json` 이 덮어써질 수 있습니다. `_suppressPageFieldSync` 가드(`:1422`, 2026-06-20 추가)는 `ReloadRecipe` **도중**의 발화만 막고 평상시 페이지 전환은 그대로 씁니다.
**넣은 것**
| 블록 | 위치(현재) | 내용 |
|---|---|---|
| 4-1 | ≈**535~540행** (`SaveAndLoadFieldScanFromLasaDb` 바로 위) | `public static Action Tracer;` 필드 |
| 4-2 | ≈**545~548행** (`newpath` 계산 직후, `SaveFieldHelper` 직전) | `Tracer?.Invoke("PAGE 저장 FieldHelper", …)` |
함수 한 곳에 넣어 **호출처 4곳이 전부** 잡힙니다. 기록되는 값은 실제 기록 경로(`newpath`)와 그 경로가 **`WorkRecipeFile` 에서 왔는지 인자로 지정됐는지**입니다 — 오염 판정의 핵심입니다.
> **델리게이트를 쓰는 이유** — 참조 방향이 `WeldingCommon` → `LASAGUI` 단방향이라 `MainPage` 에서 `RecipeTrace` 를 직접 부를 수 없습니다. `Tracer` 는 `Action` 이라 역참조가 생기지 않고, 연결은 5번 파일에서 합니다. `Tracer` 가 안 꽂히면 `?.` 로 조용히 무시되므로 **계측이 없어도 원래대로 동작합니다.**
### 5. `WeldingComponents\WeldingCommon\Utils\CommonHelper.cs` — 수정 (마커 1쌍)
**위치**: `SetMainPage()` 안, ≈17~20행
```csharp
RecipeTrace.Attach(); // MainPage.Tracer 에 RecipeTrace.Mark 를 연결
```
`SetMainPage` 는 기동 시 `MainPage` 가 준비되는 시점에 호출되므로, 페이지 조작보다 먼저 훅이 걸립니다.
---
## 현장/작업 PC 배포 절차
> [!] **소스 파일만 복사해서는 설비가 바뀌지 않습니다. 반드시 재빌드해야 합니다.**
1. **백업**
- `D:\ILSOSConfig\ILSOS_PrismaticRD_PTOP\_config_recipe` 폴더 통째로 복사
- 덮어쓸 소스 4개(2·3·4·5번)의 현재 버전 백업 — 원복 시 대조용
2. **파일 5개 복사** (위 표의 경로 그대로, 폴더 구조 유지)
3. **csproj 확인** — Visual Studio 솔루션 탐색기에 `RecipeTrace.cs` 가 보이는지. 안 보이면 2번 파일이 제대로 안 갔거나 [기존 항목 추가]가 필요합니다.
4. **빌드** — `ILSOS_All.sln` → **Release | x64**. 실패 시 진행 중단.
5. **배포** — 빌드 산출물을 설비 실행 경로로 반영.
6. **검증** (아래 체크리스트)
## 배포 후 확인 체크리스트
- [ ] 빌드 성공 (경고를 사소하게 넘기지 말 것)
- [ ] `SelectedRecipe` 관련 컴파일 에러 없음 — 있으면 튜플 멤버 직접 대입(`SelectedRecipe.name = …`)이나 `ref`/`out` 전달이 어딘가 있다는 뜻 (사전 조사 시점 **0건**)
- [ ] Manual 상태에서 레시피 선택 → 파라미터 수정 → Save → **팝업이 뜨지 않고** 정상 저장
- [ ] `D:\ILSOSConfig\ILSOS_PrismaticRD_PTOP\RecipeTrace.txt` 생성됨
- [ ] 그 안에 `SAVE 직전` / `SAVE 직후` 줄이 있음 → 3번 파일 계측 살아있음
- [ ] 페이지 콤보박스를 넘기면 `PAGE 저장 FieldHelper` 줄이 찍힘 → 4·5번 파일 계측 살아있음
- [ ] 레시피 전환 시 `대상변경 SELECTED` / `내용변경 RELOAD 진입` / `RELOAD 완료` 줄이 찍힘
**마지막 두 항목이 안 찍히면 계측이 반만 동작하는 것입니다.** `PAGE 저장 FieldHelper` 가 없으면 `Tracer` 연결(5번)이 안 된 것이니 `CommonHelper.SetMainPage` 수정분이 제대로 갔는지 확인하십시오.
## 현장 데이터 회수
사고(팝업) 발생 시:
1. **팝업 화면 전체 촬영** — 맨 위 `결론` 줄과 `무엇이 무엇으로 바뀌었나` 블록이 핵심
2. `RecipeTrace.txt` 회수 (**삭제 전 반드시 사본 확보**)
3. 발생 시각, 직전 조작(레시피 전환/페이지 전환/Auto→Manual 등) 메모
4. `_config_recipe` 폴더의 해당 시점 상태 보존
## 주의
- 이 계측은 **저장을 막지 않습니다.** 팝업이 뜨는 시점엔 파일이 이미 덮어써진 뒤입니다. 백업이 유일한 안전장치입니다.
- Save 1회당 레시피 파일 파싱이 4회 늘어 **저장이 느려질 수 있습니다.** 체감되면 `BeforeSave`/`AfterSave` 의 활성 파일 지문 계산만 제거하십시오 (판정 하나만 약해집니다).
- Auto 중에는 팝업이 뜨지 않고 파일에만 남습니다(`SHOW_IN_AUTO = false`).
- **계측은 버그 수정이 아닙니다.** 원인 확정 후 원복하고, 실제 수정은 선행 문서
`작업지시서_2026-08-03_Laser_Recipe_Save_교차오염.txt` 의 1~4단계를 따르십시오.