<!-- task=edge_node_arch plan=1 tag=REVIEW_REFACTOR -->

# Plan - REVIEW_REFACTOR

## 개요

date=2026-05-02
task=edge_node_arch, plan=1, tag=REVIEW_REFACTOR
parent=REFACTOR (code_review_0.log)

## 배경

REFACTOR 코드리뷰에서 발견된 Suggested 이슈 수정.

---

## [REVIEW_REFACTOR-1] onNodeConnected disconnect 리스너 순서 수정

### 문제

`apps/edge/internal/transport/server.go`의 `onNodeConnected` 고루틴에서
`s.registry.Register(entry)` 이후에 `client.AddDisconnectListener`가 등록됨.
두 호출 사이에 node가 disconnect되면 이벤트가 리스너 등록 전에 발생해
registry에 stale entry가 영구 잔존할 수 있음.

### 해결

`AddDisconnectListener` 블록을 `registry.Register` 이전으로 이동.

Before (`server.go:101-110`):
```go
s.registry.Register(entry)
s.logger.Info("node registered",
    zap.String("node_id", entry.NodeID),
    zap.Int("adapters", len(entry.Adapters)),
)

client.AddDisconnectListener(func(_ *toki.TcpClient) {
    s.registry.Unregister(entry.NodeID)
    s.logger.Info("node unregistered", zap.String("node_id", entry.NodeID))
})
```

After:
```go
client.AddDisconnectListener(func(_ *toki.TcpClient) {
    s.registry.Unregister(entry.NodeID)
    s.logger.Info("node unregistered", zap.String("node_id", entry.NodeID))
})

s.registry.Register(entry)
s.logger.Info("node registered",
    zap.String("node_id", entry.NodeID),
    zap.Int("adapters", len(entry.Adapters)),
)
```

### 체크리스트

- [x] `server.go`에서 `AddDisconnectListener` 블록이 `registry.Register` 이전에 위치

### 테스트 결정

기존 registry_test.go는 Register/Unregister 순서를 직접 테스트하지 않으므로 코드 변경만으로 충분.

### 중간 검증

```
$ PATH=/config/go-sdk/go/bin:/config/go-sdk/bin:$PATH go build ./apps/edge/...
```

---

## 최종 검증

```
$ PATH=/config/go-sdk/go/bin:/config/go-sdk/bin:$PATH go build ./...
$ PATH=/config/go-sdk/go/bin:/config/go-sdk/bin:$PATH go test ./...
```
