# Quality Improvements — 구현 품질 정리 ## 이 파일을 읽는 구현 에이전트에게 각 항목의 체크리스트를 완료로 표시하고, 중간 검증 명령을 실제로 실행한 뒤 출력을 `CODE_REVIEW.md`의 `검증 결과` 섹션에 붙여넣으세요. 최종 검증까지 모두 통과한 후 `CODE_REVIEW.md` 완성 여부 표를 `[x]`로 채우세요. ## 배경 코드베이스 전반 평가에서 발견된 사소하지만 일관성을 깨는 네 가지 문제를 수정합니다. PROTOCOL.md 상태 표가 이미 완료된 TypeScript·Python을 Planned로 표기하고 있고, Python `Communicator._shutdown`이 외부에서 private 메서드로 직접 호출되며, Kotlin `nextNonce()`가 불필요하게 public으로 노출됩니다. 또한 VERSIONING.md에 `nonce` int32 overflow 정책이 빠져있습니다. ## 의존 관계 및 구현 순서 REFACTOR-2(Python) → REFACTOR-3(Kotlin) → REFACTOR-1(PROTOCOL.md) → REFACTOR-4(VERSIONING.md) 순서로 진행합니다. 코드 변경 후 문서 업데이트. --- ### [REFACTOR-1] PROTOCOL.md 구현 상태 표 업데이트 **문제** [PROTOCOL.md:183-184](../PROTOCOL.md) — TypeScript와 Python이 "Planned"로 기재되어 있으나 두 언어 모두 구현 완료 상태입니다. ```markdown | TypeScript | Planned | `typescript/` | ← 183번 줄 | Python | Planned | `python/` | ← 184번 줄 ``` **해결 방법** 두 행의 `Planned` → `Available`로 교체합니다. ```markdown | TypeScript | Available | `typescript/` | | Python | Available | `python/` | ``` **수정 파일 및 체크리스트** - [x] `PROTOCOL.md` — 183번 줄 `TypeScript | Planned` → `TypeScript | Available` - [x] `PROTOCOL.md` — 184번 줄 `Python | Planned` → `Python | Available` **테스트 작성** 문서 전용 변경이므로 테스트 불필요. **중간 검증** ```bash grep "TypeScript\|Python" PROTOCOL.md | grep "Planned" # 출력 없음이 정상 grep "TypeScript\|Python" PROTOCOL.md | grep "Available" # TypeScript | Available, Python | Available 두 줄 출력 ``` --- ### [REFACTOR-2] Python `_shutdown` → `shutdown` 공개 메서드 전환 **문제** [python/toki_socket/base_client.py:51](../python/toki_socket/base_client.py) — `BaseClient.close()`가 `Communicator`의 private 메서드를 직접 호출합니다. ```python self.communicator._shutdown() # ← 51번 줄, private 접근 ``` Go/TypeScript/Kotlin은 모두 `shutdown()` public 메서드를 노출합니다. Python만 `_shutdown()` 형태여서 API 일관성이 깨집니다. **해결 방법** `communicator.py`에서 `_shutdown` → `shutdown`으로 이름을 바꾸고, `close()` 내부 self 호출도 함께 수정합니다. `base_client.py`도 맞춰 업데이트합니다. Before (`communicator.py:67`): ```python def _shutdown(self) -> None: ``` After: ```python def shutdown(self) -> None: ``` Before (`communicator.py:83`): ```python self._shutdown() ``` After: ```python self.shutdown() ``` Before (`base_client.py:51`): ```python self.communicator._shutdown() ``` After: ```python self.communicator.shutdown() ``` **수정 파일 및 체크리스트** - [x] `python/toki_socket/communicator.py:67` — `def _shutdown` → `def shutdown` - [x] `python/toki_socket/communicator.py:83` — `self._shutdown()` → `self.shutdown()` - [x] `python/toki_socket/base_client.py:51` — `self.communicator._shutdown()` → `self.communicator.shutdown()` **테스트 작성** 기존 [python/test/test_communicator.py:94](../python/test/test_communicator.py) `test_shutdown()`은 `communicator.close()`를 통해 간접 검증합니다. 직접 `shutdown()`을 호출하는 케이스가 없으므로, public 메서드를 직접 검증하는 테스트를 한 건 추가합니다. - 파일: `python/test/test_communicator.py` - 테스트명: `test_shutdown_public_method` - 단언 목표: `communicator.shutdown()` 직접 호출 후 `is_alive() == False` **중간 검증** ```bash cd python && python -m pytest test/test_communicator.py -v # PASSED test_shutdown_public_method 포함 전체 통과 ``` --- ### [REFACTOR-3] Kotlin `nextNonce()` 접근자를 `internal`로 좁히기 **문제** [kotlin/src/main/kotlin/com/tokilabs/toki_socket/Communicator.kt:92](../kotlin/src/main/kotlin/com/tokilabs/toki_socket/Communicator.kt) — `nextNonce()`가 public으로 선언됩니다. ```kotlin fun nextNonce(): Int = nonce.incrementAndGet() // ← 92번 줄 ``` Go는 소문자(`nextNonce`) 패키지 전용, TypeScript는 `private nextNonce()`. Kotlin만 외부에서 nonce를 증가시킬 수 있어 의도치 않은 상태 오염이 가능합니다. `addRequestListenerTyped`와 `sendRequestTyped`는 같은 파일 내 top-level 함수로, `internal`이면 접근 가능합니다. **해결 방법** Before (`Communicator.kt:92`): ```kotlin fun nextNonce(): Int = nonce.incrementAndGet() ``` After: ```kotlin internal fun nextNonce(): Int = nonce.incrementAndGet() ``` **수정 파일 및 체크리스트** - [x] `kotlin/src/main/kotlin/com/tokilabs/toki_socket/Communicator.kt:92` — `fun nextNonce` → `internal fun nextNonce` **테스트 작성** Kotlin 테스트(`src/test/`)는 `nextNonce()`를 직접 호출하지 않으므로 테스트 변경 불필요. `internal` 키워드는 같은 모듈 내 테스트에서는 계속 접근 가능하므로 기존 테스트 깨짐 없음. **중간 검증** ```bash cd kotlin && ./gradlew test # BUILD SUCCESSFUL, 0 failures ``` --- ### [REFACTOR-4] VERSIONING.md에 nonce overflow 정책 추가 **문제** [VERSIONING.md](../VERSIONING.md) — `nonce`는 `int32` 타입으로 ~21억 메시지 후 overflow합니다. 현재 문서에 overflow 시 동작이 명시되지 않아, 새 언어 구현자가 wrapping·연결 재시작 여부를 독자적으로 판단해야 합니다. **해결 방법** `VERSIONING.md`의 "Non-breaking Protocol Changes" 섹션 바로 아래에 `## nonce Overflow` 항목을 추가합니다. ```markdown ## nonce Overflow `nonce`와 `responseNonce` 필드는 protobuf `int32`(부호 있는 32비트)입니다. 단일 연결에서 약 21억 회 송신 후 overflow가 발생합니다. 현재 정책: - 프로토콜은 overflow를 정의하지 않는다. 단일 연결에서 int32 한계에 도달하는 경우는 현실적이지 않다. - 구현체는 overflow에 대한 복구 논리를 추가하지 않는다. - 만약 미래에 overflow 처리가 필요해지면 프로토콜 버전을 올리고 wrap-around 여부를 명시한다. ``` **수정 파일 및 체크리스트** - [x] `VERSIONING.md` — "Non-breaking Protocol Changes" 섹션 아래에 `## nonce Overflow` 항목 추가 **테스트 작성** 문서 전용 변경이므로 테스트 불필요. **중간 검증** ```bash grep -A 10 "nonce Overflow" VERSIONING.md # 추가된 섹션 출력 ``` --- ## 수정 파일 요약 | 파일 | 항목 | |------|------| | `PROTOCOL.md` | REFACTOR-1 | | `python/toki_socket/communicator.py` | REFACTOR-2 | | `python/toki_socket/base_client.py` | REFACTOR-2 | | `python/test/test_communicator.py` | REFACTOR-2 | | `kotlin/src/main/kotlin/com/tokilabs/toki_socket/Communicator.kt` | REFACTOR-3 | | `VERSIONING.md` | REFACTOR-4 | ## 최종 검증 ```bash # Python 전체 테스트 cd python && python -m pytest -v # 모든 테스트 PASSED # Kotlin 전체 테스트 cd kotlin && ./gradlew test # BUILD SUCCESSFUL # 문서 확인 grep "TypeScript\|Python" PROTOCOL.md | grep "Available" grep "nonce Overflow" VERSIONING.md # 두 항목 모두 출력 ```