## 15. P2 — SDK가 선언한 두 진입점에 구현이 없다

`RedisOperations`는 자신을 "Synchronous entry point to the typed Redis API"라고 소개하고, `ReactiveRedisOperations`가 그 reactive 짝이다. 두 인터페이스는 각각 12개 접근자(`values()`·`hashes()`·`lists()`·`sets()`·`sortedSets()`·`bitmaps()`·`bitFields()`·`hyperLogLogs()`·`geo()`·`streams()`·`keys()`·`batches()`)를 선언한다.

**둘 다 구현체가 없다.** leaf 전체의 `implements` 전수 조사(`160-...` §8.1 후속)에서 개별 표면은 전부 구현돼 있다 — sync 26종(`LettuceRedisValueOperations`·`LettuceRedisHashOperations`·… `LettuceRedisAdminOperations`·`LettuceRedisSearchOperations`까지), reactive 17종. 그런데 `implements RedisOperations` / `implements ReactiveRedisOperations`는 **0건**이다.

`main` 안에서 두 타입을 이름으로 부르는 곳도 없다. 유일한 참조가 `ReactiveRedisOperations:19`의 javadoc `{@link}` 하나와, test인 `ApiParityTest:97-98`의 반사 두 줄이다.

결과적으로 이 SDK를 쓰는 코드는 `RedisOperations`를 **얻을 수 없다**. 12개 표면을 각각 어디선가 따로 받아야 하고, 진입점이 약속하는 "하나의 객체에서 타입 있는 표면 전체" 는 존재하지 않는다. facade에 접근자를 추가하고 reactive 짝을 맞추는 규율(§14)은 실행되고 있는데, 그 facade를 만드는 코드는 없다.

**판정: P2.** 데이터 위험은 없다 — 없는 타입은 잘못된 답을 주지 않는다. 위험은 API 계약의 신뢰다: 이 leaf의 공개 표면 중 **가장 먼저 읽히는 두 타입**이 구현되지 않은 상태이고, 대칭 test가 그 사실을 가리지 못한다(인터페이스끼리만 비교하므로). sub-scope 01의 §5와 방향이 반대이면서 원인은 같다 — 조립이 절반이다. 수정은 이미 존재하는 26개 구현을 묶는 `LettuceRedisOperations` / `LettuceReactiveRedisOperations` 두 클래스를 추가하고, `ApiParityTest`에 "두 facade는 구현을 가진다"는 검사를 더하는 것이다.

## 16. P3 — Pub/Sub 채널만 렌더 크기 검증을 받지 않는다

`RedisKeyRules.requireRenderedSize(...)`는 조립된 키 문자열이 설정된 최대 바이트를 넘지 않는지 본다. 세 형제 중 하나만 그것을 부른다.
