EVD-336  재시도 코디네이터는 빈이지만 그것을 부르는 것이 없고, ADR 이 지목한 강제 수단은 존재하지 않는다
측정일 2026-09-01 · revision 21234e38 · workmachine

────────────────────────────────────────────────────────────────────────
1. 다시 잰 이유
────────────────────────────────────────────────────────────────────────
root-tree 의 case:a-retry-implementation-nobody-calls 는 "재시도 구현이 둘이고 정교한 쪽을
아무도 호출하지 않는다"로 판정한다. 그런데 참조를 세면 프로덕션 코드가 그것을 만든다.

  app-bootstrap/.../autoconfigure/jpa/JpaPlatformRuntimeAutoConfiguration.java:167-179
      @Bean
      @ConditionalOnMissingBean
      @ConditionalOnBean(SpringJpaTransactionExecutor.class)
      public FullTransactionRetryCoordinator jpaRetryCoordinator(
          SpringJpaTransactionExecutor executor, RetryEventListener retryListener, Clock clock) {
        return new JpaTransactionAutoConfiguration(clock)
            .retryCoordinator(executor, RetryProfile.boundedContention("jpa-platform-default", 3),
                              retryListener);
      }

즉 "만들어지지 않는다"는 아니다. 사이클 1이 고친 "이름만 AutoConfiguration" 결함의 결과로
지금은 빈이 된다. 그러면 남는 질문은 그 빈을 누가 쓰느냐다.

────────────────────────────────────────────────────────────────────────
2. 소비자를 센다 — 0
────────────────────────────────────────────────────────────────────────
main 소스에서 FullTransactionRetryCoordinator 를 언급하는 파일 전량:

  adapter/.../transaction/FullTransactionRetryCoordinator.java        (자기 자신)
  adapter/.../transaction/SpringJpaTransactionExecutor.java:21        (javadoc 언급뿐)
      "This class does not retry. Retry lives in FullTransactionRetryCoordinator, which calls …"
  app-bootstrap/.../autoconfigure/jpa/JpaPlatformRuntimeAutoConfiguration.java:170  (빈 선언)
  app-bootstrap/.../autoconfigure/jpa/JpaTransactionAutoConfiguration.java:99,107,109  (팩토리)

생성하는 곳 셋, 언급하는 javadoc 하나. **주입받아 호출하는 곳은 없다.**

$ grep -rn "\.execute(" --include=*.java . | grep -i coordinator
  → 일치는 전부 httpclient 의 다른 코디네이터다.
    adapter/outbound/httpclient/.../restclient/DefaultGenericHttpGateway.java:118
    나머지는 httpclient 의 test.
  JPA 코디네이터의 execute 를 부르는 프로덕션 코드: 0

────────────────────────────────────────────────────────────────────────
3. 왜 아무도 부르지 않는가 — 어드바이스가 없다
────────────────────────────────────────────────────────────────────────
ADR-JPA-002 는 재시도가 유스케이스 전체를 다시 돌린다고 정하고, advice 순서를 결정의 일부로 둔다.

  "FullTransactionRetryCoordinator re-enters JpaTransactionExecutor for every attempt, and the
   retry advice is ordered outside Spring's transaction advice so each attempt begins a new
   transaction."

  ## Enforcement
  `FullTransactionRetryCoordinatorTest`; `RetryableJpaTransactionInterceptor.DEFAULT_ORDER`.

두 번째 강제 수단이 존재하지 않는다.

$ grep -rn "RetryableJpaTransactionInterceptor" . (build 제외)
  ./docs/adr/ADR-JPA-002-full-transaction-retry.md:37            ← Enforcement 절
  ./docs/superpowers/plans/2026-08-11-jpa-…-plan.md:938,940,957,974,992,1010,1019
        ← 구현 계획. 패키지 경로가 io.backend.skeleton.* 로 지금 배치와 다르다
  ./docs/reviews/2026-08-14-jpa-module-code-review.md:368,456
        ← 저장소 자신의 리뷰가 이미 지적한다:
          "RetryableJpaTransactionInterceptor 를 실제 method pointcut 과 연결하는 Advisor 도 없다."

Java 소스는 0 건이다. 그리고 대체 경로도 없다:

$ grep -rn "Advisor|MethodInterceptor|Pointcut|@Aspect" --include=*.java \
      app-bootstrap/src/main adapter/outbound/persistence-jpa/src/main
  (일치 0)

────────────────────────────────────────────────────────────────────────
4. 교정된 판정
────────────────────────────────────────────────────────────────────────
"아무도 호출하지 않는다"는 결론은 맞다. 그러나 "만들어지지 않는다"는 함의는 틀리다.
정확한 서술은 이것이다.

  코디네이터는 조건부 빈으로 생성된다. 그것을 어떤 메서드에 적용할 어드바이스가 없어서
  주입받아 호출하는 코드가 하나도 없다. ADR 이 강제 수단으로 지목한 인터셉터 클래스는
  이 저장소에 존재하지 않고, 문서 셋(계획·리뷰·ADR)에만 이름으로 남아 있다.

이 차이가 중요한 이유는 두 가지다.

(a) 진단 방향. "빈이 없다"면 조립을 고치는 문제이고, "적용 지점이 없다"면 어드바이스나
    명시적 호출 경로를 만드는 문제다. 후자다.

(b) ADR 의 신뢰도. Enforcement 절이 존재하지 않는 클래스를 지목한다는 것은, 그 절을 읽고
    "강제되고 있다"고 판단하면 틀린다는 뜻이다. 같은 ADR 의 첫 강제 수단인
    FullTransactionRetryCoordinatorTest 는 실재하고 코디네이터 자체를 검증한다 —
    즉 코디네이터의 동작은 고정되어 있고, 그것이 적용되는지는 고정되어 있지 않다.

부수 관측: 저장소 자신의 2026-08-14 코드 리뷰가 이 공백을 이미 기록했다. 그 리뷰가 지적한
다른 항목들(plain factory, endpoint 미등록)은 이후 고쳐졌고 이 항목은 남아 있다.

애플리케이션 소스는 수정하지 않았다.
