@simplysm/sd-claude 14.0.82 → 14.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/claude/references/sd-requirement-source-handling.md +20 -20
  2. package/claude/references/sd-simplysm14/README.md +13 -13
  3. package/claude/references/sd-simplysm14/manuals/client-component.md +92 -92
  4. package/claude/references/sd-simplysm14/manuals/client-crud.md +11 -11
  5. package/claude/references/sd-simplysm14/manuals/client-demo.md +28 -28
  6. package/claude/references/sd-simplysm14/manuals/client-rules.md +1 -1
  7. package/claude/references/sd-simplysm14/manuals/client-setup.md +21 -21
  8. package/claude/references/sd-simplysm14/manuals/client-tab.md +3 -3
  9. package/claude/references/sd-simplysm14/manuals/logging.md +15 -15
  10. package/claude/references/sd-simplysm14/manuals/orm-union.md +6 -6
  11. package/claude/references/sd-simplysm14/manuals/orm.md +19 -19
  12. package/claude/references/sd-simplysm14/manuals/test.md +33 -33
  13. package/claude/rules/sd-base-rules.md +44 -43
  14. package/claude/rules/sd-design-rules.md +18 -18
  15. package/claude/skills/sd-commit/SKILL.md +10 -10
  16. package/claude/skills/sd-config/SKILL.md +2 -2
  17. package/claude/skills/sd-demo/SKILL.md +45 -45
  18. package/claude/skills/sd-dev/SKILL.md +15 -15
  19. package/claude/skills/sd-docs/SKILL.md +7 -7
  20. package/claude/skills/sd-docs/references/subagent-prompt.md +33 -33
  21. package/claude/skills/sd-impl/SKILL.md +60 -60
  22. package/claude/skills/sd-review/SKILL.md +9 -9
  23. package/claude/skills/sd-skill/SKILL.md +74 -74
  24. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +1 -1
  25. package/claude/skills/sd-spec/SKILL.md +355 -319
  26. package/claude/skills/sd-spec/references/example-spec.md +104 -104
  27. package/claude/skills/sd-unpack/SKILL.md +34 -34
  28. package/claude/skills/sd-use/SKILL.md +4 -4
  29. package/package.json +1 -1
  30. package/claude/references/sd-simplysm14/apis/angular/README.md +0 -37
  31. package/claude/references/sd-simplysm14/apis/angular/app-structure.md +0 -92
  32. package/claude/references/sd-simplysm14/apis/angular/buttons.md +0 -88
  33. package/claude/references/sd-simplysm14/apis/angular/crud.md +0 -100
  34. package/claude/references/sd-simplysm14/apis/angular/forms.md +0 -200
  35. package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +0 -231
  36. package/claude/references/sd-simplysm14/apis/angular/kanban.md +0 -80
  37. package/claude/references/sd-simplysm14/apis/angular/layout.md +0 -92
  38. package/claude/references/sd-simplysm14/apis/angular/modal.md +0 -115
  39. package/claude/references/sd-simplysm14/apis/angular/routing.md +0 -107
  40. package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +0 -35
  41. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -82
  42. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +0 -134
  43. package/claude/references/sd-simplysm14/apis/angular/sheet.md +0 -127
  44. package/claude/references/sd-simplysm14/apis/angular/toast.md +0 -97
  45. package/claude/references/sd-simplysm14/apis/angular/visual.md +0 -167
  46. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +0 -79
  47. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +0 -83
  48. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +0 -91
  49. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +0 -49
  50. package/claude/references/sd-simplysm14/apis/core-browser/README.md +0 -143
  51. package/claude/references/sd-simplysm14/apis/core-common/README.md +0 -58
  52. package/claude/references/sd-simplysm14/apis/core-common/extensions.md +0 -88
  53. package/claude/references/sd-simplysm14/apis/core-common/features.md +0 -51
  54. package/claude/references/sd-simplysm14/apis/core-common/types.md +0 -88
  55. package/claude/references/sd-simplysm14/apis/core-common/utils.md +0 -189
  56. package/claude/references/sd-simplysm14/apis/core-node/README.md +0 -12
  57. package/claude/references/sd-simplysm14/apis/core-node/consola.md +0 -59
  58. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +0 -44
  59. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +0 -42
  60. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +0 -53
  61. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +0 -24
  62. package/claude/references/sd-simplysm14/apis/core-node/worker.md +0 -65
  63. package/claude/references/sd-simplysm14/apis/excel/README.md +0 -193
  64. package/claude/references/sd-simplysm14/apis/lint/README.md +0 -94
  65. package/claude/references/sd-simplysm14/apis/orm-common/README.md +0 -58
  66. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +0 -77
  67. package/claude/references/sd-simplysm14/apis/orm-common/executable.md +0 -20
  68. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +0 -92
  69. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +0 -98
  70. package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +0 -128
  71. package/claude/references/sd-simplysm14/apis/orm-node/README.md +0 -69
  72. package/claude/references/sd-simplysm14/apis/sd-claude/README.md +0 -32
  73. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +0 -80
  74. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +0 -155
  75. package/claude/references/sd-simplysm14/apis/service-client/README.md +0 -131
  76. package/claude/references/sd-simplysm14/apis/service-common/README.md +0 -29
  77. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +0 -63
  78. package/claude/references/sd-simplysm14/apis/service-common/messages.md +0 -56
  79. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +0 -64
  80. package/claude/references/sd-simplysm14/apis/service-common/service-types.md +0 -43
  81. package/claude/references/sd-simplysm14/apis/service-server/README.md +0 -13
  82. package/claude/references/sd-simplysm14/apis/service-server/auth.md +0 -39
  83. package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +0 -71
  84. package/claude/references/sd-simplysm14/apis/service-server/define-service.md +0 -55
  85. package/claude/references/sd-simplysm14/apis/service-server/internals.md +0 -82
  86. package/claude/references/sd-simplysm14/apis/service-server/server.md +0 -57
  87. package/claude/references/sd-simplysm14/apis/storage/README.md +0 -71
@@ -1,8 +1,8 @@
1
- # Requirement Source 부정확성 처리
1
+ # 요구사항 원본(Requirement Source, 회의록·메일·문서 등 사용자 제공 원본 자료) 부정확성 처리
2
2
 
3
- ## STT 텍스트 보정
3
+ ## STT(음성→텍스트 변환) 텍스트 보정
4
4
 
5
- **명백한 오타만 보정**. 보정 시 `[원문]` 발췌로 원본도 보존.
5
+ 명백한 오타만 보정. 보정 시 `[원문]` 발췌로 원본도 보존.
6
6
 
7
7
  ```markdown
8
8
  > [2026-03-17 회의] "PDF에 빨간색으로 강조"
@@ -11,12 +11,12 @@
11
11
  ```
12
12
 
13
13
  판정:
14
- - 명백 (오타 1~2글자, 의미 자명): 보정.
15
- - 모호 (의미가 여러 갈래로 해석 가능): **사용자에게 즉시 확인**, 원문 그대로 발췌.
14
+ - 명백 (오타 1~2글자, 의미 자명): 보정함.
15
+ - 모호 (의미가 여러 갈래로 해석 가능): 사용자에게 즉시 확인, 원문 그대로 발췌.
16
16
 
17
17
  ## 화자 추정
18
18
 
19
- 회의록 화자가 부정확/누락된 경우 컨텍스트로 추정. `[추정: ...]` 표기.
19
+ 회의록의 화자 표기가 부정확하거나 누락된 경우, 앞뒤 대화 맥락으로 추정. `[추정: ...]` 표기.
20
20
 
21
21
  ```markdown
22
22
  > [2026-03-17 회의, 추정: B 차장] "주문 단위로 가는 게 맞다"
@@ -24,41 +24,41 @@
24
24
  ```
25
25
 
26
26
  판정:
27
- - 컨텍스트로 명확: 추정.
28
- - 모호: **사용자에게 즉시 확인**, 화자 미상으로 발췌.
27
+ - 앞뒤 대화 맥락으로 화자가 명확: 추정 표기.
28
+ - 모호: 사용자에게 즉시 확인, 화자 미상으로 발췌.
29
29
 
30
30
  ## 모호 발화 처리
31
31
 
32
- 지시대명사·생략 표현·비격식 발언:
32
+ 지시대명사·생략 표현·비격식 발언 예:
33
33
  - "그거 그렇게" / "이렇게 가는 걸로" / "지난번처럼" / "알아서".
34
34
 
35
35
  처리:
36
- - **자동 해석 금지** (이전 발언/맥락 추측해서 채워 넣지 말 것).
37
- - **사용자에게 즉시 확인** — "그거"가 무엇인지, "그렇게"가 어떤 방식인지.
36
+ - 자동 해석 금지 (이전 발언이나 맥락을 추측해서 채워 넣지 말 것).
37
+ - 사용자에게 즉시 확인 — "그거" 무엇을 가리키는지, "그렇게" 가 어떤 방식인지.
38
38
 
39
39
  ## 다중 화자 발언 섞임 (회의록)
40
40
 
41
41
  여러 사람이 같은 주제를 다른 입장에서 말한 경우:
42
- - 양쪽(또는 모든) 발언 모두 발췌 보존.
43
- - 사용자에게 어느 의견 채택할지 즉시 확인.
42
+ - 모든 화자의 발언을 발췌하여 보존.
43
+ - 사용자에게 어느 의견을 채택할지 즉시 확인.
44
44
 
45
- ## 비격식 메일 / paste
45
+ ## 비격식 메일 또는 붙여넣기 텍스트
46
46
 
47
47
  주어 생략, 맥락 누락:
48
- - 보충 가능한 부분(자명한 주어 등): 발췌 시 `[추정 보충: ...]` 표기로 원문에 덧붙이지 않고 명시.
48
+ - 보충 가능한 부분(자명한 주어 등): 발췌 시 `[추정 보충: ...]` 표기를 사용하여, 원문 자체는 수정하지 않고 보충분을 별도로 명시.
49
49
  - 모호한 부분: 사용자에게 즉시 확인.
50
50
 
51
51
  ## 도메인 용어 다의성
52
52
 
53
- Requirement Source 시스템 용어가 아니라 **현장 은어**. 같은 단어가 시스템상 여러 동작에 매핑될 수 있음.
53
+ 요구사항 원본에 등장하는 업무 용어는 시스템 용어가 아니라 현장 은어. 같은 단어가 시스템상 여러 동작에 매핑될 수 있음.
54
54
 
55
55
  - 예: "출고" → 창고간 재고이동 / 고객사 납품 / 차량 적재 / 그 외.
56
56
  - 예: "마감" → 일마감 / 월마감 / 정산마감 / 작업종료.
57
57
  - 예: "주문" → 고객 발주 / 내부 작업지시 / 견적 단계.
58
58
 
59
- **위험도 역설**: 일반적으로 들리는 업무 용어(출고/입고/재고/주문/마감/등록 등)일수록 더 의심. 낯선 용어는 자연스럽게 의문이 생기지만, 익숙한 용어는 모두가 안다고 착각함.
59
+ 위험도 역설: 일반적으로 들리는 업무 용어(출고·입고·재고·주문·마감·등록 등)일수록 더 의심해야 함. 낯선 용어는 자연스럽게 의문이 생기지만, 익숙한 용어는 모두가 같은 뜻으로 안다고 착각하기 쉬움.
60
60
 
61
61
  처리:
62
- - **자동 매핑 금지**.
63
- - **사용자에게 즉시 확인**"이 단어가 시스템상 어떤 동작을 가리키는지".
64
- - **후보 나열 금지**Claude 추측한 후보를 제시하면 사용자가 그 안에서만 고르게 가둠. 후보는 사용자가 답하게 둘 것.
62
+ - 자동 매핑 금지.
63
+ - 사용자에게 즉시 확인해당 단어가 시스템상 어떤 동작을 가리키는지 묻기.
64
+ - 후보 나열 금지에이전트가 추측한 후보를 먼저 제시하면, 사용자가 그 후보 안에서만 고르도록 가두는 효과 발생. 후보 없이 사용자가 직접 답하도록 둘 것.
@@ -1,31 +1,31 @@
1
1
  # @simplysm/* v14 행동 지침
2
2
 
3
- Claude 에이전트가 반드시 지켜야 할 행동 지침. (@simplysm/\* v14 포함시)
3
+ Claude 에이전트가 `@simplysm/*` v14 패키지를 사용·변경하는 작업에서 반드시 지켜야 할 행동 지침.
4
4
 
5
- ## 코드 위치 원칙
5
+ ## 코드 작성 위치 원칙
6
6
 
7
- 기본 위치는 **클라이언트**. 서버(`service-server`) 다음 두 경우에만 둠:
7
+ 업무 로직 코드의 기본 작성 위치는 **클라이언트 패키지**. 서버 패키지(`@simplysm/service-server` 기반)에는 다음 두 경우에만 코드를 둠:
8
8
 
9
- - **보안**: 클라이언트에 노출 불가한 자격증명/키, 권한 우회 위험, 외부에 직접 노출하면 안 되는 연산.
10
- - **클라이언트 미지원**: 브라우저/모바일 런타임에서 실행 불가한 기능(특정 네이티브 API, 서버 측 자원 접근 등).
9
+ - **보안 필요**: 클라이언트에 노출 불가한 자격증명·키, 권한 우회 위험이 있는 처리, 외부에 직접 노출하면 안 되는 연산.
10
+ - **클라이언트 실행 불가**: 브라우저·모바일 런타임에서 실행 불가능한 기능 (특정 네이티브 API, 서버 측 자원 접근 등).
11
11
 
12
- ORM 호출, 파일 변환, 비즈니스 로직 등은 위 두 사유에 해당하지 않는 한 클라이언트 코드에 직접 둠. "서버에 두는 게 관행"이라는 이유로 service 이관하지 않음.
12
+ ORM 호출, 파일 변환, 비즈니스 로직 등은 위 두 경우에 해당하지 않는 한 클라이언트 코드에 직접 둠. "서버에 두는 게 관행"이라는 이유로 서버 패키지로 이관 금지.
13
13
 
14
- ## CLAUDE.md 명령어 표기
14
+ ## 프로젝트 `CLAUDE.md` 명령어 표기 규칙
15
15
 
16
- `CLAUDE.md` 작성 시, 검증 명령은 다음 역할로 표기함.
16
+ `@simplysm/*` v14 기반 프로젝트의 `CLAUDE.md` 작성 시, 검증 명령 표기 규칙:
17
17
 
18
- - **기본 검증 (평소 사용)**: `pnpm check --fix` — typecheck + lint 일괄, 자동 수정 포함.
19
- - **보조**: `pnpm typecheck`, `pnpm lint` — `pnpm check` 에서 문제 났을 때 각각 따로 보기 위함. 단독 사용은 회피.
20
- - **`-t` 타겟 표기**: `sd.config.ts` 의 `packages` 키(`@simplysm/` 접두사 **제외** 한 짧은 이름. 예: `excel`, `core-node`, `sd-cli`) 임을 본문에 명시. 풀네임 사용을 막기 위해 예시도 짧은 이름으로 통일.
18
+ - **기본 검증 (평소 사용)**: `pnpm check --fix` — typecheck lint 일괄 수행, 자동 수정 포함.
19
+ - **보조 명령**: `pnpm typecheck`, `pnpm lint` — `pnpm check` 에서 문제가 났을 때 각각 따로 확인하는 용도. 단독 사용 회피.
20
+ - **`-t` 타겟 인자 표기**: `-t` 인자 값은 `sd.config.ts` 의 `packages` 키 (`@simplysm/` 접두사를 **제외** 한 짧은 이름. 예: `excel`, `core-node`, `sd-cli`) 임을 본문에 명시. 풀네임 사용을 막기 위해 예시도 짧은 이름으로 통일.
21
21
 
22
22
  ## 개발 매뉴얼
23
23
 
24
- 트리거 조건이 처음 충족될 해당 자료를 Read.
24
+ 아래 표의 트리거 조건이 현재 작업에서 처음 충족되는 시점에 해당 매뉴얼 파일을 Read 도구로 읽기.
25
25
 
26
26
  | 트리거 | 매뉴얼 |
27
27
  | ------------------------------------------------------- | ------------------------------------------------------ |
28
- | 클라이언트 코드(앱·`@simplysm/angular`) 작성 항상 | [client-rules.md](./manuals/client-rules.md) |
28
+ | 클라이언트 코드 (앱 패키지·`@simplysm/angular`) 작성·수정하는 모든 작업 | [client-rules.md](./manuals/client-rules.md) |
29
29
  | 화면 컴포넌트(`<domain>.<역할>.ts`) 작성/수정 | [client-component.md](./manuals/client-component.md) |
30
30
  | `sd-crud-list` / `sd-crud-detail` 채택한 목록·단건 화면 | [client-crud.md](./manuals/client-crud.md) |
31
31
  | 클라이언트 데모 컴포넌트 작성 | [client-demo.md](./manuals/client-demo.md) |
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## 파일명·역할·위치
4
4
 
5
- 화면 파일은 `<domain>.<역할>.ts` 형식, 역할 접미사로 책임을 표시함.
5
+ 화면 파일명은 `<domain>.<역할>.ts` 형식. 역할 접미사로 책임을 표시.
6
6
 
7
7
  | 파일명 형식 | 역할 |
8
8
  | ---------------------------- | ------------------------------------------------------------------------- |
9
- | `<domain>.view.ts` | list/detail 깔끔히 나뉘지 않는 화면. (예시: list/detail orchestrator) |
9
+ | `<domain>.view.ts` | list/detail 합성 화면. list/detail 자식을 두고 상호 트리거를 중계. |
10
10
  | `<domain>.list.ts` | 목록. `sd-crud-list` 사용. |
11
11
  | `<domain>.detail.ts` | 단건 보기/편집. `sd-crud-detail` 사용. |
12
12
  | `<domain>.modal.ts` | 모달 전용 화면. |
@@ -15,11 +15,11 @@
15
15
  | `<domain>.ts` | 컨트롤(접미사 없음). 여러 화면에서 재사용되는 단위. |
16
16
 
17
17
  - 모든 파일명은 dash-case.
18
- - 라이브러리(`@simplysm/angular`) `sd-` prefix 붙음 (`sd-button.ts`, `sd-crud-list.ts`).
18
+ - 라이브러리(`@simplysm/angular`) 의 파일은 `sd-` prefix 적용 (`sd-button.ts`, `sd-crud-list.ts`).
19
19
 
20
20
  **위치**: 도메인이 있는 파일은 도메인 폴더 안에 둠. 도메인이 없는(범용) 파일은 `src/<역할>s/` 하위에 둠. 예: `src/controls/`, `src/modals/`.
21
21
 
22
- **변형 파일**: 한 도메인 폴더 안에 같은 역할 파일이 2개 이상이면 `<domain>-<갈래>.<역할>.ts` 형식으로 prefix 를 붙여 갈래를 둠. 예 (`outbound-instruction/` 폴더):
22
+ **변형 파일**: 한 도메인 폴더 안에 같은 역할 파일이 2개 이상이면 `<domain>-<갈래>.<역할>.ts` 형식으로 갈래를 표시. 예 (`outbound-instruction/` 폴더):
23
23
 
24
24
  - `outbound-instruction.list.ts` (헤더 목록).
25
25
  - `outbound-instruction-item.list.ts` (품목 목록).
@@ -43,25 +43,25 @@ Angular 기본과 다른 부분만 명시:
43
43
  ```
44
44
 
45
45
  - **`changeDetection: OnPush`** — 항상.
46
- - **`encapsulation: ViewEncapsulation.None`** — 항상. 글로벌 SCSS 와 일관된 스타일을 쓰기 위해.
46
+ - **`encapsulation: ViewEncapsulation.None`** — 항상. 글로벌 SCSS 와 일관된 스타일을 적용하기 위함.
47
47
  - **`standalone: true`** — 항상. NgModule 신규 도입 금지.
48
- - **`selector` prefix** — 앱 컴포넌트는 `app-`, 라이브러리(`@simplysm/angular`) `sd-`.
48
+ - **`selector` prefix** — 앱 컴포넌트는 `app-`, 라이브러리(`@simplysm/angular`) 컴포넌트는 `sd-`.
49
49
  - **`template`** 은 인라인 (`*.html` 파일 분리 없음).
50
50
 
51
- **`styles`** (선택) — 다음 두 가지만 simplysm 약속:
51
+ **`styles`** (선택 사용) — 다음 두 가지를 simplysm 약속으로 따름:
52
52
 
53
- - 첫 줄에 `/* language=SCSS */` 주석을 IDE 가 SCSS 로 인식하게 함.
54
- - 내부 전용 클래스는 `_` prefix (예: `._content`, `._button`).
53
+ - 첫 줄에 `/* language=SCSS */` 주석 배치 (IDE 가 SCSS 로 인식하게 함).
54
+ - 내부 전용 클래스명은 `_` prefix (예: `._content`, `._button`).
55
55
 
56
56
  ## 화면 합성 패턴
57
57
 
58
58
  화면은 list / detail / view 단위로 책임을 분리해 합성함.
59
59
 
60
- - **`*.list.ts`** — 자기 검색·페이지·정렬·재조회를 자체 책임. 외부에 `selectMode` 같은 입력을 받아 부모가 선택 동작을 제어.
61
- - **`*.detail.ts`** — 식별자(`input.required`)를 받아 자체 로드/저장. 변경·삭제 후 `submitted` output 으로 부모에게 알림.
62
- - **`*.view.ts`** — list/detail 합성 + 자식 간 트리거 중계. 데이터 페치는 view 하지 않음.
60
+ - **`*.list.ts`** — 자체 검색·페이지·정렬·재조회를 책임. `selectMode` 같은 입력을 받아 부모가 선택 동작을 제어할 수 있게 노출.
61
+ - **`*.detail.ts`** — 식별자(`input.required`) 를 받아 자체 로드·저장. 변경·삭제 후 `submitted` output 으로 부모에게 알림.
62
+ - **`*.view.ts`** — list/detail 합성 + 자식 간 트리거 중계. 데이터 페치는 view 에서 수행 금지.
63
63
 
64
- 화면이 list 또는 detail 하나로 끝나면 view 를 만들지 않고 list/detail 자체가 라우팅 진입 단위가 됨.
64
+ 화면이 list 또는 detail 하나로 끝나면 view 를 만들지 않음. 이 경우 list/detail 자체가 라우팅 진입 단위.
65
65
 
66
66
  ### list + detail 합성
67
67
 
@@ -89,9 +89,9 @@ view 의 합성 패턴 (예: `outbound-instruction.view.ts`):
89
89
 
90
90
  핵심 약속:
91
91
 
92
- - view 는 list 컴포넌트를 템플릿 변수(`#headerSheet`)로 잡아 `selectedKeys()` 를 읽고 `doRefresh()` 를 호출함.
93
- - detail 의 단건 변경·삭제는 list 가 표시하는 같은 데이터에 반영돼야 하므로, detail 의 `submitted` → list 의 `doRefresh()` 호출로 동기화함.
94
- - view 는 `sd-base-container` 를 루트로 두고, 내부 컨텐츠는 `#contentTpl` 슬롯에 둠.
92
+ - view 는 list 컴포넌트를 템플릿 변수(`#headerSheet`) 로 잡아 `selectedKeys()` 를 읽고 `doRefresh()` 를 호출.
93
+ - detail 의 단건 변경·삭제는 list 가 표시하는 동일 데이터에 반영해야 하므로, detail 의 `submitted` → list 의 `doRefresh()` 호출로 동기화.
94
+ - view 는 `sd-base-container` 를 루트로 두고, 내부 콘텐츠는 `#contentTpl` 슬롯에 배치.
95
95
 
96
96
  ### list + list 합성 (마스터-라인)
97
97
 
@@ -120,22 +120,22 @@ view 의 합성 패턴 (예: `outbound-instruction.view.ts`):
120
120
 
121
121
  핵심 약속:
122
122
 
123
- - 우 list 는 좌의 선택 키를 `input` 으로 받아 자동 재조회. (외부 input → filter 머지 패턴은 §"외부 input 을 filter 에 반영" 참조.)
124
- - 우 list 의 저장·삭제 후 좌 헤더 목록까지 갱신해야 하면 우 list 가 `submitted` output 을 emit, view 가 받아 `#headerSheet.doRefresh()` 호출.
125
- - 우 list 안에 추가 분기(탭 등) [client-tab.md](./client-tab.md) 매뉴얼 채택.
123
+ - 우 list 는 list 의 선택 키를 `input` 으로 받아 자동 재조회. 외부 input → filter 머지 패턴은 아래 "외부 input 을 filter 에 반영" 섹션 참조.
124
+ - 우 list 의 저장·삭제 후 좌 헤더 목록까지 갱신해야 하면, 우 list 가 `submitted` output 을 emit 하고, view 가 받아 `#headerSheet.doRefresh()` 호출.
125
+ - 우 list 안에 추가 분기(탭 등) 가 필요하면 [client-tab.md](./client-tab.md) 매뉴얼 따름.
126
126
 
127
127
  ## 화면 컴포넌트의 표준 시그널
128
128
 
129
- 화면 컴포넌트(view/list/detail/modal) 가 공통으로 쓰는 시그널 4종. **필요한 것만 채택**하되, 채택할 때는 아래 약속된 이름·의미·전파를 그대로 따름.
129
+ 화면 컴포넌트(view/list/detail/modal) 가 공통으로 사용하는 시그널 4종. **필요한 것만 채택**하되, 채택 아래 약속된 이름·의미·전파를 그대로 따름.
130
130
 
131
131
  | 이름 | 종류 | 의미 |
132
132
  | ------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
133
- | `ready` | `signal(false)` | 컴포넌트가 데이터 로드를 시작해도 되는 시점. 부모/컨테이너가 true 로 만들면 자식이 effect 발화. |
134
- | `initialized` | `signal(false)` | 첫 데이터 로드까지 끝났는지. 자식이 자기 로드 끝낸 set true. |
135
- | `busyCount` | `signal(0)` | 진행 중인 비동기 작업 수. 시작 시 `+1`, 끝나면 `-1`. > 0 이면 화면이 busy 표시. |
136
- | `viewType` | `injectViewTypeSignal()` | 화면이 page / control / modal 어느 컨텍스트에서 동작 중인지. 라우팅 진입이면 `'page'`, view 자식이면 `'control'`, 모달이면 `'modal'`. |
133
+ | `ready` | `signal(false)` | 컴포넌트가 데이터 로드를 시작해도 되는 시점. 부모·컨테이너가 true 로 set 하면 자식의 effect 발화. |
134
+ | `initialized` | `signal(false)` | 첫 데이터 로드 완료 여부. 자식이 자기 로드 종료 true 로 set. |
135
+ | `busyCount` | `signal(0)` | 진행 중인 비동기 작업 수. 시작 시 `+1`, 종료 `-1`. 값이 0 보다 크면 화면이 busy 표시. |
136
+ | `viewType` | `injectViewTypeSignal()` | 화면이 page / control / modal 어느 컨텍스트에서 동작 중인지. 라우팅 진입이면 `'page'`, view 자식이면 `'control'`, 모달이면 `'modal'`. |
137
137
 
138
- **전파**: 부모가 자식에게 위 시그널들을 그대로 흘려보냄. `sd-base-container` / `sd-crud-list` / `sd-crud-detail` 이들을 입력으로 받는 표준.
138
+ **전파**: 부모가 자식에게 위 시그널들을 그대로 전달. `sd-base-container` / `sd-crud-list` / `sd-crud-detail` 시그널들을 입력으로 받는 표준 컴포넌트.
139
139
 
140
140
  **`busyCount` 사용 패턴**:
141
141
 
@@ -149,7 +149,7 @@ this.busyCount.update((v) => v - 1);
149
149
 
150
150
  ## 권한 (perms)
151
151
 
152
- 화면 컴포넌트는 권한을 `injectPermsSignal(<paths>, <actions>)` 로 받음.
152
+ 화면 컴포넌트는 권한 정보를 `injectPermsSignal(<paths>, <actions>)` 로 받음.
153
153
 
154
154
  ```ts
155
155
  perms = injectPermsSignal(
@@ -159,13 +159,13 @@ perms = injectPermsSignal(
159
159
  ```
160
160
 
161
161
  - 첫 인자: **권한 path 목록** (도메인 트리 좌표).
162
- - 둘째 인자: **확인할 action 목록**. `perms()` 사용자가 가진 action 들의 string 배열.
162
+ - 둘째 인자: **확인할 action 목록**. `perms()` 반환값은 사용자가 보유한 action string 배열.
163
163
 
164
164
  **사용 약속**:
165
165
 
166
- - 단순한 권한 체크는 `this.perms().includes("use")` 를 템플릿·코드에 인라인으로 씀. 별도 computed 로 묶지 않음.
167
- - `restricted` 입력은 `[restricted]="!perms().includes('use')"` 형태로 인라인 전달. (별도 `canUse` / `restricted` computed 만들지 않음.)
168
- - 권한 체크 뒤에 추가 조건(데이터 상태 등)이 결합되어 **같은 결합이 2회 이상 참조될 때만** computed 로 묶음.
166
+ - 단순 권한 체크는 `this.perms().includes("use")` 를 템플릿·코드에 인라인으로 작성. 별도 computed 로 묶지 않음.
167
+ - `restricted` 입력은 `[restricted]="!perms().includes('use')"` 형태로 인라인 전달. 별도 `canUse` / `restricted` computed 생성 금지.
168
+ - 권한 체크 뒤에 추가 조건(데이터 상태 등) 이 결합되어 **같은 결합이 2회 이상 참조되는 경우에만** computed 로 묶음.
169
169
 
170
170
  ```ts
171
171
  canEdit = computed(() => this.perms().includes("edit") && this.data().state === "작성");
@@ -185,7 +185,7 @@ effect(() => {
185
185
 
186
186
  ## 에러·토스트
187
187
 
188
- 비동기 작업은 `_sdToast.try(async () => { ... })` 로 감쌈. 안에서 throw 된 에러는 토스트로 표시되고 외부로 전파되지 않음.
188
+ 비동기 작업은 `_sdToast.try(async () => { ... })` 로 감쌈. 콜백 내에서 throw 된 에러는 토스트로 표시되며 외부로 전파되지 않음.
189
189
 
190
190
  ```ts
191
191
  private readonly _sdToast = inject(SdToastProvider);
@@ -206,7 +206,7 @@ this.busyCount.update((v) => v - 1);
206
206
  - `_sdToast.info("...")`.
207
207
  - `_sdToast.danger("...")`.
208
208
 
209
- **중복 작업 가드**: 진행 중인 작업이 있으면 새 작업은 건너뜀.
209
+ **중복 작업 가드**: 진행 중인 작업이 있으면 새 작업은 건너뛰고 즉시 반환.
210
210
 
211
211
  ```ts
212
212
  if (this.busyCount() > 0) return;
@@ -214,7 +214,7 @@ if (this.busyCount() > 0) return;
214
214
 
215
215
  ## DI 명명
216
216
 
217
- `inject()` 한 의존은 외부 노출 멤버(시그널·output·공개 메서드 등)와 구분하기 위해 `_` prefix 를 붙임.
217
+ `inject()` 한 의존은 외부 노출 멤버(시그널·output·공개 메서드 등) 와 구분하기 위해 `_` prefix 적용.
218
218
 
219
219
  ```ts
220
220
  private readonly _sdToast = inject(SdToastProvider);
@@ -223,8 +223,8 @@ private readonly _appOrm = inject(AppOrmProvider);
223
223
  private readonly _router = inject(Router);
224
224
  ```
225
225
 
226
- - 시그널·input·output·공개 메서드는 prefix 없이.
227
- - 항상 `private readonly`.
226
+ - 시그널·input·output·공개 메서드는 prefix 없음.
227
+ - DI 멤버는 항상 `private readonly`.
228
228
 
229
229
  ## 모달 호출
230
230
 
@@ -245,16 +245,16 @@ if (!result) return;
245
245
  // result 처리
246
246
  ```
247
247
 
248
- - **`type`** — `SdModal` 을 구현(상속)한 컴포넌트 클래스.
248
+ - **`type`** — `SdModal` 을 구현(상속) 한 컴포넌트 클래스.
249
249
  - **`title`** — 모달 헤더 제목.
250
250
  - **`inputs`** — 모달 컴포넌트가 받을 input 시그널 값. 없으면 `{}`.
251
- - **반환값** — 모달 컴포넌트가 close 시 emit 한 페이로드. 사용자가 닫기(X)/취소로 닫으면 `undefined`.
251
+ - **반환값** — 모달 컴포넌트가 close 시 emit 한 페이로드. 사용자가 닫기(X)·취소로 닫으면 `undefined`.
252
252
 
253
253
  ## `mark` 헬퍼
254
254
 
255
- `@simplysm/angular` 의 `mark(signal)` 은 시그널 값은 그대로 두고 **변경 알림만** 발행함. effect 가 의존하는 시그널을 강제로 재발화시키거나, 객체 시그널 내부 필드 변경을 알릴 때 씀.
255
+ `@simplysm/angular` 의 `mark(signal)` 은 시그널 값은 그대로 두고 **변경 알림만** 발행. effect 가 의존하는 시그널을 강제 재발화시키거나, 객체 시그널 내부 필드 변경을 알릴 때 사용.
256
256
 
257
- **1. 외부 트리거로 effect 다시 돌리기** — 값은 같지만 effect 를 다시 발화시켜야 할 때.
257
+ **1. 외부 트리거로 effect 재발화** — 값은 동일하지만 effect 를 다시 발화시켜야 할 때.
258
258
 
259
259
  ```ts
260
260
  doRefresh(): void {
@@ -262,7 +262,7 @@ doRefresh(): void {
262
262
  }
263
263
  ```
264
264
 
265
- **2. 객체/배열 시그널 내부 변경 알리기** — 시그널이 들고 있는 객체의 _필드만_ 바뀌면 시그널은 변경 알림을 보내지 않음. 양방향 바인딩 자식의 변경 이벤트에 묶어 호출.
265
+ **2. 객체·배열 시그널 내부 변경 알림** — 시그널이 들고 있는 객체의 _필드만_ 변경된 경우 시그널 자체는 변경 알림을 보내지 않음. 양방향 바인딩 자식의 변경 이벤트에 묶어 호출.
266
266
 
267
267
  ```ts
268
268
  filter = signal<IFilter>({ name: "", state: "" });
@@ -279,7 +279,7 @@ mark(this.data);
279
279
 
280
280
  ## list 데이터 흐름
281
281
 
282
- list 컴포넌트는 자체 검색·페이지·정렬·재조회를 책임짐.
282
+ list 컴포넌트는 자체 검색·페이지·정렬·재조회를 책임.
283
283
 
284
284
  ### 시그널 구성
285
285
 
@@ -296,7 +296,7 @@ lastFilter = signal<IFilter>({ ... }); // 마지막 조회 시점 — effec
296
296
  trackByFn = (item: IItem) => item.id;
297
297
  ```
298
298
 
299
- **`filter` vs `lastFilter` 분리**: 폼을 만지는 동안 매번 재조회되지 않게 하기 위해. 사용자가 조회 버튼을 눌러야 `lastFilter` 가 갱신되고 effect 가 발화함.
299
+ **`filter` vs `lastFilter` 분리**: 입력 도중 매번 재조회되지 않게 하기 위함. 사용자가 조회 버튼을 눌러야 `lastFilter` 가 갱신되고 effect 가 발화.
300
300
 
301
301
  ### 자동 재조회 effect
302
302
 
@@ -325,7 +325,7 @@ constructor() {
325
325
  ```
326
326
 
327
327
  - `lastFilter` / `page` / `sortingDefs` 변경 시 자동 재조회.
328
- - 비동기 본체는 `untracked` 안에서 실행해 자기 자신이 의존성에 들어가지 않게 함.
328
+ - 비동기 본체는 `untracked` 안에서 실행해 자기 자신이 의존성에 등록되지 않게 함.
329
329
 
330
330
  ### 조회 트리거
331
331
 
@@ -335,9 +335,9 @@ onFilterSubmit(): void {
335
335
  this.lastFilter.set({ ...this.filter() }); // effect 발화
336
336
  }
337
337
 
338
- doRefresh(): void { // 부모(view)가 호출하는 외부 API
338
+ doRefresh(): void { // 부모(view) 가 호출하는 외부 API
339
339
  if (!this.perms().includes("use")) return;
340
- mark(this.lastFilter); // 값은 같지만 effect 재발화
340
+ mark(this.lastFilter); // 값은 동일하나 effect 재발화
341
341
  }
342
342
  ```
343
343
 
@@ -351,30 +351,30 @@ private async _refresh(): Promise<void> {
351
351
  }
352
352
  ```
353
353
 
354
- `_search` 는 ORM 쿼리 실행. 자세한 사용은 [orm.md](./orm.md) 참조.
354
+ `_search` 는 ORM 쿼리 실행. 자세한 사용법은 [orm.md](./orm.md) 참조.
355
355
 
356
356
  ### 페이지네이션
357
357
 
358
- 두 패턴 중 택일. 데이터 규모와 검색·정렬 책임에 따라 화면 작성자가 판단(명확한 컷오프 없음).
358
+ 두 패턴 중 택일. 데이터 규모와 검색·정렬 책임에 따라 화면 작성자가 판단 (명확한 컷오프 없음).
359
359
 
360
- **서버 페이징** — 한 페이지 분량만 매번 서버에서 가져옴. §시그널 구성/effect/`_refresh` 가정한 디폴트 패턴.
360
+ **서버 페이징** — 한 페이지 분량만 매번 서버에서 가져옴. 위의 "시그널 구성" / "자동 재조회 effect" / "`_refresh` 구조" 섹션이 가정하는 기본 패턴.
361
361
 
362
- - `pageLength` 시그널을 두고 `_refresh` 에서 서버 응답의 총 페이지 수로 set.
362
+ - `pageLength` 시그널을 두고, `_refresh` 에서 서버 응답의 총 페이지 수로 set.
363
363
  - `page` / `sortingDefs` / `lastFilter` 모두 effect 의존성. 변경 시 재조회.
364
- - `<sd-crud-list>` 에 `[totalPageCount]="pageLength()"` 전달. `[itemsPerPage]` 는 생략(=0).
364
+ - `<sd-crud-list>` 에 `[totalPageCount]="pageLength()"` 전달. `[itemsPerPage]` 는 생략 (= 0).
365
365
 
366
- **클라이언트 페이징** — 전체 데이터를 한 번에 로드, 시트가 자체 slice/sort.
366
+ **클라이언트 페이징** — 전체 데이터를 한 번에 로드. 시트가 자체적으로 slice·sort 수행.
367
367
 
368
- - `pageLength` 시그널·`sortingDefs` effect 의존성 불필요. (정렬은 시트 내부에서 처리.)
368
+ - `pageLength` 시그널과 `sortingDefs` effect 의존성 불필요 (정렬은 시트 내부에서 처리).
369
369
  - `_refresh` 는 전체 아이템을 한 번에 `items.set(all)`.
370
- - `<sd-crud-list>` 에 `[itemsPerPage]="<페이지당 행 수>"` 전달. `[totalPageCount]` 는 생략(=0).
371
- - `[(sorts)]` 는 화면이 정렬 상태를 들고 있어야 때만 묶음. 아니면 생략.
370
+ - `<sd-crud-list>` 에 `[itemsPerPage]="<페이지당 행 수>"` 전달. `[totalPageCount]` 는 생략 (= 0).
371
+ - `[(sorts)]` 는 화면이 정렬 상태를 보유해야 하는 경우에만 바인딩. 외에는 생략.
372
372
 
373
- **`[visiblePageCount]`** (기본 10) — 페이지네이터가 한 번에 표시하는 페이지 번호 개수. 두 패턴 모두 사용자가 명시 지시한 경우에만 명시.
373
+ **`[visiblePageCount]`** (기본 10) — 페이지네이터가 한 번에 표시하는 페이지 번호 개수. 두 패턴 모두 사용자가 명시 지시한 경우에만 설정.
374
374
 
375
375
  ### 외부 input 을 filter 에 반영
376
376
 
377
- list 가 다른 화면 안에 임베드되어 외부에서 filter 의 일부를 input 으로 받을 때, effect 로 input → filter → lastFilter 흐름을 만듦.
377
+ list 가 다른 화면 안에 임베드되어 외부에서 filter 의 일부를 input 으로 받는 경우, effect 로 input → filter → lastFilter 흐름을 구성.
378
378
 
379
379
  ```ts
380
380
  constructor() {
@@ -403,7 +403,7 @@ constructor() {
403
403
 
404
404
  ## detail 데이터 흐름
405
405
 
406
- detail 컴포넌트는 식별자를 받아 자체 로드/저장하고, 변경·삭제 후 `submitted` 로 부모에게 알림.
406
+ detail 컴포넌트는 식별자를 받아 자체 로드·저장을 수행하고, 변경·삭제 후 `submitted` 로 부모에게 알림.
407
407
 
408
408
  ### 시그널 구성
409
409
 
@@ -441,8 +441,8 @@ constructor() {
441
441
  }
442
442
  ```
443
443
 
444
- - 식별자(`dataId`) 변경이 effect 의존성. 부모가 다른 항목으로 전환하면 자동 재로드.
445
- - `setupCanDeactivate(fn)` (`@simplysm/angular`) 는 라우터 이탈 시점에 `fn()` 이 false 이탈을 막음.
444
+ - 식별자(`dataId`) effect 의존성. 부모가 다른 항목으로 전환하면 자동 재로드.
445
+ - `setupCanDeactivate(fn)` (`@simplysm/angular`) 는 라우터 이탈 시점에 `fn()` 이 false 반환하면 이탈을 차단.
446
446
 
447
447
  ### `_refresh` + 원본 스냅샷
448
448
 
@@ -502,9 +502,9 @@ async onSubmit(): Promise<void> {
502
502
 
503
503
  - 식별자는 `input.required<>` 로 받음.
504
504
  - 로드 후 `_orgData = obj.clone(loaded)` 로 원본 보관.
505
- - 페이지 이탈 가드는 `setupCanDeactivate` + `obj.equal` 비교.
506
- - 저장 끝나면 `_refresh()` 로 다시 로드 → `submitted.emit(true)`.
507
- - 삭제·취소 등 다른 액션도 끝에 `submitted.emit(true)` 를 emit 해 부모(list)가 새로고침할 수 있게 함.
505
+ - 페이지 이탈 가드는 `setupCanDeactivate` + `obj.equal` 비교로 처리.
506
+ - 저장 완료 `_refresh()` 로 다시 로드 → `submitted.emit(true)`.
507
+ - 삭제·취소 등 다른 액션도 끝에 `submitted.emit(true)` 를 emit 해 부모(list) 가 새로고침할 수 있게 함.
508
508
 
509
509
  ## 시트 컬럼·셀 표준
510
510
 
@@ -518,21 +518,21 @@ async onSubmit(): Promise<void> {
518
518
 
519
519
  **폭 약속**:
520
520
 
521
- - `[width]` 는 **명시하지 않음이 기본** 자동. px 지정은 사용자가 명시 지시한 경우에만.
521
+ - `[width]` 는 **미명시가 기본** (자동). px 지정은 사용자가 명시 지시한 경우에만 적용.
522
522
  - 영역 폭(`flex-min` 의 `style="width: ..."` 등) 도 동일.
523
523
 
524
524
  **셀 본문 약속**:
525
525
 
526
- - 시트 셀에는 패딩이 없으므로 본문 div 에 `p-xs-sm` 클래스를 붙이는 기본.
527
- - 정렬 클래스(`tx-right` / `tx-center` / `tx-left`)는 **사용자가 명시 지시한 경우에만** 사용. 기본은 미지정(브라우저 기본 left). "라벨은 가운데" 같은 자동 휴리스틱 적용 금지.
526
+ - 시트 셀에는 패딩이 없으므로 본문 div 에 `p-xs-sm` 클래스 적용이 기본.
527
+ - 정렬 클래스(`tx-right` / `tx-center` / `tx-left`) 는 **사용자가 명시 지시한 경우에만** 사용. 기본은 미지정 (브라우저 기본 left). "라벨은 가운데" 같은 자동 휴리스틱 적용 금지.
528
528
  - 단, **숫자 셀은 `tx-right` 기본 적용** (수량·금액·단가·합계 등 숫자값 컬럼).
529
- - `[cell]="items()"` 는 타입 추론용 더미 실제 행 데이터는 `<sd-sheet>` 의 `[items]` 가 들고 있음.
529
+ - `[cell]="items()"` 는 타입 추론용 더미. 실제 행 데이터는 `<sd-sheet>` 의 `[items]` 가 보유.
530
530
  - 셀 컨텍스트: `let-item="item"` / `let-index="index"` / `let-depth="depth"` / `let-edit="edit"`.
531
- - 셀 안 div 에 배경색 클래스(`bg-theme-*-lightest` 등)를 토글할 때는 빈 값 자리에 `&nbsp;`를 채워 div 가 셀 높이를 유지하게 함. (table cell 자식 div 가 콘텐츠 없을 높이 0 → bg 가 셀에 차지 않음.)
532
- - 좋은 예: `{{ item.surveyLocationCode ?? "&nbsp" }}`.
533
- - 나쁜 예: `{{ item.surveyLocationCode }}`, `{{ item.surveyLocationCode ?? " " }}`, `{{ item.surveyLocationCode ?? " " }}`.
531
+ - 셀 안 div 에 배경색 클래스(`bg-theme-*-lightest` 등) 를 토글할 때는 빈 값 자리에 `&nbsp;` 채워 div 가 셀 높이를 유지하게 (table cell 자식 div 가 콘텐츠 없을 높이 0 → bg 가 셀을 채우지 못함).
532
+ - 좋은 예: `{{ item.surveyLocationCode ?? "&nbsp;" }}`.
533
+ - 나쁜 예: `{{ item.surveyLocationCode }}`, `{{ item.surveyLocationCode ?? "" }}`, `{{ item.surveyLocationCode ?? " " }}`.
534
534
 
535
- **list 안에서**: `<sd-crud-list>` 의 직속 자식으로 `<sd-sheet-column>` 을 두면 내부 시트로 자동 투영됨.
535
+ **list 안에서**: `<sd-crud-list>` 의 직속 자식으로 `<sd-sheet-column>` 을 두면 내부 시트로 자동 투영.
536
536
 
537
537
  ```html
538
538
  <sd-crud-list ...>
@@ -546,7 +546,7 @@ async onSubmit(): Promise<void> {
546
546
 
547
547
  ### 요약 행
548
548
 
549
- 컬럼에 `<ng-template #summaryTpl>` 을 두면 시트의 헤더 영역 하단(`thead` 내부)에 요약 행이 렌더됨. 스크롤 시 헤더와 함께 상단 고정되며, 배경은 warning 계열로 자동 강조됨.
549
+ 컬럼에 `<ng-template #summaryTpl>` 을 두면 시트의 헤더 영역 하단(`thead` 내부) 에 요약 행이 렌더됨. 스크롤 시 헤더와 함께 상단 고정되며, 배경은 warning 계열로 자동 강조.
550
550
 
551
551
  ```html
552
552
  <sd-sheet-column [key]="'quantity'" [header]="'수량'">
@@ -559,9 +559,9 @@ async onSubmit(): Promise<void> {
559
559
  </sd-sheet-column>
560
560
  ```
561
561
 
562
- - 컬럼 중 하나라도 `#summaryTpl` 을 가지면 요약 행 전체가 활성화됨. 정의 없는 컬럼은 빈 셀.
563
- - 셀 본문 약속(`p-xs-sm`, 정렬 클래스 등)은 요약 셀에도 동일하게 적용.
564
- - 합계·평균 등 집계 값은 시트가 계산해주지 않음. 화면 컴포넌트에서 `computed` 로 직접 만들어 노출함.
562
+ - 컬럼 중 하나라도 `#summaryTpl` 을 가지면 요약 행 전체가 활성화됨. 정의 없는 컬럼은 빈 셀로 표시.
563
+ - 셀 본문 약속(`p-xs-sm`, 정렬 클래스 등) 은 요약 셀에도 동일하게 적용.
564
+ - 합계·평균 등 집계 값은 시트가 계산하지 않음. 화면 컴포넌트에서 `computed` 로 직접 만들어 노출.
565
565
 
566
566
  ```ts
567
567
  totalQuantity = computed(() => this.items().sum((i) => i.quantity) ?? 0);
@@ -571,11 +571,11 @@ totalQuantity = computed(() => this.items().sum((i) => i.quantity) ?? 0);
571
571
 
572
572
  ### 폼 항목 레이아웃
573
573
 
574
- label + 입력 그룹을 묶는 전용 클래스 3종:
574
+ label 입력 그룹을 묶는 전용 클래스 3종:
575
575
 
576
- - `form-box` — 세로 스택. `> div` 또는 `> div` 안에 `<label>` + 입력. 항목 사이 `gap-default`.
577
- - `form-box-inline` — 가로 인라인 flex (wrap). 라벨이 입력 옆에 붙음. 검색·필터폼에 사용. 라벨 없는 `form-box-item` 도 허용 (버튼 등).
578
- - `form-table` — `<table>` 기반. `<th>` 가 우측 정렬 라벨, `<td>` 가 입력. `<th class="form-table-header">` 는 섹션 헤더(좌측 정렬, 회색, 위쪽 여백 큼). 라벨/입력 폭을 정렬해야 하는 등록·편집 폼에 사용.
576
+ - `form-box` — 세로 스택. `> div` 안에 `<label>` + 입력. 항목 사이 간격은 `gap-default`.
577
+ - `form-box-inline` — 가로 인라인 flex (wrap). 라벨이 입력 옆에 붙음. 검색·필터 폼에 사용. 라벨 없는 `form-box-item` 도 허용 (버튼 등).
578
+ - `form-table` — `<table>` 기반. `<th>` 가 우측 정렬 라벨, `<td>` 가 입력. `<th class="form-table-header">` 는 섹션 헤더 (좌측 정렬, 회색, 위쪽 여백 큼). 라벨·입력 폭을 정렬해야 하는 등록·편집 폼에 사용.
579
579
 
580
580
  ```html
581
581
  <div class="form-box-inline">
@@ -591,7 +591,7 @@ label + 입력 그룹을 묶는 전용 클래스 3종:
591
591
 
592
592
  ### 양방향 바인딩 + `mark`
593
593
 
594
- 객체 시그널 내부 필드를 양방향으로 묶고, 변경 시 [`mark` 헬퍼] 알림.
594
+ 객체 시그널 내부 필드를 양방향으로 묶고, 변경 시 위의 "`mark` 헬퍼" 섹션 패턴으로 알림.
595
595
 
596
596
  ```html
597
597
  <sd-textfield [(value)]="data().name" (valueChange)="mark(data)" />
@@ -611,7 +611,7 @@ label + 입력 그룹을 묶는 전용 클래스 3종:
611
611
 
612
612
  ### 버튼 스타일
613
613
 
614
- 화면 액션 `<sd-button>` 은 역할별로 `theme`·`size` 를 구분.
614
+ 화면 액션 `<sd-button>` 은 역할별로 `theme`·`size` 를 구분 적용.
615
615
 
616
616
  | 역할 | `[theme]` | `[size]` |
617
617
  | ------------------------------------------------------------- | --------------------------------------------------------------------------- | -------- |
@@ -621,7 +621,7 @@ label + 입력 그룹을 묶는 전용 클래스 3종:
621
621
 
622
622
  ### `<sd-form>` 으로 감싸기
623
623
 
624
- 폼 안 입력에서 enter submit 자동 처리되게 하려면 `<sd-form>` 으로 감싸고 `(formSubmit)` 받음. `sd-crud-list` / `sd-crud-detail` 는 내부에 이미 `sd-form` 을 갖고 있어 별도 래핑 불필요.
624
+ 폼 안 입력에서 Enter 키로 submit 자동 처리되게 하려면 `<sd-form>` 으로 감싸고 `(formSubmit)` 으로 받음. `sd-crud-list` / `sd-crud-detail` 는 내부에 이미 `sd-form` 을 보유하므로 별도 래핑 불필요.
625
625
 
626
626
  ## 서비스 호출 (`AppServiceProvider`)
627
627
 
@@ -645,11 +645,11 @@ await this._appOrm.connectAsync(async (db) => {
645
645
  ```
646
646
 
647
647
  - 기본은 `connectAsync` (트랜잭션). `connectWithoutTransAsync` 는 트랜잭션 안에서 동작하지 않는 작업용 헬퍼.
648
- - 쿼리 작성은 [orm.md](./orm.md), Provider 정의 컨벤션은 [client-setup.md#appormprovider](./client-setup.md#appormprovider) 참조.
648
+ - 쿼리 작성법은 [orm.md](./orm.md), Provider 정의 컨벤션은 [client-setup.md#appormprovider](./client-setup.md#appormprovider) 참조.
649
649
 
650
650
  ## 공유 데이터 (`useSharedSignal`)
651
651
 
652
- 마스터 데이터(고객사·품목 등)는 `AppSharedDataProvider` 에 등록되어 있고, 화면에서는 `useSharedSignal(name)` 으로 접근함.
652
+ 마스터 데이터(고객사·품목 등) 는 `AppSharedDataProvider` 에 등록되어 있고, 화면에서는 `useSharedSignal(name)` 으로 접근.
653
653
 
654
654
  ```ts
655
655
  sharedCustomers = useSharedSignal("고객사");
@@ -666,7 +666,7 @@ sharedCustomers = useSharedSignal("고객사");
666
666
 
667
667
  ## 레이아웃·유틸 클래스
668
668
 
669
- **화면 레이아웃** (영역 분할): flex 유틸 클래스.
669
+ **화면 레이아웃** (영역 분할) flex 유틸 클래스로 구성.
670
670
 
671
671
  상하 분할 (상단 고정 + 본문 fill):
672
672
 
@@ -694,10 +694,10 @@ sharedCustomers = useSharedSignal("고객사");
694
694
  </div>
695
695
  ```
696
696
 
697
- 자주 쓰는 유틸:
697
+ 자주 사용하는 유틸:
698
698
 
699
699
  - **Flex**: `flex-row` / `flex-column` (컨테이너), `flex-fill` (남은 공간), `flex-min` (콘텐츠 크기), `gap-sm` / `gap-default`.
700
- - **부모 가득**: `fill`.
700
+ - **부모 가득 채움**: `fill`.
701
701
  - **패딩**: `p-{vertical}-{horizontal}` (예: `p-default`, `p-xs-sm`, `p-sm-default`). 단일 방향: `pt-` / `pb-` / `pl-` / `pr-`.
702
702
  - **텍스트**: `tx-left` / `tx-center` / `tx-right`.
703
703
  - **테마 색**: 텍스트 `tx-theme-{theme}-default`, 배경 `bg-{theme}-lightest`.
@@ -705,12 +705,12 @@ sharedCustomers = useSharedSignal("고객사");
705
705
 
706
706
  **약속**:
707
707
 
708
- - 영역 분할·배치 모두 flex 유틸 클래스 우선. 자체 styles 작성은 마지막 수단.
709
- - 글로벌 클래스 정의는 `@simplysm/angular/scss/commons/`.
708
+ - 영역 분할·배치 모두 flex 유틸 클래스 우선 적용. 자체 styles 작성은 최후 수단.
709
+ - 글로벌 클래스 정의 위치는 `@simplysm/angular/scss/commons/`.
710
710
 
711
711
  ## 아이콘
712
712
 
713
- `@ng-icons/core` 의 `NgIcon` + `@ng-icons/tabler-icons` 의 `tabler*` 셋트를 사용함.
713
+ `@ng-icons/core` 의 `NgIcon` + `@ng-icons/tabler-icons` 의 `tabler*` 셋트를 사용.
714
714
 
715
715
  ```ts
716
716
  import { NgIcon } from "@ng-icons/core";
@@ -731,9 +731,9 @@ export class SomeComponent {
731
731
 
732
732
  **약속**:
733
733
 
734
- - 아이콘 셋트는 `tabler-icons` 통일.
735
- - 사용할 아이콘은 컴포넌트 클래스에 `protected readonly tablerXxx = tablerXxx` 로 노출 템플릿에서 `[svg]` 바인딩.
734
+ - 아이콘 셋트는 `tabler-icons` 통일.
735
+ - 사용할 아이콘은 컴포넌트 클래스에 `protected readonly tablerXxx = tablerXxx` 로 노출한 템플릿에서 `[svg]` 바인딩.
736
736
 
737
737
  ## sd-crud-* 컴포넌트
738
738
 
739
- 목록 화면 표준 골격 `sd-crud-list`, 단건 편집 화면 표준 골격 `sd-crud-detail`. 화면 작성 시 둘을 채택할지 결정함. 채택 시 사용법은 [client-crud.md](./client-crud.md).
739
+ 목록 화면 표준 골격은 `sd-crud-list`, 단건 편집 화면 표준 골격은 `sd-crud-detail`. 화면 작성 시 채택 여부를 결정. 채택 시 사용법은 [client-crud.md](./client-crud.md) 참조.