Conversation
WebTypesMirrorContractTest 는 필드 «이름» 만 본다. 그래서 계약 enum 에 값이 하나 늘고 types.ts 유니온이 안 따라와도 아무것도 안 울었다. ApiError.code 핸들러·openapi·CLAUDE.md·유니온·문면 표·명세 §9 여섯 벌 나머지 enum openapi · types.ts 유니온 0 벌 #594 가 유니온을 들고 오고 #596 이 같은 enum 에 다섯째 값을 더했는데, 두 PR 이 서로를 알고 있어서 사람이 맞췄다. 다음 카드가 생기는 날에는 두 변경이 겹치지 않을 수 있다. 갈리면 화면이 값으로 분기하는 자리가 조용히 기본 갈래로 떨어진다 — 운영 콘솔이면 카드 하나가 이름 없이 그려지고, 하필 그 카드가 지금 문제인 카드일 수 있다(#316 과 같은 모양). - 짝을 손으로 적지 않는다. 「어느 enum 이 어느 유니온과 짝인가」를 목록으로 두면 그 목록이 새 사본이 되고 늘릴 때 같이 안 고쳐진다(#586 이 SOURCES 에서 밟은 자리). 값 집합이 같은지로 짝을 찾으므로 계약이 값을 더하는 순간 어느 enum 과도 안 맞아 빨개진다 - contracts/ 전체를 읽는다. RiskItem 의 importance·status 는 risk_item.schema.json 에 있고 화면이 그 둘도 유니온으로 든다 — openapi.yaml 만 보면 맞는 코드가 빨개진다 - 반대 방향은 안 본다. 계약 enum 28 개 중 유니온으로 온 것이 22 개이고 나머지(ageBand · amountBand · experienceLevel 등)는 화면이 string 으로 받는다. 값으로 분기하지 않으므로 유니온일 이유가 없고, 「전부 유니온이어야 한다」로 두면 그것을 요구하는 그물이 된다 - 허용 목록이 없다. 지금 22 개가 전부 짝이 있다 - 닻으로 ApiError.code 집합이 뽑히는지 먼저 잰다. 정규식이 깨지면 0 건이 되고 그러면 대조가 아무것도 안 재고 통과한다. 숫자를 적어 두지 않는 이유는 그 숫자가 낡아서다 역검증: 계약 enum 에 여섯째 값을 더한다(types.ts 그대로) 빨강 ← #596 이 겪은 그 상황 types.ts 유니온에서 값 하나를 뺀다 빨강 정규식에서 줄 주석 건너뛰기를 뺀다 닻 테스트 빨강 openapi.yaml 만 읽는다 빨강 (risk_item 쪽 둘이 짝을 잃는다) server 전체 832건 · 실패 0 · skip 0 Closes #597 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
junseo2323
left a comment
There was a problem hiding this comment.
방향은 맞고 #597 이 든 자리는 실제로 막힙니다(아래 ①). 그런데 짝을 「값 집합」으로만 짓는 탓에 types.ts 유니온 22 개 중 11 개가 이 그물에 안 걸립니다 — 계약에 같은 값집합이 두 자리 이상 있으면, 그중 하나가 값을 더해도 유니온이 나머지와 여전히 맞아서 초록입니다. 재현했습니다.
① 먼저 — 되는 것부터 확인했습니다
기준선 server 전체 BUILD SUCCESSFUL
변이 ⓐ OpsComponent.id 에 여섯째 값 추가 everyWebUnionMatchesAContractEnum FAILED ✅
변이 ⓑ GAP 정규식을 깨뜨린다(줄 주석 미처리) theExtractorActuallyFindsUnions FAILED ✅
ⓑ 가 잡히는 것이 이 PR 에서 제일 좋은 부분입니다. 「0 건으로 조용히 통과」를 먼저 막고 시작한 것이 맞고, 닻으로 ApiError.code 를 쓰면서 숫자를 안 적은 것도 맞습니다.
❗② 그런데 productType 으로 같은 변이를 냈더니 초록입니다
변이 ⓒ contracts/openapi.yaml:1148 ProductSummary.productType
enum: [ELS, VARIABLE_INSURANCE] → [ELS, VARIABLE_INSURANCE, FUND]
(web/src/api/types.ts:561 ProductSummary.productType 은 그대로 두 값)
결과 WebUnionsMirrorContractEnumsTest tests="2" BUILD SUCCESSFUL ❗초록
화면이 그 필드를 유니온으로 들고 값으로 분기하는데 계약이 값을 더했고, 이 대조는 아무 말도 안 합니다. 본문·javadoc 이 "계약이 값을 하나 더하는 순간 어느 enum 과도 안 맞아서 여기가 빨개진다" 고 단정한 바로 그 갈래입니다.
이유는 짝짓기 방식입니다. 대조가 묻는 것은 «이 유니온과 같은 집합인 enum 이 계약 어딘가에 있나» 이지 «짝인 enum 이 같은 집합인가» 가 아닙니다. ELS|VARIABLE_INSURANCE 는 계약에 세 자리(openapi:44 · openapi:1148 · parsed_document.schema.json)가 있어서, 한 자리가 늘어도 나머지 둘이 옛 집합을 그대로 들고 있어 짝이 계속 잡힙니다.
③ 전수로 셌습니다 — 절반입니다
web 유니온 22 개 중 «값집합이 계약에 두 자리 이상» 인 것 11 개 ❗이 그물에 안 걸린다
types.ts:63 U1|U2|U3|U4 계약 2자리 (openapi:1358 · judgment.schema.json)
types.ts:66 GREEN|YELLOW|RED 계약 3자리
types.ts:71 CREATED|IN_PROGRESS|…|ABORTED 계약 2자리
types.ts:367 parsed|parse_failed 계약 2자리
types.ts:561 ELS|VARIABLE_INSURANCE 계약 3자리 ← ⓒ 로 재현한 자리
types.ts:562 parsed|parse_failed 계약 2자리
types.ts:659/738/774/871 org|branch 계약 4자리
types.ts:670 seller|branch|item 계약 3자리
나머지 11 개(OpsComponent.id 처럼 값집합이 계약에서 유일한 것)는 ⓐ 대로 제대로 물립니다. 즉 지금 이 그물은 「값집합이 계약에서 유일한 유니온」에만 성립합니다. 등급·세션 상태·상품유형처럼 화면이 제일 많이 분기하는 축이 하필 안 걸리는 쪽입니다.
④ 고치는 방향 — 짝 목록을 만들자는 말이 아닙니다
#586 의 교훈(짝 목록은 새 사본이 된다)에 동의하고, 목록을 만들라는 요청이 아닙니다. 이름이 이미 있는 자리는 이름으로 짝을 지으면 목록 없이 좁혀집니다.
필드 이름이 있는 유니온 ProductSummary.productType ↔ 계약의 같은 이름 property 의 enum
→ 집합을 비교한다. 이름 짝짓기는 WebTypesMirrorContractTest 가 이미 하는 일이다
이름 없는 인라인 유니온 OpsComponent.id 처럼 → 지금처럼 값집합으로 짝짓는다
아니면 훨씬 싸게, 지금 구멍을 문면으로 남기는 것도 받겠습니다 — javadoc 의 단정을 "값집합이 계약에서 유일한 유니온에만 성립한다" 로 고치고, 위 11 개를 알려진 사각으로 적는 것입니다. 지금 문면대로 두는 것만 피하고 싶습니다: 다음 사람이 이 그물을 믿고 productType 에 값을 더합니다. 그 상태는 그물이 없는 것보다 나쁩니다.
둘 중 어느 쪽이든 제가 다시 보고 바로 승인하겠습니다.
⑤ 나머지는 이견 없습니다
contracts/전체를 읽는 것 —risk_item.schema.json의importance·status가openapi.yaml에 없어서 한 파일만 보면 맞는 코드가 빨개집니다. 역검증 ⓓ 로 그걸 잡아 두신 것이 맞습니다.- 반대 방향을 안 보는 것 — 「전부 유니온이어야 한다」가 되면
ageBand여섯을 유니온으로 만들라는 그물이 됩니다. 이 대조의 몫이 아닌 게 맞습니다. - 허용 목록을 안 만든 것 — 예외 목록이 장식이 된다는 판단에 동의합니다.
WebTypesMirrorContractTest에 상호 참조를 적은 것 — 이름/값이 갈라진 이유가 두 파일에 다 있어야 한다는 것도 맞습니다.
#597입니다.#594가 머지돼서 선행이 풀렸습니다.무엇이 비어 있었나
WebTypesMirrorContractTest는 필드 이름만 봅니다. 계약 enum 에 값이 하나 늘고 유니온이 안 따라와도 아무것도 안 울었습니다.#594(운영 콘솔)와#596(추출 카드)이 서로를 알고 있어서 이번엔 사람이 맞췄습니다. 다음 카드가 생기는 날에는 두 변경이 겹치지 않을 수 있습니다.갈리면 화면이 값으로 분기하는 자리가 조용히 기본 갈래로 떨어집니다 — 운영 콘솔이면 카드 하나가 이름 없이 그려지고, 하필 그 카드가 지금 문제인 카드일 수 있습니다(
#316과 같은 모양).❗짝을 손으로 적지 않습니다 — 값 집합으로 찾습니다
「어느 enum 이 어느 유니온과 짝인가」를 목록으로 두면 그 목록이 새 사본이 되고 늘릴 때 같이 안 고쳐집니다(
#586이SOURCES에서 밟은 자리입니다).인라인 유니온(
OpsComponent.id는 이름 없는 유니온입니다)까지 보려면 이름으로는 짝을 못 짓습니다. 그래서 이쪽은 값 집합으로 짓고, 이름 대조는 기존 테스트가 계속 맡습니다. 두 파일에 상호 참조를 적었습니다.contracts/전체를 읽습니다openapi.yaml만 보면 이 둘이 짝 없는 유니온으로 잡혀 맞는 코드가 빨개집니다. 역검증 ⓓ 가 그것입니다.❗반대 방향은 안 봅니다
「전부 유니온이어야 한다」로 두면 그 여섯을 유니온으로 만들라고 요구하는 그물이 되는데, 그건 이 대조가 막으려는 결함과 무관합니다.
허용 목록이 없습니다
지금 22 개가 전부 짝이 있습니다. 예외 목록을 만들면 어긋난 것을 목록에 넣어 통과시키게 되고 그러면 그물이 아니라 장식이 됩니다(
WebTypesMirrorContractTest와 같은 판단).닻을 먼저 잽니다
정규식이 깨지면 유니온이 0 건이 되고, 그러면 「짝 없는 유니온 0 건」으로 초록입니다. 그래서
ApiError.code집합이 뽑히는지 먼저 단정합니다 — 그 한 벌은ErrorCodeContractTest가 이미 지키고 있어서, 여기에 숫자를 적어 두면 그 숫자가 낡습니다.역검증
types.ts그대로)#596이 겪은 그 상황types.ts유니온에서 값 하나를 뺀다openapi.yaml만 읽는다risk_item쪽 둘이 짝을 잃는다셋째가 둘째 단정의 전제를 지킵니다. 넷째는 거짓 양성 방향이라 그 설계가 필요했다는 근거입니다.
검증
build.gradle이../web/src/api/types.ts와../contracts를 이미 입력으로 들고 있어 둘 중 하나만 고쳐도 이 대조가 다시 돕니다 — 새 입력 선언이 필요 없습니다.Closes #597