# 진단계측 변경 파일 목록 (배포용) — 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단계를 따르십시오.