15주차 미리보기
W15 미리보기 · 웹소설 본편

STARRY PASS 11 — 네 개 서랍과 꼬리표 전쟁

같은 사실을 한곳에 두면 장부가 덜 싸운다

범위D1–D6 · 월–토p487 L10–27 + p488–512 + p513 L5–12
정본 상태SOURCE AUDIT PASSPDF·source·fixture byte 폐쇄
실행 상태W15 RUNNER NOT_RUNtestsExecutedByAudit=0

이 이야기는 W15 개요와 D1–D6만 다룹니다. 정확한 범위는 p487 L10–27 + p488–512 + p513 L5–12이고, p487 상단 W14 복구 문장과 p513 L14부터의 D7·p517 주간 통합·p518 이후는 제외합니다. 공통 코어이며 트랙 선택 시 증권 기본으로 표시하지만 증권 전용 기능 주차는 아닙니다. source audit은 PASS여도 testsExecutedByAudit=0이므로 상태는 W15 RUNNER NOT_RUN입니다.

STARRY 앞 골목에 벼룩시장이 섰다. 료는 바퀴 하나가 빠진 네 칸 캐비닛을 천 원에 사 왔다. 첫 서랍에는 계좌 카드, 둘째에는 돈이 움직인 업무 사건, 셋째에는 사건이 계좌에 남긴 돈줄, 넷째에는 같은 요청이 다시 들어왔을 때 자리를 지키는 접수표가 뒤섞여 있었다. 손님 이름과 번호와 잔액이 여러 종이에 복사되어 어느 것이 원본인지 알 수 없었다.

“종이가 많아서 풍성한 게 아니라 같은 사실이 서로 다른 말을 하고 있어.” 니지카가 말했다.

히토리는 종이를 한 줄씩 읽다가 손님 이름 하나가 세 철자로 적힌 것을 찾았다. 키타는 먼저 색깔별로 나누자고 했고, 료는 색보다 각 줄이 무엇 한 건을 뜻하는지부터 정해야 한다고 했다. 네 사람은 캐비닛을 공연장 한가운데로 옮겨, 한 줄의 의미와 한 줄을 다시 찾는 방법부터 적기로 했다.

니지카가 태블릿을 보며 네 핵심 테이블과 식별자 표를 점검하는 공식 장면
그림 한눈에: 공식 장면컷은 네 테이블을 함께 점검하는 분위기 전환용이며, 학습 사건과 수치는 원문·source 감사에 따른 비공식 구성입니다.

첫째 서랍 이름은 account, 둘째는 business_tx, 셋째는 ledger_entry, 넷째는 idempotency_request였다. 이것들은 현재 물리 schema가 저장하는 네 종류의 entity였다. 각 열은 그 entity를 설명하는 attribute이고, 각 행은 실제 instance 한 건이었다. 니지카는 네 서랍을 그리되, 표 이름만 예쁘게 적는 ERD로 끝내지 말자고 했다.

금색 스티커는 한 행을 딱 하나로 찾는 기본키였다. 빨간 스티커는 후보가 될 수 있는 유일 값이나 업무상 중복되면 안 되는 값을 표시했다. account_no 같은 업무 번호와 idempotency_request의 복합 UNIQUE는 유일성을 주지만, 모든 후보를 자동으로 기본키로 만들지는 않았다. candidate key 가운데 대표로 선택한 것이 PK이고, business key는 업무 의미를 가진 유일 값일 수 있었다.

히토리는 owner 이름을 account의 식별자로 쓰면 친절하지 않겠느냐고 물었다. 료는 동명이인 둘을 적고, 이름을 바꾼 한 사람을 그 옆에 적었다. 사람이 같아도 이름이 달라지고 사람이 달라도 이름이 같을 수 있으므로 안정적인 식별자가 아니었다. 또 business transaction ID 하나에는 ledger 줄이 여러 개 붙을 수 있어 그 ID만으로 개별 ledger 행을 식별할 수도 없었다.

account, business_tx, ledger_entry, idempotency_request 네 엔터티와 기본키·업무키를 분리한 지도
그림 한눈에: 네 entity, 선택된 PK, candidate·business key, 비식별자 반례를 한 화면에서 분리합니다.

료는 V001__common.sql을 열어 스티커 수를 셌다. source에는 table 4, PK 4, REFERENCES 3, UNIQUE 4, CHECK 5, explicit index 2가 있었다. 이 수는 문자열 장식이 아니라 실제 migration의 저장 규칙을 읽은 결과였다. 그러나 숫자를 센 것만으로 ERD 의미가 맞다거나 3NF가 형식적으로 증명되지는 않았다.

캐비닛 옆에는 자동 검사기가 있었다. CoreSchemaIT은 public BASE TABLE 이름이 네 개와 정확히 같은지만 보았다. column·key·index·cardinality는 읽지 않았다. OpeningIntegrationTestcustomer-1, OPEN-100, 12_345로 정상 개설한 뒤 account 한 행, OPENING transaction 한 행, OPENING ledger 한 행을 각각 셌다. 중간 실패 rollback, 세 조회의 single snapshot, amount와 balance 일치는 직접 검사하지 않았다.

검사기를 움직이는 run-w15-schema.ps1은 두 class selector와 tests>=2, failure·error·skip 0을 기대했다. 하지만 두 selector는 stage-only 참조이고 active packaged root에는 exact class가 둘 다 없었다. selector 문자열이 있다고 현재 learner root가 Green인 것은 아니었다. 감사가 확인한 것은 source 폐쇄였고, 실제 Gradle·Docker·PostgreSQL 실행은 영 건이었다.

W15 runner의 두 staged selector, isolated schema, cardinality 1,2와 2,0, 증거 파일의 경계
그림 한눈에: selector 2개·staged test 2개·현재 실행 0개와 isolated fixture 1,2·2,0을 서로 다른 층으로 봅니다.

runner는 isolated w15_schema에 두 account를 넣고 첫째의 ledger는 2행, 둘째는 0행인지 확인했다. key gate는 PK>=4, FK>=2, UNIQUE>=2라는 하한이고 index는 기록만 했다. keys.txt, cardinality.csv, schema.txt를 minimum key 검사보다 먼저 각각 쓸 수 있어 실패 시 부분 evidence가 남을 수 있었다. 파일이 존재한다고 Green이 되는 구조가 아니었다.

Compose mode는 자신이 만든 project와 volume을 정리하지만, Container mode는 사용자가 넘긴 PostgreSQL container 안의 w15_schema를 drop/recreate하고 끝난 뒤 남겼다. 히토리는 “연습 서랍 하나뿐이어도 남의 창고 안에서 갈아엎는 일은 미리 알려야 하네요”라고 말했다. 니지카는 고개를 끄덕이며, 오늘은 runner를 실행하지 않고 source가 말하는 영향만 정확히 표시했다.

고양이 한 마리가 캐비닛 뒤에서 나와 파란 연결끈을 물고 달렸다. 되찾은 끈으로 ledger_entryaccount_idbusiness_tx_id를 다시 이었다. 두 FK 열은 NOT NULL이므로 ledger 한 행은 account 하나와 business transaction 하나를 반드시 가리켰다. 반대 방향은 달랐다. account는 ledger가 하나도 없을 수 있고 여러 개일 수도 있었다.

“아이 한 명이 부모 한 명을 가리킨다고 모든 부모가 아이를 반드시 가진다는 뜻은 아니구나.” 히토리가 말했다.

고정 fixture에서 account 1은 ledger 2개, account 2는 0개였다. 1,22,0은 optionality를 눈으로 확인하기 좋은 반례였지만 모든 운영 데이터의 일반 1:N을 증명하는 표본은 아니었다. LEFT JOIN을 쓰면 둘째 account도 0과 함께 남고, INNER JOIN을 쓰면 ledger 없는 account가 사라졌다.

idempotency_requestbusiness_tx 사이에는 현재 V001의 직접 FK가 없었다. 업무상 관련되어 보이는 것과 database가 referential integrity로 연결한 것은 달랐다. 삭제·보존 정책 역시 선 하나만 보고 결정할 수 없었다.

account 한 행에 ledger 두 행 또는 영 행이 붙고 각 ledger는 한 account를 반드시 가리키는 관계도
그림 한눈에: child의 필수 참조와 parent의 0..N 가능성을 반대 방향에서 따로 읽습니다.
네 사람이 카디널리티와 정규화 반례를 함께 검토하는 공식 장면
그림 한눈에: 공식 장면컷은 관계 방향과 반례를 함께 토론하는 분위기용이며, 현재 runner 실행 장면이 아닙니다.

연결을 마치자 같은 owner 이름이 ledger 종이마다 반복된 문제가 보였다. 어떤 종이는 이름을 고쳤고 어떤 종이는 예전 이름을 남겼다. 새 owner를 먼저 등록하려면 억지 transaction 줄이 필요했고, 마지막 ledger 줄을 지우면 owner 정보까지 함께 사라질 위험도 있었다. 수정·삽입·삭제 anomaly였다.

료는 X→Y를 “같은 X를 알면 Y가 하나로 결정된다”라고 읽었다. account ID가 owner ID를 결정한다면 owner 사실은 account 쪽에 두고 ledger는 account ID를 참조하는 편이 낫다. 반복을 무조건 죄악으로 부르는 대신, 어떤 determinant가 어떤 dependent를 정하는지부터 적었다.

중복 저장에서 삽입·수정·삭제 이상이 생기고 함수 종속을 기준으로 분리하는 흐름
그림 한눈에: 중복 메모가 세 이상 현상을 만들고 함수 종속을 기준으로 사실의 집을 다시 정합니다.

첫 번째 정리 단계인 1NF는 한 칸에 반복 목록을 넣지 않고 원자값으로 만드는 것이었다. 2NF는 복합 candidate key의 일부에만 기대는 non-key 사실을 분리했다. 복합 key가 없는 표에 부분 종속을 억지로 붙이지 않았다. 3NF는 key가 아닌 값이 또 다른 non-key 값을 정하는 이행 종속을 분리했다. BCNF는 모든 determinant가 candidate key인지 더 강하게 물었다.

키타는 종이를 많이 나누면 무조건 좋은지 물었다. 니지카는 분해 뒤 무손실 join과 필요한 종속 보존을 확인해야 한다고 답했다. 정규형 이름은 분해 주문이 아니라 주어진 함수 종속과 candidate key를 근거로 한 판정이었다.

1NF, 2NF, 3NF를 원자값·부분 종속·이행 종속 제거 순서로 보여 주는 사다리
그림 한눈에: 원자값, 부분 종속, 이행 종속, determinant 조건을 계단별 질문으로 구분합니다.

그래도 공연 중 account balance를 매번 ledger 전체에서 계산하면 느릴 수 있었다. replay를 위해 idempotency response를 가까이 둘 수도 있었다. 이런 의도적 중복은 목적, 갱신 owner, 대사 주기, mismatch 감지와 monitoring을 함께 적어야 했다. “정규화했으니 중복 0”도 틀리고 “빠르니 복사”도 불완전했다.

네 사람은 물리 ERD에 열·type·nullable·PK·FK·UNIQUE·CHECK·index를 적었다. balance>=0 CHECK는 음수 저장 모양을 막을 뿐 동시 출금 안전이나 ledger 대사를 증명하지 않았다. account_id FK는 account 존재를 볼 뿐 요청자의 소유권을 판단하지 않았다. ledger의 amountsigned_amount 사이에도 부호와 절댓값 일치를 강제하는 CHECK가 없었다. idempotency 복합 UNIQUE도 request hash 비교·replay response·동시 claim protocol 전체를 구현하지 않았다.

PK·FK·UNIQUE·CHECK가 보장하는 저장 모양과 권한·원자성·대사를 보장하지 않는 경계
그림 한눈에: 물리 constraint가 직접 막는 저장 오류와 application·transaction·대사가 맡는 규칙을 갈라 봅니다.

D5의 연습용 DDL 발췌는 전체 V001 정본이 아니었다. 완성한 project-erd.pdf와 review 문서는 실제 schema.txt hash에 묶고, PK·FK·UNIQUE·CHECK 검토 상태와 source of truth 설명을 남겨야 했다. PDF header·EOF·byte·hash가 맞아도 선 방향과 업무 의미까지 자동 판정되지는 않아 MANUAL_REVIEW_REQUIRED가 남았다.

키타가 세 장의 SQL 문제 카드를 꺼냈다. 첫 카드는 Q16, 날짜별 SUCCESS·FAILED 건수였다. 입력 한 행은 business_tx 한 건이고 출력 한 행은 business_date 하루였다. FILTER로 두 상태를 세고, 선택적 비율은 SUCCESS+FAILED가 0이면 NULLIF 때문에 NULL이 되게 했다. occurred_at::date를 쓰지 않고 이미 정의된 DATE 열을 써 session timezone 이동 함정을 피했다.

fixture에는 9일이 있었다. 2026-07-02는 0·0·NULL, 2026-07-01은 2·1·66.67, 2026-12-28은 0·3·0.00이었다. 핵심 계약은 count이고 비율은 0분모 경계를 보이는 선택 열이었다.

날짜별 SUCCESS·FAILED 건수와 분모 영일 때 NULL이 되는 학습용 Q16 도식
그림 한눈에: 날짜 grain, 두 조건부 count, 분모 0일 때 NULL을 같은 표에서 봅니다.

두 번째 카드 Q21은 전체 account 평균 balance보다 큰 account를 찾았다. 안쪽 aggregate subquery는 바깥 account와 상관없이 한 행의 평균 266287.375를 돌려주었다. strict > 결과 ID는 106·107·108, 3행이었다. status filter가 없어 CLOSED 107도 포함되고, 평균과 같은 행은 빠졌다. 입력이 비면 AVG는 NULL이며 비교 결과도 true가 되지 않았다.

전체 평균 266287.375보다 큰 계좌 106·107·108을 고르는 scalar subquery 도식
그림 한눈에: 한 번 정한 전체 평균선 위의 세 account와 strict greater-than 경계를 표시합니다.

세 번째 카드 Q22는 바깥 account의 customer가 바뀔 때마다 같은 customer의 MAX balance를 다시 물었다. 결과 표시 순서 ID는 105·106·107·104·108, 5행이었다. account가 없는 customer 5는 account에서 시작하는 query에 나타나지 않았다. query 모양은 최대 balance 동률을 모두 남기지만 현재 fixture의 같은-customer 최대 동률은 0행이었다.

고객별 최대 잔액 계좌를 고르고 동률을 모두 보존하는 correlated subquery 도식
그림 한눈에: 바깥 customer와 연결된 MAX 질문, 공동 최대 보존, account 없는 customer 제외를 구분합니다.

세 SQL은 workbook 문제와 격리 fixture를 바탕으로 audit이 만든 fixture-bound 학습용 예시였다. shipped 정본 답안이 아니었다. 니지카는 결과 숫자를 외우기보다 시작 table, 입력·출력 grain, cardinality, NULL·동률·0건 반례를 먼저 말하게 했다.

마지막으로 네 사람은 40장의 모델링 진단 카드를 50분 타이머 옆에 놓았다. 틀린 카드는 entity/key, cardinality, normalization, reading 네 상자에 넣었다. 맞혔지만 근거 없이 고른 문제는 lucky로 따로 표시했다. 점수 하나보다 무엇을 왜 틀렸는지가 다음 복습을 정했다.

첫 시도 뒤에는 modeling-diagnostic.csv 40행과 정답 없는 prompt snapshot 40행을 남기고, 오답 상위 두 범주에서 48시간 뒤 다시 풀 10개를 item ID로 연결했다. D3·D4·D6의 간단한 validator는 file 40 byte 이상, nonblank 세 줄, placeholder 없음, SHA를 볼 뿐 내용의 정확성을 읽지 않았다.

40문항 오답을 entity/key·cardinality·normalization·reading 네 범주로 나누는 진단판
그림 한눈에: 40문항 첫 시도에서 네 오답 범주, lucky 표식, 상위 두 범주 10문항 재시험으로 이어집니다.
카운터에 모인 네 사람이 모델링 진단과 오답 분류를 정리하는 공식 장면
그림 한눈에: 공식 장면컷은 D6 진단 카드를 정리하는 분위기용이며, D7 구두 방어와 주간 통합은 이번 범위에 넣지 않습니다.

밤이 되자 네 서랍은 조용해졌다. account와 business transaction, ledger, idempotency request가 각자 한 종류의 사실을 맡았다. 금색 열쇠와 파란 연결끈, 빨간 중복 도장은 저장 모양을 지켰고, application의 권한·transaction·대사는 별도의 책임으로 남았다.

히토리는 닫힌 캐비닛 손잡이에 작은 메모를 붙였다. source audit PASS는 정본을 정확히 읽었다는 뜻이고, current runner Green은 실제 learner root와 fresh XML·database 실행으로 별도 얻어야 한다. 오늘은 D6의 40장 분류까지 끝난 이야기였다. p513 L14에서 시작하는 D7의 ERD 구두 방어는 다음 문을 열 때까지 그대로 닫아 두었다.

W15 미리보기 · 히토리 질문 노트

히토리의 질문 노트 — STARRY PASS 11

본편의 비유를 실제 SQLD·PostgreSQL 기술 이름과 증거 경계로 다시 연결합니다. 답은 W15 개요와 D1–D6에만 한정하며 current runner Green을 만들었다고 가정하지 않습니다.

1. 이번 미리보기의 strict PDF 범위는 어디인가요?

p487의 W15 heading과 개요인 p487 L10–27, D1–D6 본문인 p488–512, D6 최종 Gate인 p513 L5–12입니다. p487 L5–8의 W14 복구 문장은 포함하지 않습니다.

p513 L14부터 D7 ERD 구두 방어가 시작하므로 제외합니다. p514–516 D7, p517 주간 통합, p518 W15 복구 꼬리와 W16 시작도 범위 밖입니다.

실제 기술 이름mixed-page semantic boundary — W15 overview and D1–D6 only

2. W15 D1–D6은 어떤 순서로 모델링을 배우나요?

D1 entity·attribute·identifier, D2 cardinality·optionality, D3 functional dependency·anomaly, D4 1NF·2NF·3NF, D5 logical/physical ERD와 constraint, D6 40문항 diagnostic·error taxonomy 순서입니다.

용어를 외운 뒤 그림을 그리는 순서가 아니라, 실제 migration과 fixture를 읽고 관계·종속·정규형·물리 규칙을 설명한 뒤 오답을 분류하는 흐름입니다. 공통 코어이며 트랙 선택 시 증권 기본으로 표시합니다.

실제 기술 이름SQLD data-modeling progression from identification to diagnostic retrieval

3. source audit PASS와 현재 W15 Green은 왜 다른가요?

source audit PASS는 PDF·canonical/reference source·workbook fixture와 SHA 폐쇄를 확인했다는 뜻입니다. 이번 audit은 Gradle, Docker, PostgreSQL, W15 owner를 실행하지 않았고 testsExecutedByAudit=0입니다.

따라서 상태는 W15 RUNNER NOT_RUN입니다. PDF에 적힌 W15_SCHEMA_GREEN이나 LOCAL_ARTIFACT_VALIDATED는 기대 marker 계약이지 현재 실행 결과가 아닙니다.

실제 기술 이름byte-verified source closure PASS versus unexecuted runtime Gate

4. 네 핵심 table과 각 행의 entity 의미는 무엇인가요?

account는 계좌 한 건, business_tx는 업무 사건 한 건, ledger_entry는 사건이 한 계좌에 남긴 금액 변화 한 줄, idempotency_request는 멱등 요청 key와 처리 상태 한 건입니다.

table은 entity 집합, 열은 attribute, 실제 row는 entity instance입니다. 비슷해 보이는 데이터를 한 table에 합치기 전에 각 row grain과 lifecycle을 먼저 정해야 합니다.

실제 기술 이름four physical entities and row-grain definition

account, business_tx, ledger_entry, idempotency_request 네 엔터티와 기본키·업무키를 분리한 지도
그림 한눈에: 네 entity와 PK·candidate/business key·비식별자 반례를 함께 봅니다.

5. V001 migration에서 직접 확인되는 constraint 수는 얼마인가요?

정확히 table 4, PK 4, REFERENCES 3, UNIQUE 4, CHECK 5, explicit index 2입니다. explicit index 둘은 migration에 직접 쓴 CREATE INDEX 두 줄을 뜻하며 PostgreSQL의 implicit index 전체 수가 아닙니다.

이 token 수는 물리 DDL의 저장 규칙을 확인하지만 ERD 의미 equality, 3NF·BCNF, query 성능, authorization을 자동 증명하지 않습니다.

실제 기술 이름V001 physical-schema token inventory with proof boundary

6. PK, candidate key, business key는 어떻게 다른가요?

candidate key는 한 행을 유일하게 식별할 수 있는 최소 속성 집합이고, 그중 대표로 선택한 것이 PRIMARY KEY입니다. business key는 계좌 번호나 요청 key처럼 업무 의미를 가진 유일 값이며 UNIQUE로 표현될 수 있습니다.

업무 key가 항상 PK인 것은 아닙니다. 변경 가능성, 안정성, 최소성, 참조 편의 때문에 surrogate PK를 선택하고 business key를 별도 UNIQUE로 둘 수 있습니다.

실제 기술 이름candidate-key set, selected primary key, and alternate business key

7. owner 이름과 business transaction ID가 각각 식별자로 부적절한 반례는 무엇인가요?

owner 이름은 동명이인 때문에 서로 다른 사람에게 같을 수 있고 이름 변경 때문에 같은 사람에게 달라질 수 있습니다. 안정성과 유일성을 동시에 만족하지 못합니다.

business transaction 하나에는 ledger entry가 여러 행 붙을 수 있으므로 business_tx_id만으로 개별 ledger row를 유일하게 찾지 못합니다. ledger에는 별도의 row PK가 필요합니다.

실제 기술 이름unstable natural-key counterexample and one-to-many child identity

8. ledger_entry의 세 REFERENCES는 어떤 관계를 나타내나요?

ledger_entrybusiness_txaccount를 가리키고, reversal 원거래를 표현하는 self reference도 가집니다. 반면 idempotency_requestbusiness_tx 사이에는 V001의 직접 FK가 없습니다.

업무상 연관돼 보이는 것과 database가 referential integrity로 강제하는 것은 다릅니다. ERD에는 실제 FK와 단순 논리 연관을 같은 선으로 그리지 않아야 합니다.

실제 기술 이름two parent foreign keys, optional self-reference, and absent direct idempotency FK

9. account와 ledger의 cardinality·optionality는 어떻게 읽나요?

account 한 행에는 ledger가 0..N개 붙을 수 있습니다. 각 ledger 행은 NOT NULL account_id 때문에 정확히 한 account를 가리킵니다. child→parent 최소 수와 parent→child 최소 수를 서로 바꾸면 안 됩니다.

fixture의 exact 관찰값은 1,22,0입니다. 첫 account에 ledger 2행, 둘째 account에 0행이라는 작은 예이지 모든 운영 데이터의 일반 수량 증명은 아닙니다.

실제 기술 이름asymmetric one-to-zero-or-many cardinality with mandatory child reference

account 한 행에 ledger 두 행 또는 영 행이 붙고 각 ledger는 한 account를 반드시 가리키는 관계도
그림 한눈에: parent 0..N과 child exactly-one을 양방향에서 읽습니다.

10. LEFT JOIN이 optionality 확인에 필요한 이유는 무엇인가요?

account를 시작 table로 두고 ledger를 LEFT JOIN하면 ledger 없는 account도 NULL 확장행으로 남습니다. fixture의 둘째 account가 0이라는 사실을 결과에 보존할 수 있습니다.

INNER JOIN은 child가 없는 parent를 없애므로 존재하는 account 전체를 기준으로 optionality를 확인하는 질문에는 맞지 않습니다. count할 때도 COUNT(*)보다 nullable side의 non-NULL key를 세어야 0을 유지합니다.

실제 기술 이름parent-preserving LEFT JOIN and zero-child cardinality observation

11. run-w15-schema의 두 selector와 active-root 경계는 무엇인가요?

selector는 com.example.financialcore.CoreSchemaITcom.example.financialcore.account.OpeningIntegrationTest 두 class입니다. frozen staged reference의 source-local @Test도 두 개이고 selected test도 두 개입니다.

하지만 둘 다 stage-only이고 active packaged root에는 exact selector source file이 0개입니다. learner root에 stage를 조립하고 source identity를 결박하지 않으면 bare packaged root Green이라고 말할 수 없습니다.

실제 기술 이름two staged class selectors with absent active packaged test sources

12. runner가 JUnit XML에서 직접 Gate하는 값은 무엇인가요?

기대 두 class와 XML의 unique class 집합을 exact 비교하고 aggregate tests>=2, failures=0, errors=0, skipped=0을 요구합니다. selector 문자열과 class count는 source identity hash가 아닙니다.

runner는 source SHA를 marker에 기록하지 않습니다. 따라서 같은 class name의 어느 bytes가 compile됐는지, full suite가 Green인지, 오래된 결과가 없는지까지 이 조건만으로 말할 수 없습니다.

실제 기술 이름exact JUnit class-set and aggregate result Gate without source-hash binding

W15 runner의 두 staged selector, isolated schema, cardinality 1,2와 2,0, 증거 파일의 경계
그림 한눈에: 두 selector, tests 하한, isolated schema, 현재 NOT_RUN 상태를 한 흐름으로 봅니다.

13. CoreSchemaIT과 OpeningIntegrationTest의 직접 증거는 어디까지인가요?

CoreSchemaIT은 public BASE TABLE 이름이 account, business_tx, ledger_entry, idempotency_request와 정확히 같은지 봅니다. column·PK·FK·CHECK·index·cardinality는 검사하지 않습니다.

OpeningIntegrationTest는 customer-1, OPEN-100, 12_345 정상 호출 뒤 account·OPENING business transaction·같은 account의 OPENING ledger count가 각각 1인지 봅니다. rollback, single snapshot, amount·balance 일치는 직접 증명하지 않습니다.

실제 기술 이름exact table-name set and success-path opening persistence counts

14. key와 index Gate가 exact inventory가 아닌 이유는 무엇인가요?

runner는 PK>=4, FK>=2, UNIQUE>=2만 거부선으로 사용합니다. V001의 직접 token은 REFERENCES 3과 UNIQUE 4지만, runner가 그 exact 수를 강제하는 것은 아닙니다.

index는 definition과 count를 evidence에 기록하지만 index는 기록만 하고 minimum 또는 exact count로 Gate하지 않습니다. 파일 출력 뒤 key minimum 검사라 실패해도 부분 evidence가 남을 수 있습니다.

실제 기술 이름lower-bound key Gate, record-only index inventory, and partial-evidence window

PK·FK·UNIQUE·CHECK가 보장하는 저장 모양과 권한·원자성·대사를 보장하지 않는 경계
그림 한눈에: source의 exact 수와 runner의 하한·기록 전용 항목을 같은 표에서 비교합니다.

15. Compose mode와 Container mode의 영향 범위는 어떻게 다른가요?

Compose mode는 고유 project를 올리고 자신이 만든 project와 volume을 finally에서 내립니다. startup 일부 실패 때도 owner cleanup을 시도합니다.

Container mode는 사용자가 넘긴 실행 중 PostgreSQL container 안에서 기존 w15_schema를 drop한 뒤 다시 만들고, 종료 후 그 schema를 남깁니다. named schema 안에서 destructive하므로 supplied container를 보존한다고 표현하면 안 됩니다.

실제 기술 이름owned Compose lifecycle versus supplied-container schema replacement

16. D1 식별자 문서 validator는 무엇을 보고 무엇을 못 보나요?

erd-identifiers.md의 필수 section·token·네 source path와 실제 SHA, placeholder 제거, 최소 길이를 확인합니다. 자동 결과도 MANUAL_REVIEW_REQUIRED입니다.

네 table의 entity 의미, candidate/business key 판정, transfer 1:N 반례가 논리적으로 맞는지는 사람이 schema 원자료와 대조해야 합니다. hash equality는 의미 quality가 아닙니다.

실제 기술 이름structure/token/hash validation with mandatory semantic review

17. 함수 종속과 세 이상 현상은 어떻게 연결되나요?

함수 종속 X→Y는 같은 X가 주어졌을 때 Y가 하나로 결정된다는 뜻입니다. owner 사실을 ledger마다 복제하면 같은 account에 여러 owner 표기가 생길 수 있습니다.

새 owner를 넣기 어려운 insertion anomaly, 이름을 일부만 바꾸는 update anomaly, 마지막 ledger 삭제와 함께 owner 사실을 잃는 deletion anomaly가 생깁니다. 종속을 적은 뒤 사실의 소유 table을 정합니다.

실제 기술 이름functional dependency driving insertion, update, and deletion anomaly analysis

중복 저장에서 삽입·수정·삭제 이상이 생기고 함수 종속을 기준으로 분리하는 흐름
그림 한눈에: 중복 저장에서 세 anomaly가 생기고 결정자 기준으로 분리되는 흐름입니다.

18. 의도적 비정규화는 언제 설계 선택이 되나요?

account.balance처럼 빠른 현재값 조회가 필요하거나 idempotency response처럼 replay가 필요한 경우 일부 사실을 가까이 둘 수 있습니다. 이것은 정규화 실패를 숨기는 말이 아닙니다.

왜 복사하는지, 갱신 owner가 누구인지, transaction 안에서 어떻게 함께 바꾸는지, ledger와 얼마나 자주 대사하는지, mismatch를 어떻게 감시하는지를 함께 문서화해야 합니다.

실제 기술 이름controlled denormalization with update ownership and reconciliation

19. 1NF·2NF·3NF·BCNF의 판정 질문은 무엇인가요?

1NF는 한 칸이 원자값이고 반복 group이 없는지, 2NF는 복합 candidate key 일부에만 의존하는 non-key가 없는지, 3NF는 key가 아닌 값이 다른 non-key를 정하는 이행 종속이 없는지 봅니다.

BCNF는 모든 determinant가 candidate key인지 묻습니다. 정규형 이름만 쓰지 말고 attribute 집합, FD의 좌·우, candidate key, 위반 근거를 함께 적어야 합니다.

실제 기술 이름normal-form tests over atomicity, partial dependency, transitive dependency, and determinants

20. 정규화 분해에서 왜 무손실 join과 종속 보존을 확인하나요?

table을 나누었을 때 원래 relation을 join으로 정확히 되살릴 수 있어야 가짜 row나 정보 손실을 피합니다. 필요한 business dependency를 한 relation이나 enforceable constraint에서 유지할 수 있는지도 봐야 합니다.

복합 key가 없는 table에 2NF 부분 종속을 억지로 적용하거나, BCNF라는 이름만 보고 무조건 분해하면 안 됩니다. 분해는 주어진 FD와 candidate key에 대한 결정입니다.

실제 기술 이름lossless-join decomposition and dependency-preservation review

1NF, 2NF, 3NF를 원자값·부분 종속·이행 종속 제거 순서로 보여 주는 사다리
그림 한눈에: 정규형 사다리 뒤에 무손실 join과 종속 보존 확인이 이어집니다.

21. 물리 constraint가 보장하지 않는 대표 규칙은 무엇인가요?

balance>=0 CHECK는 저장되는 한 row의 음수만 막을 뿐 concurrent withdraw 안전이나 ledger 합과 balance의 대사를 증명하지 않습니다. account_id FK는 account 존재를 보지만 요청자의 owner authorization은 보지 않습니다.

ledger의 amount와 signed_amount 사이에 부호·절댓값 일치 CHECK가 없고, idempotency composite UNIQUE도 request hash 비교·response replay·atomic claim protocol 전체를 구현하지 않습니다.

실제 기술 이름declarative storage constraints versus transactional and authorization invariants

22. D5의 ERD PDF와 연습용 DDL에는 어떤 provenance 경계가 있나요?

D5의 짧은 DDL block은 연습용 발췌이며 canonical V001 전체가 아닙니다. 실제 source of truth는 hash-bound migration과 schema output입니다.

project-erd.pdf의 header·EOF·byte·SHA와 review field를 검사해도 선 방향·nullable·업무 의미가 맞는지는 자동 판정되지 않습니다. 그래서 expected marker에 MANUAL_REVIEW_REQUIRED가 남습니다.

실제 기술 이름physical-ERD artifact integrity separated from semantic schema equivalence

23. Q16 일별 성공·실패 count의 grain과 0분모 경계는 무엇인가요?

입력 grain은 business transaction 한 건, 출력 grain은 business_date 하루 한 행입니다. FILTER로 SUCCESS와 FAILED를 따로 세며 핵심 요구는 두 count입니다.

fixture는 9일이고 2026-07-02=0/0/NULL, 2026-07-01=2/1/66.67, 2026-12-28=0/3/0.00입니다. rate는 선택 열이며 NULLIF로 0분모를 피합니다. DATE 열을 사용해 timezone date-cast 함정을 피합니다.

실제 기술 이름date-grain conditional aggregation with zero-safe optional rate

날짜별 SUCCESS·FAILED 건수와 분모 영일 때 NULL이 되는 학습용 Q16 도식
그림 한눈에: 두 count와 0·0·NULL 경계를 날짜별로 확인합니다.

24. Q21 scalar AVG subquery의 exact fixture oracle과 경계는 무엇인가요?

uncorrelated aggregate subquery는 전체 balance 평균 266287.375 한 행을 반환합니다. strict greater-than 결과는 account ID 106·107·108, 총 3행입니다.

prompt에 status filter가 없어 CLOSED 107도 포함됩니다. 평균과 같은 행은 빠지고, 빈 입력의 AVG는 NULL이므로 바깥 비교도 true가 되지 않습니다.

실제 기술 이름uncorrelated one-row scalar AVG comparison with strict boundary

전체 평균 266287.375보다 큰 계좌 106·107·108을 고르는 scalar subquery 도식
그림 한눈에: 한 평균선과 그 위의 세 account, CLOSED 포함 경계를 봅니다.

25. Q22 correlated MAX subquery가 동률을 보존하는 이유는 무엇인가요?

바깥 account의 customer_id와 같은 customer만 안쪽에서 좁혀 MAX balance를 구하고, 바깥 row의 balance가 그 MAX와 같은지 비교합니다. 그래서 최대값과 같은 모든 account row가 남습니다.

fixture 결과 표시 순서는 105·106·107·104·108, 5행이고 account 없는 customer 5는 나오지 않습니다. query shape는 동률을 보존하지만 supplied fixture의 같은-customer 최대 동률 row는 0개입니다.

실제 기술 이름customer-correlated MAX semi-filter preserving maximum ties

고객별 최대 잔액 계좌를 고르고 동률을 모두 보존하는 correlated subquery 도식
그림 한눈에: customer별 MAX와 tie 보존, account 없는 customer 제외를 봅니다.

26. Q16·Q21·Q22를 정본 workbook 답안이라고 부르면 왜 안 되나요?

workbook README와 fixture contract는 learner answer file을 제공하지 않는다고 밝힙니다. 세 SQL 파일은 prompt와 deterministic fixture를 근거로 audit이 만든 fixture-bound 학습용 예시입니다.

따라서 oracle을 재현하고 grain·반례를 설명하는 데는 쓸 수 있지만 shipped 정본 답안, 모든 운영 schema의 보편 query, 증권 상품별 규칙이라고 일반화할 수 없습니다.

실제 기술 이름audit-authored illustrative SQL with no shipped canonical answer

27. D6의 40문항 진단은 점수 외에 무엇을 남겨야 하나요?

SQLD 데이터 모델링 40문항을 50분에 풀고 오답을 entity/key, cardinality, normalization, reading 네 범주로 분류합니다. 맞았지만 근거가 약한 문항은 lucky로 표시합니다.

modeling-diagnostic.csv 40행과 정답 없는 prompt snapshot 40행을 만들고, 오답 상위 두 범주에서 48시간 뒤 다시 풀 10문항 queue를 item ID로 연결합니다.

실제 기술 이름40-item timed diagnostic, error taxonomy, and delayed retrieval queue

40문항 오답을 entity/key·cardinality·normalization·reading 네 범주로 나누는 진단판
그림 한눈에: 40문항에서 네 오답 범주와 상위 두 범주 10문항 재시험으로 이어집니다.

28. D1–D6의 최종 Green 주장 전에 남는 자동검사 한계는 무엇인가요?

D1은 section·token·source hash를, D3·D4·D6은 최소 byte·nonblank line·placeholder·SHA를, D5는 PDF container·hash·review field를 주로 봅니다. 자동 validator는 식별자·함수 종속·정규형·ERD 의미의 정확성을 모두 읽지 않습니다.

runner도 active root source 부재, lower-bound key gate, record-only index, 부분 evidence, Container mode mutation 경계를 가집니다. 그러므로 source audit PASS와 expected marker만으로 current W15 Green, formal normalization proof, 증권 업무 규칙 완료를 말할 수 없습니다.

실제 기술 이름evidence-bounded D1–D6 contract with runtime and semantic review still open