# Roo 작업 지시: 노드맵 대시보드 undefined 필드 수정

## 배경 및 원인

`src/Web/Program.cs` 에 다음 설정이 있음:
```csharp
opt.JsonSerializerOptions.PropertyNamingPolicy = null;  // PascalCase 직렬화
```

이로 인해 C# 익명 객체 shorthand `new { x.Id, x.NodeId }` 등은 PascalCase로 직렬화됨.
프론트엔드(`app.js`)는 camelCase(`r.id`, `r.nodeId`)로 접근 → **모든 값이 `undefined`로 표시됨**.

같은 문제를 Browse 엔드포인트에서도 확인했으며, 명시적 camelCase 익명 객체로 수정 완료:
```csharp
// 수정 전
return Ok(new { success = r.Success, nodes = r.Nodes, error = r.ErrorMessage });

// 수정 후
return Ok(new {
    success = r.Success,
    error   = r.ErrorMessage,
    nodes   = r.Nodes.Select(n => new {
        nodeId      = n.NodeId,
        displayName = n.DisplayName,
        nodeClass   = n.NodeClass,
        hasChildren = n.HasChildren
    })
});
```

---

## 수정 대상 파일

**`src/Web/Controllers/ExperionControllers.cs`**  
클래스: `ExperionNodeMapController`  
메서드: `Query()` (약 571번째 줄)

---

## 현재 코드 (문제)

```csharp
return Ok(new
{
    total = r.Total,
    items = r.Items.Select(x => new
    {
        x.Id, x.Level, x.Class, x.Name, x.NodeId, x.DataType
    })
});
```

`x.Id` → JSON `"Id"` (PascalCase) → JS `r.id` = undefined

---

## 수정 후 코드 (목표)

```csharp
return Ok(new
{
    total = r.Total,
    items = r.Items.Select(x => new
    {
        id       = x.Id,
        level    = x.Level,
        @class   = x.Class,
        name     = x.Name,
        nodeId   = x.NodeId,
        dataType = x.DataType
    })
});
```

`@class` 는 C# 예약어 회피용이며, JSON 직렬화 시 `"class"` 로 정상 출력됨.

---

## 추가 확인 사항 (같은 패턴이 있는지 전수 검사)

`ExperionControllers.cs` 전체에서 `PropertyNamingPolicy = null` 환경에서 PascalCase로 직렬화될 수 있는 패턴을 모두 찾아 수정:

1. `new { x.PropertyName }` 형태의 shorthand 익명 객체
2. 직접 typed record/class 인스턴스를 `Ok(...)` 에 넣는 경우

단, 다음은 이미 lowercase이므로 수정 불필요:
- `new { success = ..., nodes = ... }` — 명시적 소문자 키
- `new { total = ..., names = ... }` — 명시적 소문자 키

---

## 빌드 검증

수정 후 반드시:
```bash
dotnet build src/Web/ExperionCrawler.csproj --no-restore -v q
```
- `Build succeeded` 확인
- 에러 0건 확인

---

## 클로드 코드 검수 항목

수정 완료 후 아래 내용을 검수 요청:
1. `ExperionNodeMapController.Query()` 응답 필드가 모두 camelCase인지
2. 같은 패턴(`{ x.Prop }`)이 다른 컨트롤러에도 있는지 확인 여부
3. 빌드 성공 여부
4. `@class` → JSON `"class"` 직렬화 정상 작동 여부
