feat: 가상화 문서들 추가
This commit is contained in:
+5
-5
@@ -29,13 +29,13 @@ source:
|
||||
|
||||
이 건은 같은 갈래의 다른 것들과 결이 다르다. 테스트가 아니라 생성기가 값을 버렸다.
|
||||
|
||||
파생 스펙을 파서에 넣으면 스키마 15개를 「is not of type `object`」로 거절했다. 그 스키마들은 전부 `type: object` 를 명시하고 있어서 계약 결함처럼 보이지 않았다.
|
||||
파생 스펙을 파서에 넣으면 스키마 15개를 「is not of type object」로 거절했다. 그 스키마들은 전부 type: object 를 명시하고 있어서 계약 결함처럼 보이지 않았다.
|
||||
|
||||
`validateSpec` 을 끄면 생성이 성공한다. 그렇게 만든 모델을 컴파일하면 통과한다.
|
||||
validateSpec 을 끄면 생성이 성공한다. 그렇게 만든 모델을 컴파일하면 통과한다.
|
||||
|
||||
## 결론
|
||||
|
||||
거절의 원인은 계약이 아니라 파생 단계였다. 변환들이 같은 `Map` 인스턴스를 여러 property 에 재사용했고 snakeyaml 이 그 지점을 anchor 와 alias 로 덤프했다. 파생 스펙에 alias 가 34곳 있었다.
|
||||
거절의 원인은 계약이 아니라 파생 단계였다. 변환들이 같은 Map 인스턴스를 여러 property 에 재사용했고 snakeyaml 이 그 지점을 anchor 와 alias 로 덤프했다. 파생 스펙에 alias 가 34곳 있었다.
|
||||
|
||||
검증을 끄고 만든 모델에서 사라진 필드 넷 :
|
||||
LatestEntry.publishedAt
|
||||
@@ -45,7 +45,7 @@ ReleaseListItem.changeTypes
|
||||
|
||||
컴파일이 통과한 이유는 아직 그 필드를 쓰는 코드가 없어서다.
|
||||
|
||||
덤프 직전 deep copy 로 노드 identity 를 끊어 alias 를 원천 차단하고, 남으면 빌드가 실패하도록 fail-closed 게이트를 뒀다. `validateSpec` 은 다시 켰다. 생성 모델 대조는 schema 이름에서 property 단위로 강화했다 — 이번 누락을 그 게이트가 통과시켰기 때문이다.
|
||||
덤프 직전 deep copy 로 노드 identity 를 끊어 alias 를 원천 차단하고, 남으면 빌드가 실패하도록 fail-closed 게이트를 뒀다. validateSpec 은 다시 켰다. 생성 모델 대조는 schema 이름에서 property 단위로 강화했다 — 이번 누락을 그 게이트가 통과시켰기 때문이다.
|
||||
|
||||
## 검증 환경
|
||||
|
||||
@@ -57,7 +57,7 @@ tech-log-backend : 365560e
|
||||
## 재현 조건
|
||||
|
||||
1. 파생 스펙에서 anchor 와 alias 를 찾는다
|
||||
2. `validateSpec` 을 켜고 생성한다 — 그 스키마들이 거절된다
|
||||
2. validateSpec 을 켜고 생성한다 — 그 스키마들이 거절된다
|
||||
3. 끄고 생성한 뒤 모델의 property 를 계약과 하나씩 맞춘다
|
||||
|
||||
## 본문
|
||||
|
||||
+4
-4
@@ -14,7 +14,7 @@ source:
|
||||
|
||||
# 그 SQL 은 한 번도 실행된 적이 없었다
|
||||
|
||||
작업본 삭제가 500 을 돌려줬다. 참조 검사가 없는 컬럼을 조회하고 있었다. 진짜 문제는 그 SQL 이 한 번도 실행된 적이 없다는 것이었다 — 표준 `check` 는 Testcontainers 를 띄우지 않으므로 persistence SQL 을 한 줄도 돌리지 않고 빌드가 통과한다.
|
||||
작업본 삭제가 500 을 돌려줬다. 참조 검사가 없는 컬럼을 조회하고 있었다. 진짜 문제는 그 SQL 이 한 번도 실행된 적이 없다는 것이었다 — 표준 check 는 Testcontainers 를 띄우지 않으므로 persistence SQL 을 한 줄도 돌리지 않고 빌드가 통과한다.
|
||||
|
||||
## 관계
|
||||
|
||||
@@ -27,7 +27,7 @@ source:
|
||||
|
||||
## 문제
|
||||
|
||||
작업본을 지우려 하면 500 이 났다. 참조 검사가 `public_resource_projection.document_id` 를 조회하는데 그런 컬럼이 없다.
|
||||
작업본을 지우려 하면 500 이 났다. 참조 검사가 public_resource_projection.document_id 를 조회하는데 그런 컬럼이 없다.
|
||||
|
||||
이 테이블은 하나로 case·question·project·release 를 모두 담기 때문에 종류와 식별자 두 컬럼으로 기록을 가리킨다.
|
||||
|
||||
@@ -37,7 +37,7 @@ source:
|
||||
|
||||
> 그 쿼리의 여섯 컬럼 중 다섯은 마이그레이션과 대조했다. 이 하나만 가정했고, 그것이 틀렸다.
|
||||
|
||||
표준 `check` 는 Testcontainers 를 띄우지 않는다. persistence SQL 은 한 번도 실행되지 않은 채 빌드가 통과하고, 컴파일도 단위 테스트도 컬럼 이름을 검증하지 못한다.
|
||||
표준 check 는 Testcontainers 를 띄우지 않는다. persistence SQL 은 한 번도 실행되지 않은 채 빌드가 통과하고, 컴파일도 단위 테스트도 컬럼 이름을 검증하지 못한다.
|
||||
|
||||
삭제 경로 전용 통합 테스트 태스크를 만들고 실패했던 그 쿼리를 포함해 여덟 시나리오를 실제 PostgreSQL 에서 돌린다.
|
||||
|
||||
@@ -51,7 +51,7 @@ DB : 실제 PostgreSQL (Testcontainers)
|
||||
## 재현 조건
|
||||
|
||||
1. 어댑터의 SQL 에서 컬럼 이름을 하나 틀리게 적는다
|
||||
2. `./gradlew check` 를 돌린다 — 통과한다
|
||||
2. ./gradlew check 를 돌린다 — 통과한다
|
||||
3. 삭제 경로 통합 테스트 태스크를 돌린다 — 그 쿼리에서 멈춘다
|
||||
|
||||
## 본문
|
||||
|
||||
+6
-6
@@ -31,18 +31,18 @@ source:
|
||||
|
||||
컴포넌트 스캔이 생성자를 고르지 못하면 컨텍스트가 refresh 에 실패한다. 컨텍스트를 띄우는 테스트가 없으면 그 실패는 배포에서 처음 나타난다.
|
||||
|
||||
두 번째 사건은 import 였다. `JdbcProjectRepositoryAdapter` 가 Jackson 2 의 `ObjectMapper` 를 요구했는데 이 빌드는 Jackson 3 이다.
|
||||
두 번째 사건은 import 였다. JdbcProjectRepositoryAdapter 가 Jackson 2 의 ObjectMapper 를 요구했는데 이 빌드는 Jackson 3 이다.
|
||||
|
||||
## 결론
|
||||
|
||||
두 건 다 컨텍스트가 뜰 때 처음 드러났다.
|
||||
|
||||
첫 번째 : 스캔되는 컴포넌트에 생성자 둘, `@Autowired` 없음
|
||||
두 번째 : Jackson 2 `ObjectMapper` 를 요구, 이 빌드는 Jackson 3
|
||||
첫 번째 : 스캔되는 컴포넌트에 생성자 둘, @Autowired 없음
|
||||
두 번째 : Jackson 2 ObjectMapper 를 요구, 이 빌드는 Jackson 3
|
||||
|
||||
두 번째가 컴파일을 통과한 이유는 Jackson 2 타입이 어떤 전이 의존성을 통해 클래스패스에 남아 있어서다. 잘못된 import 가 정상적으로 해석된다.
|
||||
|
||||
첫 번째는 ArchUnit 규칙으로 막았다. 스캔되는 컴포넌트는 생성자가 하나이거나, 여럿이면 그중 하나에 `@Autowired` 가 붙어야 한다. 규칙이 실제로 잡는지 결함을 되돌려 확인했다.
|
||||
첫 번째는 ArchUnit 규칙으로 막았다. 스캔되는 컴포넌트는 생성자가 하나이거나, 여럿이면 그중 하나에 @Autowired 가 붙어야 한다. 규칙이 실제로 잡는지 결함을 되돌려 확인했다.
|
||||
|
||||
## 검증 환경
|
||||
|
||||
@@ -53,8 +53,8 @@ Jackson : 이 빌드는 Jackson 3, 클래스패스에 Jackson 2 타입이 전이
|
||||
|
||||
## 재현 조건
|
||||
|
||||
1. 스캔되는 컴포넌트에 생성자를 둘 만들고 `@Autowired` 를 붙이지 않는다
|
||||
2. `./gradlew check` 를 돌린다 — 통과한다
|
||||
1. 스캔되는 컴포넌트에 생성자를 둘 만들고 @Autowired 를 붙이지 않는다
|
||||
2. ./gradlew check 를 돌린다 — 통과한다
|
||||
3. ArchUnit D20 규칙을 켠 상태로 돌린다 — 그 컴포넌트를 짚는다
|
||||
|
||||
## 본문
|
||||
|
||||
Reference in New Issue
Block a user