Files
DongHyeonkaandClaude Fable 5.1 b25357c48a docs(clean-architecture-backend-template): fold analysis into final and re-select one topic
- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다
- 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5
  (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를
  techviz 로 만들었다
- 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs
  돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다.
  Concept 이 인용한 코드가 SSOT 에 없어 뺐다
- candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-07 12:39:20 +09:00

8.3 KiB

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn assets evidence source
CASE a05-f018-sql 쿼리 이름을 SQL 로 옮기는 두 경로가 양쪽 끝만 있고 가운데가 없다 runtime-reachability-and-composition clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 case:a05-f018-sql 2026-09-02
key file
a05-f018-sql ../../../final/evidence/rendered/a05-f018-sql.svg
../../../final/evidence/raw/a05-f018-sql.txt
원본 분석 절은 `final/document.md#a05` §55 의 backlog 안, 「Cross-scope P1/P2 — query SQL naming/observability composition 부재」 항목이다. 검사기의 런타임 등록이 0 이라는 판정, SQL 계층으로 잇는 다리가 확인되지 않았다는 판정, 그리고 최종 판정을 트랜잭션 관측 배선 공백과 함께 관측·설정 범위로 미룬다는 기록이 거기 있다.
다리가 확인되지 않았다는 판정은 맞다. `QueryNameContext` 가 이름을 스레드에 묶고 검사기가 그것을 읽지만, 어떤 SessionFactory 도 그 검사기를 설치하지 않으므로 `inspect()` 는 호출되지 않는다. 코드에 있는 것은 다리가 아니라 양쪽 끝이다. 두 번째 경로인 힌트도 마찬가지다.

쿼리 이름을 SQL 로 옮기는 두 경로가 양쪽 끝만 있고 가운데가 없다

쿼리 이름을 SQL 주석으로 실어 나르는 문장 검사기가 있다. 어떤 SessionFactory 도 그것을 설치하지 않아 inspect() 가 호출되지 않는다. 두 번째 경로인 org.hibernate.comment 힌트도 그것을 SQL 로 내보내는 설정이 꺼져 있다. 이름을 넣는 프로덕션 클래스 셋은 자기 단위 테스트 밖에서 쓰이지 않는다.

관계

  • @Bean이 있다는 것은 조립 증거가 아니다 구현의 존재를 조립의 증거로 읽는다는 점이 같다.
  • 이름은 값이 아니라 registry key다 쿼리 이름이 등록된 식별자로 쓰이는 맥락이다.
  • 카디널리티 경계를 타입으로 표현하기 그 이름이 메트릭 태그가 되는 경계다.

문제

주석에 이름이 실려야 DBA 가 눈앞의 문장을 어느 유스케이스에서 나온 것인지 되짚는다. 검사기 javadoc 이 그 이유를 적고, 없으면 어느 엔드포인트가 이 쿼리를 내는지를 SQL 조각으로 코드베이스를 뒤져 답하게 된다고 덧붙인다.

결론

inspect() 는 다 쓰여 있다. 현재 스레드에 묶인 이름을 꺼내 /* 이름 */ 을 앞에 붙이고, 이름에 주석 종료자가 있으면 원본을 돌려준다. 그 분기는 도달하지 않는다. QueryName 의 형식 [a-z][a-z0-9.-]{2,95} 가 이미 * 와 / 를 막고, javadoc 도 그 검사를 additionally 라고 적는다.

단위 테스트는 없다. 검사기에도 컨텍스트에도 테스트 파일이 없다.

SessionFactory 가 설치해 주지 않으면 inspect() 는 불리지 않는다. 네 경로는 저장소 루트에서 확장자 제한 없이 훑어 얻었다. 설정 키 0, HibernatePropertiesCustomizer 와 SessionFactoryBuilder 와 ServiceRegistry 와 Integrator 0, persistence.xml 0, 런타임 리소스의 FQCN 0 이다.

이름을 넣는 쪽은 배선되어 있다. QueryNameContext.with(...) 를 부르는 프로덕션 코드가 셋이다. 그 컨텍스트를 읽는 쪽은 검사기 하나뿐이다.

SQL 로 이름을 옮기는 길이 그것 말고 또 있다. org.hibernate.comment 힌트를 거는 것은 리포지토리 조각 지원과 Querydsl 지원이다. 그 힌트도 스위치 하나에 달려 있는데 저장소에 그 키가 0 이다.

두 경로 다 이름을 넣는 코드와 그것을 읽는 자리는 있는데, 그 사이를 잇는 설치와 스위치가 없다.

넣는 세 클래스도 실행되지 않는다. 각 타입을 쓰는 파일은 자기 자신과 자기 단위 테스트뿐이고, 리포지토리 조각 지원을 상속하는 유일한 코드도 그 테스트 안의 중첩 클래스다.

검증 환경

OpenJDK : 21.0.12 확인 방식 : 설치 경로 넷을 저장소 루트에서 계수, 이름을 넣고 읽는 지점 추적, 두 번째 경로의 활성 설정 확인 소스 수정 : x

재현 조건

  1. 검사기 구현과 javadoc, 그리고 QueryName 의 형식 정규식을 읽는다.
  2. 저장소 루트에서 확장자 제한 없이 설치 경로 넷을 각각 센다.
  3. 그 클래스의 단위 테스트가 있는지 찾는다.
  4. 이름을 넣는 호출과 읽는 호출을 각각 센다.
  5. org.hibernate.comment 힌트를 거는 곳과, use_sql_comments 를 켜는 곳을 센다.
  6. 넣는 세 클래스를 쓰는 파일과 상속하는 코드를 전부 나열한다.

본문

쿼리 이름이 SQL 주석으로 실려야 DBA 가 pg_stat_activity 나 느린 쿼리 로그의 문장을 유스케이스로 되돌릴 수 있다. 검사기 javadoc 이 그 이유를 적는다.

inspect() 가 하는 일

:::evidence key="a05-f018-sql" alt="문장 검사기의 javadoc 앞부분과 클래스 본문, 쿼리 이름의 형식 정규식, 하이버네이트가 이 구현을 설치하는 경로 넷을 저장소 루트에서 확장자 제한 없이 센 결과와 그 클래스의 단위 테스트 수, 이름을 컨텍스트에 넣는 세 곳과 읽는 곳, 이름을 SQL 로 옮기는 두 번째 경로와 그것을 활성화하는 설정의 수, 그리고 넣는 세 클래스를 쓰는 파일과 상속하는 코드를 출력한 터미널 기록." caption="검사기 javadoc 과 본문 · 이름 형식이 이미 * 와 / 를 막음 · 설치 경로 넷 전부 0 · 단위 테스트 0 · 넣는 곳 셋과 읽는 곳 하나 · 두 번째 경로의 use_sql_comments 0 · 세 클래스는 자기 테스트만 — 69줄 · exit 0" zoom="true" :::

public String inspect(String sql) {
  if (sql == null) {
    return null;
  }
  Optional<QueryName> queryName = QueryNameContext.current();
  if (queryName.isEmpty()) {
    return sql;
  }
  String value = queryName.get().value();
  if (value.contains(COMMENT_TERMINATOR)) {
    return sql;
  }
  return "/* " + value + " */ " + sql;
}

현재 스레드에 묶인 이름을 꺼내 주석으로 붙인다. 이름에 */ 가 있으면 원본을 돌려주는 분기가 하나 더 있는데, QueryName 의 형식 [a-z][a-z0-9.-]{2,95} 가 이미 */ 를 막으므로 도달하지 않는다. javadoc 도 그 검사를 additionally 라고 적는다.

이 클래스에는 단위 테스트가 없다. 컨텍스트 쪽도 없다.

검사기를 설치하는 설정이 없다

하이버네이트가 inspect() 를 부르려면 SessionFactory 가 이 구현을 설치해야 한다. 설치 경로 넷을 저장소 루트에서 확장자 제한 없이 셌다.

statement_inspector 설정 키                                        : 0
HibernatePropertiesCustomizer / SessionFactoryBuilder / Integrator : 0
persistence.xml                                                    : 0
런타임 리소스의 FQCN                                                : 0

이름을 컨텍스트에 넣는 세 곳

JpaStreamExecutor:63, JpaKeysetQuerySupport:49, JpaRepositoryFragmentSupport:72 가 작업을 감싸며 이름을 컨텍스트에 넣는다. 그 컨텍스트를 읽는 코드는 검사기 하나다.

이름을 SQL 로 옮기는 경로는 하나가 더 있다. 리포지토리 조각 지원과 Querydsl 지원이 org.hibernate.comment 힌트를 건다.

return entityManager.createQuery(jpql, resultType).setHint(COMMENT_HINT, name.value());

그 힌트가 SQL 로 나오려면 hibernate.use_sql_comments 가 켜져야 한다. 저장소에 그 키는 0 이다.

두 경로 모두 양쪽 끝만 있고 가운데가 없다.

세 클래스의 프로덕션 참조

각 타입을 쓰는 파일은 자기 자신과 자기 단위 테스트뿐이다. 리포지토리 조각 지원을 상속하는 유일한 코드도 그 테스트 안의 중첩 클래스다.

스프링 데이터의 조각 규약으로 연결될 여지도 없다. 그 클래스는 인터페이스가 아니라 추상 클래스이고, repositoryBaseClass@NoRepositoryBean 도 저장소에 없다.

이름은 실행 경로에 오르지 않는다.

확인하지 못한 것

애플리케이션을 부팅해 실제 문장에 주석이 붙지 않는 것을 관측하지 않았다. 설치 경로와 호출 지점을 센 것까지가 확인 범위다.