diff --git a/resources/master_data/ref/_분석_알약_상세줄.md b/resources/master_data/ref/_분석_알약_상세줄.md new file mode 100644 index 00000000..3cbf3f50 --- /dev/null +++ b/resources/master_data/ref/_분석_알약_상세줄.md @@ -0,0 +1,73 @@ +# 분석 — 단가산출 상세 줄을 「알약 + 사칙연산」으로 + +코드 하나도 안 고침. 읽고 짚어 보기만 함. + +바라는 모습 — 줄이 표 칸 안에 묶여 있지 않고 「[석공 노임] × [표 QF000421] × (1 + [증가율]) = 52,437.06」처럼 +알약과 연산기호로 죽 이어짐. 알약을 누르면 지금처럼 모달로 그 자료를 보임(모달 자체는 없애지 않고, 모달을 여는 자리만 표 밖 줄로 뺌). + +## 1. 지금 줄이 무엇으로 그려지는지 + +세 컨테이너가 관계됨 — 이름은 같지만 그리는 법이 서로 다름. + +| 컨테이너 | 파일 | 그리는 법 | +|---|---|---| +| 단가산출 상세(호표 표) | `M01_MasterData_UI_LogicLab_Detail.ts`(`hoBox`·`groupTable`·`lineRow`) | 비목별 표 — 칸 다섯(이름·단위·수량·단가·금액). 「수량」 칸은 식 글자가 아니라 `item.수량` 을 판 태그(「표」·「입력」…)+포맷된 값 하나로만 보임. **줄을 누르면 모달**(`openMaterialModal`)이 뜸 | +| 텍스트 수식 | `M01_MasterData_UI_LogicLab_Formula.ts` | 표가 아니라 두 칸짜리 줄 목록 — 왼쪽 = 이름 식(`line.이름글`) · 오른쪽 = `line.이름 : line.글`(값 식). 서버가 이미 **다 조립한 문장 하나**를 그대로 찍음. 줄을 눌러도 모달은 안 뜨고 밝기만 바뀜(`is-pin`) | +| 호표 줄 모달 | `M01_MasterData_UI_LogicLab_Modal.ts` | 상세 표 줄을 누르면 뜸 — 그 줄의 raw 식(`item.수량`, 별칭 안 씌운 원문)을 **클라이언트가 다시** 훑어(`relatedFinds` in `M01_MasterData_UI_Logic_Note.ts`) 찾기(...) 호출·요소 참조를 뽑아 알약 목록(`pillBar`)으로 늘어놓음. 알약을 누르면 표/단가 자료가 아래 펼쳐짐 | + +서버가 주는 값의 모양(`resources/master_data/scripts/master_text.py`, `POST /text`) — + +- 줄 하나 = `{이름, 글, 이름글, 짝, 금액, 까닭?}`. **`글`·`이름글` 둘 다 완성된 문자열 하나**(`_draw`/`named` 가 식 나무를 재귀로 내려가며 문자열을 이어 붙임) — 토큰(알약이 될 조각, 연산기호)으로 나뉘어 있지 않음. +- `이름글` 이 이미 요청과 거의 같은 문장을 만듦 — 실제 예(13-4-1 석공비, PLAN 에서 검증된 값) `석공노임 * 메쌓기인력.석공 * (1 + 증가율 %) = 석공비` / `글` 은 `268,908 * 0.15 * (1 + 0 %) = 40,336.2`. 요청한 보기(`[석공 노임] × [표 QF000421] × (1 + [증가율]) = 52,437.06`)와 짜임이 같음 — **`석공노임`이 알약(단가) · `메쌓기인력`이 알약(표, `.석공`은 붙는 칸이름이라 그대로 글자) · `증가율`은 그냥 입력값(알약 아님)**. +- 알약 후보를 가려내는 자료는 이미 있음 — `master_copy.aliases(row, master)` 가 로직 한 줄마다 「찾기(...)·로직(...) 부르기 한 덩이 = 별칭 이름 하나」인 목록(밑이름·참조·값칸·결과단위 포함)을 만들고, `master_text.py` 는 이걸로 원문 식을 별칭 이름으로 갈아 끼운 뒤(`mc.mask`) 그 나무를 걷어 `이름글`을 만듦. **즉 "이 이름이 알약인지 아닌지, 알약이면 표인지 로직인지"는 서버가 이미 알고 있음 — 화면에 안 넘겨 줄 뿐.** + +## 2. 서버가 더 줘야 하는 것 + +**지금 텍스트 수식(`글`·`이름글`)만으로는 안 됨** — 둘 다 이미 문자열로 다 붙은 뒤라 알약 자리·글자 자리를 다시 가르기 어려움(정규식으로 이름을 되짚어 찾는 건 같은 이름이 여러 번 나오거나 다른 값과 이름이 겹칠 때 깨짐). + +모자란 건 "토큰 배열" — 서버가 `이름글`을 만들 때 쓰는 식 나무 순회(`master_text._draw`/`named`/`_bin`/`_side`)를 문자열 이어 붙이기 대신 **조각 목록**으로 뱉게 고쳐야 함. 조각 하나는 대략 — + +``` +{ 종류: "알약-표" | "알약-단가" | "알약-로직" | "글자", 보임: "석공노임", 참조?: "LB0031" } +{ 종류: "글자", 보임: "*" } … +``` + +- `종류` 는 이미 아는 정보로 매길 수 있음 — 나무 마디가 `ref`(요소 키, `LB`/`EQ`/`MT`/`MP`/`MO` 로 시작)면 단가 알약, `name` 인데 그 이름이 `aliases()` 별칭 목록에 있으면 그 별칭의 `종류`(찾기/로직)를 그대로 씀, 그 밖 `name`(입력·중간 값)과 숫자·문자 리터럴은 그냥 글자. +- 괄호·연산기호(`*`, `+`, `%`, 만약 골라진 가지 표시)는 지금 `_bin`/`_side` 가 이미 계산해 붙이는 자리 그대로 "글자" 조각으로 넣으면 됨 — **정밀도·괄호 규칙(`_PREC`·`_RIGHT_TIGHT`)은 그대로 재사용**, 새로 안 만들어도 됨. +- 값(`글` 쪽 알약 라벨에 보일 실제 값)도 같은 순회에서 `_value()`/`fmt()` 를 그대로 쓰면 됨. + +즉 **새 계산은 없음** — 이미 있는 나무 순회를 "문자열 이어 붙이기"에서 "조각 목록 쌓기"로 바꾸는 것 하나. 계산 함수(`master_formula.evaluate`/`run`)는 안 건드림. + +다른 길 — 화면(TS)이 raw 식(`item.수량`)을 직접 다시 파싱해서 토큰을 만드는 방법도 있음(모달이 지금 `relatedFinds` 로 하는 것과 비슷한 정규식 확장). 하지만 이러면 **연산자 우선순위·괄호 붙이는 규칙(`_PREC`/`_RIGHT_TIGHT`)을 TS 에도 따로 베껴야** 함 — 서버 쪽 규칙이 바뀌면 화면이 슬쩍 어긋날 위험이 있어, 굳이 계산기를 두 벌 만드는 셈. **서버가 조각을 주는 쪽이 더 안전함.** + +## 3. 어려운 자리 + +1. **식이 길거나 괄호가 겹칠 때** — 모달은 세로 공간이 넉넉해 문제없지만, 표 줄 안(또는 표를 대신하는 한 줄)에 다 넣으면 알약+글자가 한 줄에 여러 개 몰려 줄바꿈이 잦아짐. 알약 컴포넌트(`m01lab__pill-row`)는 이미 `flex-wrap: wrap` 이라 줄바꿈 자체는 됨 — 다만 표 `` 안에 가두면 그 칸만 세로로 길어져 다른 칸(이름·단위·금액)과 줄 높이가 안 맞음. +2. **만약() 처럼 갈래가 있는 식** — 지금 `named()`/`_draw()` 는 **걸린 가지 하나만** 적음(`만약(조건, 참, 거짓)` → 조건에 따라 참/거짓 중 한쪽만 글로 나감, 조건식 자체는 아예 안 보임). 알약 줄도 같은 식이면 "왜 이 가지가 골렸는지"는 안 보임 — 지금 방식을 그대로 따를지, 조건도 알약으로 보여줄지 결정 필요. +3. **로직을 부르는 줄** — 별칭 처리로 이미 "로직 알약" 하나로 뭉침(모달에 있는 `Pill_Logic` 그대로 씀). 그 알약 안에 그 로직 자체의 노무비·재료비·경비 몫이 또 있는데, 지금 모달은 "로직 · GF000119" 정도만 보여주고 그 속까지 안 풂 — 알약을 누르면 또 알약이 나오는 중첩을 받을지, 지금처럼 한 단으로 멈출지 결정 필요. +4. **덧줄(비율)** — 덧줄 식은 앞선 노무비·재료비·경비 **소계 자체**를 변수로 씀(`env.update(sums)`, 예: "노무비 × 5%"). 이 "노무비"라는 이름은 표·단가 알약이 아니라 "이 로직의 소계"를 가리키는 특수한 자리 — 지금 `named()` 는 이런 것도 그냥 보통 이름처럼 적어 알약인지 아닌지 가릴 표시가 따로 없음. 알약으로 할지, 그냥 숫자로 둘지 새로 정해야 함. +5. **한 줄에 알약이 여러 개일 때** — 모달은 알약 여러 개라도 펼침 자리(`stage`)가 하나뿐이라 안 겹침. 표 줄마다 이 자리를 따로 두면(㉯ 길) 여러 줄을 동시에 펼쳤을 때 화면이 한참 길어질 수 있음 — 페이지 전체에서 "한 번에 하나만 펼침"으로 조율할지, 줄마다 따로 열리게 둘지 결정 필요. +6. **390px 좁은 화면** — 지금 표는 좁으면 표 전체가 가로 스크롤(`m01-logic__scroll`)로 빠짐. 알약 줄을 표 안에 두면 가로 스크롤 속에 갇혀 오히려 더 안 보이게 될 수 있음. 표 밖(㉯ 길)으로 빼면 텍스트 수식 컨테이너처럼 세로로 자연스럽게 쌓여 좁은 화면에 더 맞음. +7. **표 안에서 줄바꿈** — 지금 "수량" 칸은 식이 아니라 태그+숫자 하나뿐이라 줄바꿈 문제가 아예 없음. 알약 줄을 그 칸에 넣는 순간 칸 폭이 줄마다 달라지고, 이름·단위·단가·금액 칸과 세로 줄이 안 맞게 됨 — 표 모양을 지키려면 칸을 나누는 방식 자체를 다시 짜야 함. + +## 4. 두 갈래 — 어느 게 쉽고 어느 게 어려운지 + +**㉮ 호표 표(칸 다섯)는 그대로 두고, 그 안 글자를 알약으로 바꿈** + +- 쉬움 — `entries()`/`groupTable()`/소계·합계·비목 나누기·자체 로직 접이(`ownEditor`/`fold`) 같은 지금 조립 얼개를 하나도 안 건드림. 표의 스크린리더 시맨틱(``)도 그대로. 위험이 작음. +- 어려움 — "수량" 칸 하나에 알약+연산기호+"= 금액"까지 다 넣으려면 사실상 그 칸만 문장 하나짜리 자유 칸이 되어 표 모양이 깨짐(다른 네 칸과 안 어울림). 좁은 화면에서 가로 스크롤에 갇힘(위 6번). 결국 "표를 거의 접고 그 칸만 커지는" 모습이라 ㉮ 라는 이름과 달리 실제로는 표를 많이 허무는 셈이 됨. + +**㉯ 호표 표를 알약 줄 목록으로 새로 짜기(텍스트 수식 컨테이너와 같은 얼개)** + +- 쉬움 — 선례가 이미 있음(`M01_MasterData_UI_LogicLab_Formula.ts` 가 "줄마다 전체 폭 한 줄" 얼개를 씀). 알약 폭 제약이 없어 줄바꿈이 자연스럽고, 좁은 화면에 더 잘 맞음(6·7번 안 걸림). "이름 : 알약 × 알약 × (1 + 알약) = 금액" 한 줄 + 그 아래 소계 — 요청한 보기와 그대로 맞아떨어짐. +- 어려움 — 지금 표 전용 조립(비목별 소계 줄·"그 밖"은 있을 때만·자체 로직 접이)을 목록 얼개로 다시 짜야 함. 표 시맨틱을 포기하므로 접근성(스크린리더가 "표"로 안 읽음)을 다른 방식(예: 줄마다 `role`)으로 보완해야 함. 단위·규격처럼 지금 표 칸에 있던 부가정보를 알약 라벨이나 옆 글자로 옮겨야 함. + +## 5. 시험 계산·금액이 그대로인지 + +- 값(`금액`·`계`) 은 서버 `master_text.lines()`(정확히는 `master_formula.run`)가 이미 계산해 준 것을 화면이 찍기만 함 — **알약화는 "보여주는 방식"만 바꾸는 것**이라, 계산 코드(`master_formula.evaluate`/`run`)를 안 건드리면 값 자체는 안 바뀜. +- 단, 2 장에서 말한 "문자열 이어 붙이기 → 조각 목록"으로 고치는 작업은 `master_text.py` 의 `_draw`/`named`/`_bin`/`_side` 를 직접 고치는 일이라, 실수로 계산 쪽(`mf.evaluate` 호출 자리)까지 건드리면 값이 흔들릴 위험은 있음. 이미 이 파일을 겨눈 시험(`resources/tester/test_m01_text.py`, 산림 13-4-1·12-4·12-17-1 세 견본)이 있으니, 고친 뒤 그 시험이 **지금과 같은 `글`·`이름글`·`금액` 값**을 주는지부터 대조하면 됨(토큰을 다시 이어 붙였을 때 원래 문자열과 같아지는지 보는 거울 시험을 하나 더 두면 더 확실). +- 퍼센트 표기(`나눗셈 100` → `N %`)는 `_bin` 안에 있는 특수 규칙 — 토큰화해도 "%" 는 알약이 아니라 글자로 남기면 지금 보기와 같아짐. 소수 자릿수·천 단위 쉼표(`fmt()`)도 그대로 재사용되므로 값 표기 자체는 안 바뀜. + +## 결론 + +지금 「텍스트 수식」 두 칸은 문장으로는 이미 요청과 거의 같은 모양을 냄 — 모자란 건 계산이 아니라 **그 문장을 알약 조각으로 쪼개 주는 것** 하나(서버 `master_text.py` 의 문자열 조립을 조각 목록 조립으로 바꿈). 알약이 아는 자료(표/단가/로직 구분)는 `master_copy.aliases()` 가 이미 갖고 있어 새로 만들 건 없음. 표(㉮)냐 목록(㉯)이냐는 좁은 화면·줄바꿈에서 갈림 — ㉯ 쪽이 선례(텍스트 수식 컨테이너)가 있어 다시 짤 게 적고 좁은 화면에도 더 맞지만, 표 시맨틱·소계 조립을 새로 짜야 하는 몫이 ㉯ 쪽에 있음.