Releases: maxidea1024/tabbit
Release list
v0.1.0
첫 릴리즈입니다. 아래가 최근에 바뀐 것이고, 도구 전체의 모습은 절 끝의
담긴 것에 있습니다.
-
샘플이 전부 합성 데이터가 되었습니다. 검증에 쓰던 상용 프로젝트의 워크북을 들어내고,
같은 규모와 같은 표기를 재현하는 가상 코퍼스로 바꿨습니다
(샘플).sprout— 출시 전 소규모. 워크북 17개·테이블 71개·109,218행. 이 도구가 설계하지
않은 규칙으로 쓰인 시트를 그대로 읽는 쪽이고, 변환하면 무엇이 나오는가의 답입니다 —
지원하는 모든 언어의 산출물이 커밋되어 있습니다canopy— 라이브 대규모. 워크북 42개·정의된 이름 549개·셀 873만. 테이블의 경계가
워크북의 정의된 이름인 레이아웃이고, 중첩 컬럼·매트릭스 표·지역 변종·제약 행을 전부
담습니다. 같은 코퍼스가.xlsx와.xlsb양쪽에 있어 두 리더의 결과가 같아야 하는
게이트로 섭니다- 값이 아니라 분포를 재현합니다. 정본은
schema/*.tsv이고 워크북은 생성기가 만듭니다.
표기와 값이 갈라져 있어, 레이아웃을 읽는 방식이 바뀌면 그 파일들의 diff로 드러나고
데이터가 바뀌면 드러나지 않습니다 - 벤치마크를 전면 재측정했습니다. 데이터셋이 바뀌었으므로 파일 크기·로드 시간·CPU·
메모리 전부 다시 쟀고, 기준이 바뀐 사실을 문서 앞에 적었습니다
(벤치마크)
-
찾은 문제를 로그가 아니라 보고서로 냅니다. 실행이 끝나면 HTML 한 장과 JSON 한 장을
남기고, 경고 이상이면 브라우저로 엽니다
(사용 · 설계).- 멈춘 실행이 본론입니다. 타깃은 임포트·쿠킹·검증을 전부 통과해야 도달하는데, 이
산출물이 가장 필요한 실행은 거기까지 가지 못한 실행입니다. 그래서 타깃이 아니라 실행 자체에
붙어 있고, 예외로 끝난 경로에서도 씁니다. 종료 코드에는 관여하지 않습니다. - 구글 시트의 셀은 클릭 한 번입니다. 위치가 이미 셀 단위 딥링크였고, 그것이 로그에서
버려지고 있었습니다. xlsx는 셀을 여는 이식 가능한 URL이 없으므로 링크인 척하지 않고
위치 텍스트와 복사 버튼을 냅니다. - 누적을 수치로 보입니다. 직전 리포트와 대조해 신규 · 지속 · 해소를 셉니다. 대조는
참고이지 판정이 아니어서 종료 코드에도 검증에도 관여하지 않습니다 — 시트에 행이 끼어들면
같은 문제가 신규+해소 한 쌍으로 나타나기 때문이고, 그 한계는 페이지에 적혀 있습니다. - 겉모습은 GitHub Primer입니다 — 색 토큰 · 서체 · 박스 · 알약 라벨 · 밑줄 내비게이션 ·
버튼까지. 이 페이지를 읽는 사람은 하루의 대부분을 그렇게 생긴 화면 앞에서 보내고,
도구마다 제 나름의 회색 상자 방언을 쓰면 내용을 읽기 전에 방언부터 익혀야 합니다.
검색은 찾은 자리를 표시하고, 검색창에는 지움 버튼이 있습니다. - 행에서 앞자리는 내용입니다. 무엇이 잘못됐는지가 먼저 오고 위치는 행 끝입니다 —
위치는 맥락이지 내용이 아닌데 맨 왼쪽 고정폭 자리를 차지하고 있었습니다. 보고가 백틱으로
인용한 이름은 코드로 놓이고(그 이름이 윗 행과 다른 유일한 부분입니다), 모든 위치가
공유하는 폴더는 머리글에서 한 번만 말합니다. - 복사 버튼은 보고 전체를 담습니다 — 문장, 그 아래 위치, 구글 시트면 셀을 여는 링크,
그리고 메시지 ID. 콘솔이 찍는 형태 그대로라 동료에게 그대로 보낼 수 있습니다. 위치만
복사하던 것은 아무도 보내지 않는 것이었습니다. - 목록은 한 번에 하나, 행은 한 줄입니다. 문제 · 알려진 문제 · 해소됨 · 기록은 탭이고,
행은 한 줄로 잘려 클릭하면 펼쳐집니다 — 보고 하나는 문단이고 그런 문단 14개는 벽인데
행마다 다른 부분은 문장 앞쪽에 있기 때문입니다. 메시지 ID는 닫힌 행에 없습니다:
CI가 필터하는 이름이지 시트를 가진 사람이 할 수 있는 일이 아니라서, 펼친 행과 종류별
묶기의 머리글에만 둡니다. - 평면 목록이 아니라 워크북·시트로 묶입니다. 한 실행이 5,831건을 낸 적이 있고, 그 규모의
평면 목록은 벽입니다. 행 하나짜리 자리는 그룹을 만들지 않고 그냥 행입니다 — 실측에서
시트 12개가 각각 1건이었고, 그러면 항목마다 머리글을 하나씩 무는 평면 목록이 됩니다.
묶는 축은 둘이고(시트별은 일하는 순서, 종류별은 이해하는 순서) 전환은 클릭 하나입니다. - 보는 사람이 없으면 열지 않습니다.
CI환경 변수 · 리다이렉트된 출력 ·--silent는
설정보다 우선합니다. 마지막 리포트는--show-report로 변환 없이 다시 엽니다. - 새 검출은 하나도 추가하지 않았습니다. 단계마다 수집되어 인쇄되고 버려지던 것을 남길
뿐이고, 콘솔과 파일 로그는 그대로입니다.
- 멈춘 실행이 본론입니다. 타깃은 임포트·쿠킹·검증을 전부 통과해야 도달하는데, 이
-
바뀐 것이 없으면 아무것도 하지 않습니다. 지난 실행이 무엇을 읽고 무엇을 썼는지 기록해
두었다가 비교하고, 전부 그대로면 즉시 종료합니다
(사용 · 설계).- 실측이 먼저였습니다. 테이블 548개·워크북 36개(1,149 MB)를 7개 타깃으로 내는 실행이
161초이고, 그 절반이 임포트와 쿠킹, 나머지 절반이binary·json익스포트입니다 —
코드 생성 5개 언어는 합쳐 7.5초입니다. 어느 한쪽만 캐시해도 절반밖에 줄지 않으므로
양쪽을 함께 건너뜁니다. - 키가 셋입니다. recipe의 전역 설정과 입력이 모델을 정하고,
Validation섹션이 검증을,
Targets항목 하나하나가 그 항목의 산출을 정합니다. 그래서 타깃 하나의 설정을 고친 것이
워크북 36개를 다시 읽을 이유가 되지 않습니다 — 그 항목만 다시 냅니다. - 수정 시각만 바뀐 것은 바뀐 것이 아닙니다. 크기와 시각이 어긋난 파일만 해시해서
내용으로 판정합니다.git checkout은 받은 파일 전부의 수정 시각을 지금으로 바꾸므로,
시각만 보는 캐시는 체크아웃 한 번을 넘기지 못합니다. - recipe의 주석과 공백, 설정 순서는 키에 들어가지 않습니다. 파싱된 문서를 정규화해서
해시하므로, 제외 목록에 이유를 적어 넣는 것이 변환 한 번의 값이 되지 않습니다. - 디렉터리 목록도 기록합니다. 워크북이 하나 추가된 것은 기존 어느 파일도 바꾸지
않으므로, 파일 목록만으로는 보이지 않습니다. - 강제가 둘입니다.
--full은 캐시를 의심할 때(입력부터 전부 다시),--force-output은
캐시를 믿으면서 산출물만 다시 원할 때입니다.--validate-only와 함께 쓰는 것은 거절합니다. - 건너뛴 항목의 파일은 「이 실행이 쓴 것」에 포함됩니다. 스윕은 이 실행이 쓰지 않은 생성
파일을 지우므로, 이것이 없으면 캐시가 맞다고 판정한 파일을 그 실행이 전부 지웁니다. - 건너뛰지 않는 것. 파일을 하나도 쓰지 않는 항목입니다 — 데이터베이스 익스포트와
히스토리 기록이 그렇습니다. 산출물을 해시해서 확인할 수 있는 것만 건너뜁니다. 그리고
히스토리·요약 타깃이 있는 recipe는 커밋 식별자가 키에 들어가므로, 새 커밋은 전체 실행입니다. - 검증은 캐시를 쓰지 않습니다.
--validate-only가 「지난번에 통과했다」로 통과하면
게이트가 아닙니다. - 왜 전체를 다시 하는지 항상 말합니다. 어느 워크북이 바뀌었는지, recipe의 어느 쪽이
바뀌었는지, 다른 빌드가 쓴 캐시인지. 이유를 대지 못하는 캐시는--full이 습관이 되어
없는 것과 같아집니다. - 구글 시트는 Drive의
version으로 판정합니다. 문서는 크기도 수정 시각도 없으므로
drive.metadata.readonly스코프를 더 받아 카운터 하나를 읽습니다. 셀은 읽지 않습니다.
물어볼 수 없으면 바뀐 것으로 보고 가져오고, 무엇을 허용하면 되는지와 어느 파일을 지우면
동의를 다시 받는지까지 출력합니다. - 건너뛴 실행도 낡은 생성 파일은 지웁니다. 아무것도 하지 않고 끝나면 스윕에 도달하지
못하므로, 「테이블을 지웠을 때 그 파일이 없어지는가」가 그날 다른 것이 바뀌었는지에
달리게 됩니다. 이것을 잡은 것은 기존 스윕 게이트입니다 — 캐시가 「건너뛴다」고 보고하며
파일을 남겼습니다. --detailed-exit-code로 할 일이 없던 실행을 구분합니다. 종료 코드2입니다. 다음
단계가 배포인 파이프라인이 쓰는 형태이고, 플래그 뒤에 둔 이유는 호환입니다 — 기본으로
0이 아닌 값을 내면 뒤에 단계를 이어 붙인 스크립트가 캐시가 처음 동작한 날 멈춥니다.- 캐시는 커밋 대상이 아닙니다. 절대 경로와 그 기계의 파일 상태를 담습니다.
- 실측이 먼저였습니다. 테이블 548개·워크북 36개(1,149 MB)를 7개 타깃으로 내는 실행이
-
실행이 여는 두 줄에 버전을 적습니다. 도구 빌드가 한 줄,
.tcb형식 번호와 .NET
런타임과 플랫폼이 다음 줄, 그 아래 빈 줄입니다 — 넷을 한 줄에 담으면 아무것도 찾을 수 없는
줄이 되고, 빈 줄이 없으면 그 뒤 수백 줄의 앞 두 줄이 됩니다. 받은 로그에 대해 묻게 되는
것이 대개 이 넷 중 하나이고, 그중 형식 번호가 유일하게 읽는 쪽과 어긋날 수 있는
값입니다. 빌드 문자열은 빌드 캐시의 키에 쓰는 것과
같은 값이라 한 곳에서 나옵니다 — 「다른 빌드가 쓴 캐시입니다」라는 보고와 첫 줄이 어긋나면
아무도 무엇을 해야 할지 알 수 없습니다. 표준 출력이 남의 입력인 실행
(--new-encryption-key,--out없는 조회)에는 적지 않고 파일 로그에만 남깁니다. -
실행이 단계별 소요 시간을 스스로 말합니다. 임포트·쿠킹·검증·산출·커밋과,
--verbose에서는
타깃별로. 지금까지는 총 소요만 나왔으므로 어디가 느린지 알려면 종료 지점을 바꿔 세 번 돌리고
로그의 타임스탬프를 손으로 빼야 했습니다. -
명령줄 옵션마다 캐시에 대한 뜻을 선언합니다.
--verbose는 산출을 바꾸지 않으므로 캐시를
버리지 않고,--target-side는 바꾸므로 키에 들어갑니다. 선언이 없는 옵션이 있으면 테스트가
실패합니다 — 분류를 잊은 결과가 「조용히 낡은 산출」이 아니라 「빌드가 안 됨」이어야 합니다. -
로그 한 줄이 수준과 단계를 먼저 말합니다.
[W] [Cooking ] ...형식이고, 콘솔과 파일이
같은 구성입니다 — 콘솔은 지켜보는 동안 읽는 것이라 수준을 한 글자로, 파일은 나중에 읽는
것이라 시각과 함께 세 글자로 적습니다 (보기).- 단계는 그 줄을 쓴 클래스가 밝힙니다. 호출 스택에서 미루어 짐작하는 것이 아니라
클래스마다 한 줄로 적어 둡니다.Loading·Importing·Cooking·Validating·Exporting·
Committing·Recording일곱 가지이고, 밝히지 않은 줄은Tabbit으로 나갑니다. - 메시지 쪽은 하나도 손대지 않았습니다. 선언한 이름이 정적
Log를 가리므로 기존 호출
132곳이 그대로입니다.
- 단계는 그 줄을 쓴 클래스가 밝힙니다. 호출 스택에서 미루어 짐작하는 것이 아니라
-
시트의 날짜를 어느 시간대로 읽을지 recipe에 적습니다.
TimeZone이 그것이고, 저장되는 값은
언제나 UTC입니다 — 이 설정이 정하는 것은 시트에 적힌 시각을 어느 시간대의 것으로 읽을지 하나뿐입니다
(설정 ·
설계).- 지역 이름과 고정 오프셋을 모두 받습니다.
Asia/Seoul·Korea Standard Time같은 이름은
서머타임을 포함한 그 지역의 역사를 따르고,+09:00·+0900·+09·Z는 일 년 내내 같습니다.
후자는 기계에 시간대 데이터가 없어도 되므로, 컨테이너에서 도는 변환이 이름 조회에 매이지
않습니다. - 소스 항목별로 다르게, 명령줄로 강제. 항목의
TimeZone이 recipe 전체 설정보다 우선하고,
--time-zone은 그 둘 다를 덮어씁니다 — recipe가 시간대를 잘못 적고 있는 실행을 위한
것이므로, 덮어쓸 대상이 바로 그 항목별 설정입니다. 적용한 값은 실행 로그에 한 줄로 남습니다. - 오프셋을 적은 셀이 실행 기계에 따라 달라지던 것을 고쳤습니다.
2022-01-24T10:30:00Z가
변환을 도는 기계의 시간대로 옮겨져 읽혔습니다 — KST PC에서는 19:30, UTC 러너에서는 10:30이
되었고, 어느 쪽도 그 사실을 말하지 않았습니다. 이제 셀이 적은 오프셋이 그 값을 정하고,
recipe 설정보다 우선합니다. - 서머타임의 두 자리. 시계가 건너뛴 시각은 그 지역에 존재하지 않았으므로 셀 위치와 함께
거절합니다. 두 번 지나간 시각은 표준시 쪽으로 읽고 그런 셀이 몇 개였는지 보고합니다. - 비워 두면 지금까지와 같습니다. 셀이 이미 UTC로 적힌 것으로 보므로 값이 달라지지 않고,
골든도 한 바이트도 바뀌지 않았습니다. 저장 타입의 크기(초 단위·32비트)는 별도 검토입니다.
- 지역 이름과 고정 오프셋을 모두 받습니다.
-
HTML 문서를 데이터 확인 도구로. 생성되는 페이지 구성과 항해가 바뀌었습니다. 데이터·형식·
생성기는 그대로이고, 바뀐 것은 이 타깃의 산출물뿐입니다
(가이드 · 설계).- 테이블당 페이지 하나입니다. 전부 한 페이지였고, 최대 테이블이 10만 행인 워크북에서 그
페이지가 36.9 MB였습니다 — 그 테이블 하나 때문에 나머지 66개를 볼 수 없었습니다.
MaxRowsPerTable(기본 1,000,0은 무제한)이 페이지가 보여주는 행 수를 정하고, 적용되면
몇 행 중 몇 행인지 페이지에 적힙니다. - 모든 페이지에 상단 바·브레드크럼·형제 목록이 있습니다. 예전에는 상세 페이지에서 나가는
링크가 하나도 없어 브라우저 뒤로가기가 유일한 수단이었습니다. 목록이 페이지 안에 있으므로
파일 하나만 전달받아도 이동이 됩니다. - 전체 윤곽을 개요가 제시합니다. 테이블·행·컬럼·enum·레이블·상수·셀 개수와, 컬럼의
타입별·역할별·측별 분포, 최대 테이블 목록입니다. 여기에 전체 컬럼 색인(fields.html)이
더해집니다 — 같은 컬럼 이름의 타입이 어긋난 곳을 이름 정렬로 찾을 수 있습니다. - enum 값은 커서를 올리면 enum 전체가 카드로 나타납니다. 이동하지 않고 확인됩니다.
정의는 페이지마다 한 번만 싣습니다 — 칸마다title에 담으면 10만 행 테이블에서 enum 전체가
10만 번 반복됩니다. - 참조와 사용처가 양방향입니다. 테이블 페이지가 자기를 가리키는 컬럼을, enum 페이지가
자기를 쓰는 컬럼을 함께 냅니다. - 표에 필터와 정렬(5,000행까지)이 붙고, 빈 문자열·값 없음·빈 배열이 구분되어 표시되고,
키 컬럼이 가로 스크롤에서 고정됩니다. 폐기된font·align마크업이 CSS로 바뀌면서
어두운 테마도 따릅니다. 외부 요청은 계속 0개입니다. - 테마를 고를 수 있습니다. 상단 바의 버튼이 시스템 → 밝게 → 어둡게를 순환하고 선택은
localStorage에 남습니다. 페이지가 그려지기 전에 적용되므로 이동할 때 다른 테마가
번쩍이지 않습니다. - 종류마다 목록 페이지.
tables.html·fields.html·enums.html·
constantsets.html이 각각 정렬·필터되는 목록이고, 개요는 카운터와 분포만 남습니다 —
목록을 개요에 두면 프로젝트가 커질수록 카운터 아래가 이름의 벽이 됩니다. - 아이콘과 브랜드 마크. 테이블·컬럼·enum·상수 세트·워크북·시트에 인라인 SVG 심볼을
붙였습니다(이모지가 아닌 것은 플랫폼마다 다른 그림이 되기 때문입니다). 상단 바에 브랜드
마크가 들어가고, 스크롤바도 얇은 것으로 지정합니다. - 중첩·옵셔널 시트를 문서화합니다. 이 타깃은 네 가지 형태(레코드 그룹 · 다중 중첩 ·
옵셔널 필드 · 옵셔널 원소) 중 어느 것도 선언하지 않고 있었습니다 — 그래서 그런
워크북은 문서가 한 장도 생성되지 않았고, 그것이 데이터를 들여다볼 필요가 가장 큰 시트
입니다. 컬럼을 그리는 타깃이라 구현이 필요한 것은 없었고, 선언과 그룹 이름을 읽는 자리
하나였습니다. - 헤더와 키 컬럼이 고정됩니다. 표가 페이지가 아니라 자기 컨테이너 안에서 스크롤되므로
값을 보면서 컬럼 이름을 잃지 않습니다. 헤더 행 높이를 고정해 스택이 첫 값을 덮던 것도
함께 고쳤고, 설명이 하나도 없는 시트에서는 설명 행과 Description 열을 그리지 않습니다. - 참조 값이 그 행으로 갑니다. 키가 적혀 있는데 그 행을 찾는 방법이 없었습니다. 대상이
여럿인 컬럼은 후보 테이블을 함께 내고 읽는 사람이 고릅니다. 행 상한 때문에 그 페이지에
없는 행이면 페이지까지만 가리킵니다 — 없는 앵커를 만들지 않습니다. - 참조 그래프 페이지(
references.html)를 추가했습니다. 테이블에 커서를 올리면 그
테이블의 간선만 남습니다 — 실측 노드 323개·간선 637개에서 47개만 남으므로, 수백 개가
겹치는 가운데에서도 읽힙니다. 층으로 배치해 모든 화살표가 앞을
향하고, 자기 참조는 고리입니다. 좌표는 생성기가 계산하고 페이지는 인라인 SVG를 담습니다 —
레이아웃 라이브러리를 싣지 않으므로 매번 같은 그림이고 커밋해서 diff할 수 있습니다. - 페이지의 문구가 한국어입니다. 시트에서 온 이름과 설명은 그대로이고, 타입 이름과 측
표기(c·s·cs)는 recipe의 어휘라 번역하지 않습니다. - 목록의 기본 정렬은 이름 오름차순입니다 — 테이블·컬럼·enum·상수 세트 모두, 대소문자를
가리지 않고. 서수 정렬은 대문자를 모두 소문자 앞에 두므로 찾는 이름이 예상한 자리에 없습니다. - 참조 그래프를 탐색기로. 끌어서 이동하고 휠로 확대하며, 테이블을 누르면 그 테이블의
이웃만 그려집니다 — 왼쪽이 가리키는 테이블, 오른쪽이 가리켜지는 테이블이고, 이웃을 다시
눌러 걸어갈 수 있습니다. 그림은 변환된 그룹 안에 있으므로 이동이 요소 하나의 속성 하나이고,
호버 강조는 간선 전체를 담은 그룹의 불투명도 하나를 바꿉니다. 아래에 연결 정도 표를
두어 어디서부터 볼지 정하게 했습니다. - 스크롤 영역은 페이지당 하나입니다. 표와 페이지가 함께 ...
- 테이블당 페이지 하나입니다. 전부 한 페이지였고, 최대 테이블이 10만 행인 워크북에서 그