# GLM-4.7-Flash 코드 작업 규칙 (ExperionCrawler) ## 필수 준수 사항 ### 작업 전 - 반드시 `task_state.md`를 먼저 읽어 진행 상태 파악 - 파일 수정 전 반드시 `read_file`로 전체 내용 확인 후 수정 ### 코드 수정 원칙 - 요청된 범위만 수정 — 관련 없는 코드 리팩토링 금지 - 빌드 검증: 각 파일 수정 후 `dotnet build src/Web/ExperionCrawler.csproj --no-restore -v q` 실행 - 빌드 실패 시 즉시 원인 수정 후 재빌드, 다음 항목으로 넘어가지 않음 ### issues.md 작성 형식 ``` | # | 파일 | 심각도 | 분류 | 내용 | 상태 | |---|------|--------|------|------|------| | 1 | src/... | HIGH/MED/LOW | bug/perf/quality/security | 설명 | pending/fixed | ``` 심각도 기준: - HIGH: 런타임 예외, 데이터 손실, 보안 취약점 - MED: 성능 저하, 잘못된 동작, 예외 미처리 - LOW: 코드 품질, 불필요한 코드, 명명 불일치 ### 클로드 검수를 위한 커밋 규칙 - 각 이슈 수정 완료 시: `git add -p` 후 이슈 번호 포함 커밋 예: `fix(#3): ExperionDbContext null 참조 예외 방어 처리` - 전체 완료 후 `REVIEW_REQUEST.md` 생성하여 검수 요청 ### MCP 도구 활용 - `search_codebase`: 관련 코드 패턴 검색에 적극 활용 - `ask_iiot_llm`: IIoT/OPC UA 도메인 판단이 필요할 때 사용 --- ## [CRITICAL] ASP.NET Core 컨트롤러 JSON 직렬화 규칙 ### 배경 (반드시 숙지) `src/Web/Program.cs`에 다음 설정이 있다: ```csharp opt.JsonSerializerOptions.PropertyNamingPolicy = null; // PascalCase 그대로 직렬화 ``` 이로 인해 C# 속성명이 **그대로** JSON 키가 된다. 프론트엔드(`app.js`)는 **모든 JSON 필드를 camelCase**로 접근하므로, PascalCase 키가 오면 **모든 값이 `undefined`** 가 된다. ### 금지 패턴 (절대 사용 금지) ```csharp // ❌ shorthand 익명 객체 — C# 속성명(PascalCase)이 JSON 키로 그대로 사용됨 return Ok(new { x.Id, x.TagName, x.NodeId, x.LiveValue }); // ❌ typed 객체를 Ok()에 직접 전달 — PascalCase 직렬화됨 return Ok(result); return Ok(new MyDto { Id = 1, TagName = "abc" }); ``` ### 올바른 패턴 (항상 명시적 camelCase 매핑) ```csharp // ✅ 항상 명시적으로 소문자 키 지정 return Ok(new { id = x.Id, tagName = x.TagName, nodeId = x.NodeId, liveValue = x.LiveValue, timestamp = x.Timestamp }); // ✅ 컬렉션 포함 응답 return Ok(new { total = r.Total, items = r.Items.Select(x => new { id = x.Id, tagName = x.TagName, nodeId = x.NodeId }) }); ``` ### C# 예약어 처리 `class`는 C# 예약어이므로 `@class`를 사용한다. System.Text.Json이 `"class"`로 정상 직렬화한다: ```csharp // ✅ @class → JSON "class" return Ok(new { id = x.Id, @class = x.Class, name = x.Name }); ``` ### 점검 체크리스트 컨트롤러에서 `Ok(...)` 또는 `return` 사용 시: - [ ] 익명 객체의 모든 키가 소문자(camelCase)인가? - [ ] `new { x.SomeProp }` 형태(shorthand)가 없는가? - [ ] typed record/class를 그대로 반환하지 않는가? - [ ] C# 예약어(`class`, `string` 등)에 `@` 접두사를 붙였는가?