낯선 시스템 앞에서 · 같은 말이 세 시스템에서 다른 뜻이다 · 실습
고객·주문·활성 — 세 시스템이 다른 것을 센다
목표
고객이 "고객"·"활성"·"주문" 이라 부르는 것이 세 시스템에서 각각 무엇인지 대조표로 굳히고, 같은 이름이 가리키는 집합의 크기와 겹침을 자료로 잰다. 식별자 정규화를 바꾸면 답이 통째로 달라진다는 것을 직접 보고, 같은 이름 다른 집합과 다른 이름 같은 집합을 갈라 보고서로 낸다.
왜 중요한가
회의에서 "활성 고객이 몇 명이죠" 라고 물으면 세 사람이 세 숫자를 답하는데 셋 다 맞을 수 있다. 영업은 상태 글자가 A 인 행을, 청구는 청구 가능한 계정을, 운영은 최근에 로그인한 사람을 센 것이다. 세 정의는 각자의 업무에서 옳고, 틀린 것은 하나의 낱말이 세 정의를 다 담고 있다고 믿은 쪽이다.
이 어긋남은 오류로 드러나지 않는다. 쿼리는 성공하고 보고서는 인쇄된다. 드러날 때는 이미 그 숫자로 결정이 내려진 뒤다. 그래서 첫 주에 용어-식별자 대조표를 파일로 만들어 두고, 집계 도구가 그 파일을 읽게 한다.
집합을 견주려면 "같은 것" 이 무엇인지부터 정해야 한다. RFC 5321 2.4 절은 메일 주소의 로컬 파트를 대소문자를 가려 다루라고 정하고 도메인은 가리지 않는다고 적는다. 규격대로 보면 겹치는 사람이 한 명도 없고, 전부 소문자로 눕히면 거의 다 겹친다 — 같은 데이터에서 두 답이 나온다.
채점기는 여러분이 적어 낸 문구를 믿지 않는다. 매번 다른 표 이름과 값으로 만든 데이터베이스에 여러분의 집계기를 실제로 돌려 집합 크기와 겹침을 직접 계산한 값과 대조한다.
단계
1. /root/glossary/gen_systems.py 를 만들어 실행해 /root/glossary/systems.db 를 만드세요. 영업(crm)·청구(bill)·운영(ops) 세 시스템의 표 여섯 개가 들어갑니다.
2. /root/glossary/terms.json 에 용어-식별자 대조표를 적으세요. 고객·활성·주문 세 용어 × 세 시스템 = 아홉 줄이고, 줄마다 system·table·id_column·predicate 를 적습니다.
3. /root/glossary/census.py 를 만들어 대조표의 줄마다 집합 크기를 재고 /root/glossary/census.json 을 쓰게 하세요.
4. --overlap <경로> 를 더해 한 용어 안에서 시스템 두 개씩 견준 결과를 쓰게 하세요. 겹친 수와 한쪽에만 있는 수를 냅니다.
5. --normalize none|strict|loose 를 더하세요. strict 는 공백을 떼고 도메인만 소문자로, loose 는 공백을 떼고 전부 소문자로 눕힙니다.
6. loose 로 잰 값으로 /root/glossary/conflicts.json 을 만들어 용어마다 가장 어긋나는 시스템 쌍과 자카드 계수를 적으세요.
7. /root/glossary/naming.json 에 같은 이름 다른 집합(자카드 0.1 이하)과 다른 이름 같은 집합(고객 용어의 칼럼 쌍 중 자카드 0.5 이상)을 갈라 적으세요.
8. /root/glossary/glossary_report.md 에 네 절로 보고하세요.
참고
- 실행 계약:
python3 /root/glossary/census.py --db <DB> --terms <대조표> --out <집계 JSON> [--overlap <겹침 JSON>] [--normalize none|strict|loose]는 한 줄 요약을 표준출력에 내고 종료 코드 0 으로 끝납니다. 입력을 읽을 수 없으면 3 입니다. - 대조표:
{"entries": [{"term": …, "system": …, "table": …, "id_column": …, "predicate": "SQL 조건", "note": …}]}. predicate 는WHERE뒤에 그대로 붙는 조건 문자열이고, 조건이 없으면1=1입니다. - 집계 JSON:
{"normalize": …, "counts": [{"term", "system", "table", "rows", "distinct_ids"}]}. counts 는 term, system 오름차순입니다. rows 는 조건에 맞는 행 수, distinct_ids 는 정규화한 식별자의 가짓수입니다. - 겹침 JSON:
{"normalize": …, "pairs": [{"term", "left", "right", "both", "left_only", "right_only"}]}. 한 용어 안에서 시스템 이름 오름차순으로 두 개씩 묶고, left 가 right 보다 앞섭니다. - 정규화: none 은 값 그대로, strict 는
공백 제거 + 마지막 @ 뒤만 소문자, loose 는공백 제거 + 전부 소문자입니다. - conflicts.json:
{"normalize": "loose", "terms": [{"term", "sizes": {시스템: 크기}, "min_pair": [시스템, 시스템], "min_jaccard": 소수점 셋째 자리, "conflict": true|false}]}. 자카드는 교집합 크기를 합집합 크기로 나눈 값이고, 합집합이 비면 1.0 으로 봅니다. conflict 는 min_jaccard 가 1.0 미만일 때 참입니다. - naming.json:
{"same_name_different_thing": [{"term", "min_pair", "jaccard"}], "different_name_same_thing": [{"a", "b", "jaccard"}]}. a 와 b 는시스템.표.칼럼꼴이고 a 가 b 보다 앞섭니다. - 흔한 실수: 대조표에 조건을 빼먹기(활성의 차이는 표가 아니라 조건에 있습니다), 정규화 규칙을 집계마다 다르게 쓰기, 겹침을 세기 전에 중복을 없애지 않기.
- 자카드 문턱값 0.1 과 0.5, 그리고 소수점 셋째 자리 반올림은 이 실습의 가정입니다. 표준이 정해 주는 값이 아니라 보고서에 적어 두고 쓰는 값입니다.
- 참고 문서: [RFC 5321 2.4 절](https://www.rfc-editor.org/rfc/rfc5321.html)은 메일 주소의 대소문자 규칙을, [RFC 4949](https://www.rfc-editor.org/rfc/rfc4949.html)는 같은 낱말을 여러 뜻으로 쓰는 문제를 다루는 용어집의 본보기를, [SQLite SELECT 문서](https://www.sqlite.org/lang_select.html)는 INTERSECT 와 EXCEPT 를 설명합니다.
단계 8개
- 시스템 세 대를 손에 쥐기
- 용어-식별자 대조표 만들기
- 같은 이름의 집합 크기 재기
- 두 시스템씩 견주기
- 무엇을 같다고 볼 것인가
- 같은 이름이 다른 집합을 가리킨다
- 다른 이름이 같은 것을 가리킨다
- 무엇을 합의할지 적기