@wooojin/forgen 0.4.8 → 0.4.9

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 (122) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/assets/dev-guide/be/README.md +226 -0
  3. package/assets/dev-guide/be/adapters/build-agents-md.sh +63 -0
  4. package/assets/dev-guide/be/principles/common.md +433 -0
  5. package/assets/dev-guide/be/principles/go.md +469 -0
  6. package/assets/dev-guide/be/principles/node.md +388 -0
  7. package/assets/dev-guide/be/skills/go/be-build/SKILL.md +262 -0
  8. package/assets/dev-guide/be/skills/go/be-perf/SKILL.md +308 -0
  9. package/assets/dev-guide/be/skills/go/be-review/SKILL.md +119 -0
  10. package/assets/dev-guide/be/skills/go/be-security/SKILL.md +362 -0
  11. package/assets/dev-guide/be/skills/node/be-build/SKILL.md +239 -0
  12. package/assets/dev-guide/be/skills/node/be-perf/SKILL.md +272 -0
  13. package/assets/dev-guide/be/skills/node/be-review/SKILL.md +118 -0
  14. package/assets/dev-guide/be/skills/node/be-security/SKILL.md +355 -0
  15. package/assets/dev-guide/be/sources/12factor/INDEX.md +53 -0
  16. package/assets/dev-guide/be/sources/api-design/INDEX.md +56 -0
  17. package/assets/dev-guide/be/sources/ddia/INDEX.md +55 -0
  18. package/assets/dev-guide/be/sources/go-runtime/INDEX.md +62 -0
  19. package/assets/dev-guide/be/sources/node-runtime/INDEX.md +60 -0
  20. package/assets/dev-guide/be/sources/otel/INDEX.md +53 -0
  21. package/assets/dev-guide/be/sources/owasp-api/INDEX.md +52 -0
  22. package/assets/dev-guide/be/sources/postgres/INDEX.md +55 -0
  23. package/assets/dev-guide/be/sources/sre-book/INDEX.md +48 -0
  24. package/assets/dev-guide/fe/README.md +197 -0
  25. package/assets/dev-guide/fe/adapters/build-agents-md.sh +63 -0
  26. package/assets/dev-guide/fe/adapters/refresh.sh +68 -0
  27. package/assets/dev-guide/fe/principles/common.md +160 -0
  28. package/assets/dev-guide/fe/principles/react.md +183 -0
  29. package/assets/dev-guide/fe/principles/vue.md +196 -0
  30. package/assets/dev-guide/fe/skills/react/fe-build/SKILL.md +139 -0
  31. package/assets/dev-guide/fe/skills/react/fe-perf/SKILL.md +179 -0
  32. package/assets/dev-guide/fe/skills/react/fe-review/SKILL.md +141 -0
  33. package/assets/dev-guide/fe/skills/vue/fe-build/SKILL.md +148 -0
  34. package/assets/dev-guide/fe/skills/vue/fe-perf/SKILL.md +163 -0
  35. package/assets/dev-guide/fe/skills/vue/fe-review/SKILL.md +136 -0
  36. package/assets/dev-guide/fe/sources/a11y-dx/INDEX.md +41 -0
  37. package/assets/dev-guide/fe/sources/a11y-dx/chrome-devtools-memory.md +150 -0
  38. package/assets/dev-guide/fe/sources/a11y-dx/chrome-devtools-performance.md +99 -0
  39. package/assets/dev-guide/fe/sources/a11y-dx/lighthouse-audits.md +146 -0
  40. package/assets/dev-guide/fe/sources/a11y-dx/react-devtools-profiler.md +128 -0
  41. package/assets/dev-guide/fe/sources/a11y-dx/wcag22-new-criteria.md +174 -0
  42. package/assets/dev-guide/fe/sources/perf/01-core-web-vitals.md +58 -0
  43. package/assets/dev-guide/fe/sources/perf/02-inp.md +83 -0
  44. package/assets/dev-guide/fe/sources/perf/03-lcp-cls.md +130 -0
  45. package/assets/dev-guide/fe/sources/perf/04-speculation-rules.md +148 -0
  46. package/assets/dev-guide/fe/sources/perf/05-view-transitions.md +153 -0
  47. package/assets/dev-guide/fe/sources/perf/06-nextjs-caching.md +188 -0
  48. package/assets/dev-guide/fe/sources/perf/07-server-components.md +181 -0
  49. package/assets/dev-guide/fe/sources/perf/08-ppr.md +133 -0
  50. package/assets/dev-guide/fe/sources/perf/09-nextjs-image.md +200 -0
  51. package/assets/dev-guide/fe/sources/perf/10-optimize-lcp.md +201 -0
  52. package/assets/dev-guide/fe/sources/perf/INDEX.md +88 -0
  53. package/assets/dev-guide/fe/sources/react/INDEX.md +41 -0
  54. package/assets/dev-guide/fe/sources/react/keeping-components-pure.md +135 -0
  55. package/assets/dev-guide/fe/sources/react/no-effect-patterns.md +183 -0
  56. package/assets/dev-guide/fe/sources/react/react-compiler.md +182 -0
  57. package/assets/dev-guide/fe/sources/react/server-components.md +194 -0
  58. package/assets/dev-guide/fe/sources/react/server-functions.md +192 -0
  59. package/assets/dev-guide/fe/sources/react/suspense.md +218 -0
  60. package/assets/dev-guide/fe/sources/react/use-action-state.md +123 -0
  61. package/assets/dev-guide/fe/sources/react/use-form-status.md +158 -0
  62. package/assets/dev-guide/fe/sources/react/use-hook.md +153 -0
  63. package/assets/dev-guide/fe/sources/react/use-optimistic.md +194 -0
  64. package/assets/dev-guide/fe/sources/toss-ff/INDEX.md +58 -0
  65. package/assets/dev-guide/fe/sources/toss-ff/cohesion-code-directory.md +79 -0
  66. package/assets/dev-guide/fe/sources/toss-ff/cohesion-form-fields.md +110 -0
  67. package/assets/dev-guide/fe/sources/toss-ff/cohesion-magic-number.md +47 -0
  68. package/assets/dev-guide/fe/sources/toss-ff/coupling-item-edit-modal.md +124 -0
  69. package/assets/dev-guide/fe/sources/toss-ff/coupling-use-bottom-sheet.md +57 -0
  70. package/assets/dev-guide/fe/sources/toss-ff/coupling-use-page-state.md +71 -0
  71. package/assets/dev-guide/fe/sources/toss-ff/overview-4-principles.md +77 -0
  72. package/assets/dev-guide/fe/sources/toss-ff/predictability-hidden-logic.md +59 -0
  73. package/assets/dev-guide/fe/sources/toss-ff/predictability-http.md +77 -0
  74. package/assets/dev-guide/fe/sources/toss-ff/predictability-use-user.md +110 -0
  75. package/assets/dev-guide/fe/sources/toss-ff/readability-comparison-order.md +52 -0
  76. package/assets/dev-guide/fe/sources/toss-ff/readability-condition-name.md +64 -0
  77. package/assets/dev-guide/fe/sources/toss-ff/readability-login-start-page.md +183 -0
  78. package/assets/dev-guide/fe/sources/toss-ff/readability-magic-number.md +53 -0
  79. package/assets/dev-guide/fe/sources/toss-ff/readability-submit-button.md +73 -0
  80. package/assets/dev-guide/fe/sources/toss-ff/readability-ternary-operator.md +38 -0
  81. package/assets/dev-guide/fe/sources/toss-ff/readability-use-page-state.md +77 -0
  82. package/assets/dev-guide/fe/sources/toss-ff/readability-user-policy.md +98 -0
  83. package/assets/dev-guide/fe/sources/vue/INDEX.md +17 -0
  84. package/assets/dev-guide/fe/sources/vue/composition-api.md +251 -0
  85. package/assets/dev-guide/fe/sources/vue/nuxt-data-fetching.md +232 -0
  86. package/assets/dev-guide/fe/sources/vue/pinia-state-management.md +134 -0
  87. package/assets/dev-guide/fe/sources/vue/reactivity-pitfalls.md +261 -0
  88. package/assets/dev-guide/fe/sources/vue/style-guide-priority-a.md +117 -0
  89. package/assets/dev-guide/fe/sources/vue/style-guide-priority-b.md +231 -0
  90. package/assets/dev-guide/fe/sources/vue/style-guide-priority-c.md +86 -0
  91. package/assets/dev-guide/fe/sources/vue/style-guide-priority-d.md +72 -0
  92. package/dist/cli.js +42 -0
  93. package/dist/core/dashboard-cli.d.ts +12 -0
  94. package/dist/core/dashboard-cli.js +226 -0
  95. package/dist/core/dev-guide-injector.d.ts +26 -0
  96. package/dist/core/dev-guide-injector.js +137 -0
  97. package/dist/core/init.js +53 -0
  98. package/dist/core/lifecycle-classifier.d.ts +23 -0
  99. package/dist/core/lifecycle-classifier.js +104 -0
  100. package/dist/core/observability-backfill.d.ts +31 -0
  101. package/dist/core/observability-backfill.js +178 -0
  102. package/dist/core/observability-store.d.ts +58 -0
  103. package/dist/core/observability-store.js +195 -0
  104. package/dist/core/session-store.js +4 -0
  105. package/dist/core/spawn.d.ts +17 -0
  106. package/dist/core/spawn.js +179 -2
  107. package/dist/core/statusline-cli.js +34 -1
  108. package/dist/engine/compound-extractor.js +39 -0
  109. package/dist/engine/compound-loop.js +6 -0
  110. package/dist/engine/compound-retire.d.ts +20 -0
  111. package/dist/engine/compound-retire.js +85 -0
  112. package/dist/hooks/context-guard.js +25 -1
  113. package/dist/hooks/post-tool-use.js +48 -0
  114. package/dist/hooks/solution-injector.js +93 -0
  115. package/dist/host/install-claude.d.ts +6 -2
  116. package/dist/host/install-claude.js +74 -2
  117. package/dist/host/install-codex.d.ts +4 -0
  118. package/dist/host/install-codex.js +71 -0
  119. package/dist/host/install-orchestrator.js +1 -0
  120. package/package.json +6 -6
  121. package/plugin.json +1 -1
  122. package/scripts/postinstall.js +134 -0
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: Vue 3 스타일 가이드 - Priority A (Essential)
3
+ source: https://vuejs.org/style-guide/rules-essential
4
+ fetched: 2026-05-18
5
+ category: style-guide
6
+ vue_version: 3
7
+ ---
8
+
9
+ # Priority A: Essential
10
+
11
+ 반드시 지켜야 하는 규칙. 위반 시 버그 또는 예측 불가 동작이 발생한다.
12
+
13
+ ---
14
+
15
+ ## 1. 멀티-워드 컴포넌트 이름
16
+
17
+ **규칙:** 루트 `App` 컴포넌트를 제외한 모든 사용자 정의 컴포넌트는 반드시 다단어 이름을 사용한다. HTML 요소는 모두 단일 단어이므로 충돌을 방지한다.
18
+
19
+ ```vue
20
+ <!-- Bad -->
21
+ <Item />
22
+ <!-- Good -->
23
+ <TodoItem />
24
+ ```
25
+
26
+ ---
27
+
28
+ ## 2. 상세한 Prop 정의
29
+
30
+ **규칙:** 커밋된 코드에서 prop 정의는 가능한 한 상세하게 작성하고, 최소한 타입은 지정해야 한다.
31
+
32
+ ```js
33
+ // Bad
34
+ const props = defineProps(['status'])
35
+
36
+ // Good
37
+ const props = defineProps({
38
+ status: String
39
+ })
40
+
41
+ // Best
42
+ const props = defineProps({
43
+ status: {
44
+ type: String,
45
+ required: true,
46
+ validator: (value) => {
47
+ return ['syncing', 'synced', 'version-conflict', 'error'].includes(value)
48
+ }
49
+ }
50
+ })
51
+ ```
52
+
53
+ ---
54
+
55
+ ## 3. v-for에 key 사용
56
+
57
+ **규칙:** 컴포넌트의 `v-for`에는 반드시 `key`를 사용한다.
58
+
59
+ ```vue
60
+ <!-- Bad -->
61
+ <li v-for="todo in todos">{{ todo.text }}</li>
62
+
63
+ <!-- Good -->
64
+ <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
65
+ ```
66
+
67
+ ---
68
+
69
+ ## 4. v-if와 v-for 혼용 금지
70
+
71
+ **규칙:** 같은 요소에 `v-if`와 `v-for`를 함께 사용하지 않는다. Vue에서 `v-if`가 `v-for`보다 우선순위가 높아 반복 변수에 접근이 불가하다.
72
+
73
+ ```vue
74
+ <!-- Bad -->
75
+ <li v-for="user in users" v-if="user.isActive" :key="user.id">
76
+
77
+ <!-- Good: computed로 필터링 -->
78
+ <li v-for="user in activeUsers" :key="user.id">
79
+
80
+ <!-- Good: template 래퍼 사용 -->
81
+ <template v-for="user in users" :key="user.id">
82
+ <li v-if="user.isActive">{{ user.name }}</li>
83
+ </template>
84
+ ```
85
+
86
+ ```js
87
+ // Composition API
88
+ const activeUsers = computed(() => users.filter((user) => user.isActive))
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 5. 컴포넌트 스코프 스타일링
94
+
95
+ **규칙:** 앱 레벨 및 레이아웃 컴포넌트를 제외한 모든 컴포넌트의 스타일은 반드시 스코프를 가져야 한다.
96
+
97
+ ```vue
98
+ <!-- Bad: 전역 스타일 -->
99
+ <style>
100
+ .btn-close { background-color: red; }
101
+ </style>
102
+
103
+ <!-- Good: scoped -->
104
+ <style scoped>
105
+ .btn-close { background-color: red; }
106
+ </style>
107
+
108
+ <!-- Good: CSS Modules -->
109
+ <style module>
110
+ .btnClose { background-color: red; }
111
+ </style>
112
+
113
+ <!-- Good: BEM -->
114
+ <style>
115
+ .c-Button--close { background-color: red; }
116
+ </style>
117
+ ```
@@ -0,0 +1,231 @@
1
+ ---
2
+ title: Vue 3 스타일 가이드 - Priority B (Strongly Recommended)
3
+ source: https://vuejs.org/style-guide/rules-strongly-recommended
4
+ fetched: 2026-05-18
5
+ category: style-guide
6
+ vue_version: 3
7
+ ---
8
+
9
+ # Priority B: Strongly Recommended
10
+
11
+ 코드 가독성과 DX를 향상시킨다. 위반 시 코드는 동작하나 정당한 이유가 있어야 한다.
12
+
13
+ ---
14
+
15
+ ## 1. 컴포넌트 파일 분리
16
+
17
+ 각 컴포넌트는 별도 파일로 분리한다.
18
+
19
+ ```
20
+ components/
21
+ |- TodoList.vue
22
+ |- TodoItem.vue
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 2. SFC 파일명 케이싱
28
+
29
+ PascalCase 또는 kebab-case 중 하나를 일관되게 사용한다.
30
+
31
+ ```
32
+ # Good (PascalCase)
33
+ components/|- MyComponent.vue
34
+
35
+ # Good (kebab-case)
36
+ components/|- my-component.vue
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 3. 베이스 컴포넌트 이름 접두사
42
+
43
+ 순수 프레젠테이션 컴포넌트는 `Base`, `App`, `V` 접두사를 붙인다.
44
+
45
+ ```
46
+ # Bad
47
+ |- MyButton.vue, Icon.vue
48
+
49
+ # Good
50
+ |- BaseButton.vue, BaseTable.vue, BaseIcon.vue
51
+ ```
52
+
53
+ Vite 자동 전역 등록:
54
+ ```js
55
+ const modules = import.meta.glob('./src/**/Base*.vue', { eager: true })
56
+ for (const path in modules) {
57
+ const config = modules[path].default
58
+ const name = config.name || path.match(/Base[A-Z]\w+/)[0]
59
+ app.component(name, config)
60
+ }
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 4. 강하게 결합된 컴포넌트 이름
66
+
67
+ 부모에 종속된 자식 컴포넌트는 부모 이름을 접두사로 사용한다.
68
+
69
+ ```
70
+ # Bad
71
+ |- TodoList.vue, TodoItem.vue, TodoButton.vue
72
+
73
+ # Good (연관성 명확)
74
+ |- TodoList.vue, TodoListItem.vue, TodoListItemButton.vue
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 5. 컴포넌트 이름 단어 순서
80
+
81
+ 가장 일반적인 단어부터 시작하고, 수식어를 뒤에 붙인다.
82
+
83
+ ```
84
+ # Bad
85
+ |- ClearSearchButton.vue, RunSearchButton.vue
86
+
87
+ # Good
88
+ |- SearchButtonClear.vue, SearchButtonRun.vue, SearchInputQuery.vue
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 6. 셀프 클로징 컴포넌트
94
+
95
+ SFC/JSX에서 콘텐츠 없는 컴포넌트는 셀프 클로징한다. in-DOM 템플릿에서는 사용하지 않는다.
96
+
97
+ ```vue
98
+ <!-- Good: SFC/JSX -->
99
+ <MyComponent/>
100
+
101
+ <!-- Good: in-DOM template -->
102
+ <my-component></my-component>
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 7. 템플릿에서 컴포넌트 이름 케이싱
108
+
109
+ SFC: PascalCase / in-DOM: kebab-case
110
+
111
+ ```vue
112
+ <MyComponent/> <!-- SFC -->
113
+ <my-component></my-component> <!-- in-DOM -->
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 8. JS/JSX에서 PascalCase
119
+
120
+ ```js
121
+ import MyComponent from './MyComponent.vue'
122
+ export default { name: 'MyComponent' }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 9. Prop 이름 케이싱
128
+
129
+ 선언: camelCase / in-DOM 템플릿: kebab-case
130
+
131
+ ```js
132
+ // 선언
133
+ const props = defineProps({ greetingText: String })
134
+ ```
135
+
136
+ ```vue
137
+ <!-- SFC -->
138
+ <WelcomeMessage greeting-text="hi"/>
139
+ <!-- in-DOM -->
140
+ <welcome-message greeting-text="hi"></welcome-message>
141
+ ```
142
+
143
+ ---
144
+
145
+ ## 10. 멀티 속성 요소 줄 분리
146
+
147
+ 여러 속성은 한 줄에 하나씩 작성한다.
148
+
149
+ ```vue
150
+ <!-- Bad -->
151
+ <MyComponent foo="a" bar="b" baz="c"/>
152
+
153
+ <!-- Good -->
154
+ <MyComponent
155
+ foo="a"
156
+ bar="b"
157
+ baz="c"
158
+ />
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 11. 템플릿에서 단순 표현식
164
+
165
+ 복잡한 로직은 computed나 method로 분리한다.
166
+
167
+ ```vue
168
+ <!-- Bad -->
169
+ {{ fullName.split(' ').map((word) => word[0].toUpperCase() + word.slice(1)).join(' ') }}
170
+
171
+ <!-- Good -->
172
+ {{ normalizedFullName }}
173
+ ```
174
+
175
+ ```js
176
+ const normalizedFullName = computed(() =>
177
+ fullName.value
178
+ .split(' ')
179
+ .map((word) => word[0].toUpperCase() + word.slice(1))
180
+ .join(' ')
181
+ )
182
+ ```
183
+
184
+ ---
185
+
186
+ ## 12. 단순 computed 속성
187
+
188
+ 복잡한 computed는 여러 단순한 속성으로 분리한다.
189
+
190
+ ```js
191
+ // Bad
192
+ const price = computed(() => {
193
+ const basePrice = manufactureCost.value / (1 - profitMargin.value)
194
+ return basePrice - basePrice * (discountPercent.value || 0)
195
+ })
196
+
197
+ // Good
198
+ const basePrice = computed(() => manufactureCost.value / (1 - profitMargin.value))
199
+ const discount = computed(() => basePrice.value * (discountPercent.value || 0))
200
+ const finalPrice = computed(() => basePrice.value - discount.value)
201
+ ```
202
+
203
+ ---
204
+
205
+ ## 13. 속성 값 인용
206
+
207
+ 비어있지 않은 HTML 속성 값은 항상 따옴표로 감싼다.
208
+
209
+ ```vue
210
+ <!-- Bad -->
211
+ <input type=text>
212
+
213
+ <!-- Good -->
214
+ <input type="text">
215
+ ```
216
+
217
+ ---
218
+
219
+ ## 14. 디렉티브 단축형 일관성
220
+
221
+ `:`, `@`, `#` 단축형을 항상 사용하거나, 항상 사용하지 않는다. 혼용 금지.
222
+
223
+ ```vue
224
+ <!-- Good: 항상 단축형 -->
225
+ <input :value="val" @input="onInput">
226
+ <template #header>...</template>
227
+
228
+ <!-- Good: 항상 전체형 -->
229
+ <input v-bind:value="val" v-on:input="onInput">
230
+ <template v-slot:header>...</template>
231
+ ```
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: Vue 3 스타일 가이드 - Priority C (Recommended)
3
+ source: https://vuejs.org/style-guide/rules-recommended
4
+ fetched: 2026-05-18
5
+ category: style-guide
6
+ vue_version: 3
7
+ ---
8
+
9
+ # Priority C: Recommended
10
+
11
+ 여러 동등한 선택지가 있을 때 일관성을 위해 권장되는 규칙.
12
+
13
+ ---
14
+
15
+ ## 1. 컴포넌트/인스턴스 옵션 순서 (Options API)
16
+
17
+ 1. `name`
18
+ 2. `compilerOptions`
19
+ 3. `components`, `directives`
20
+ 4. `extends`, `mixins`, `provide`/`inject`
21
+ 5. `inheritAttrs`, `props`, `emits`, `expose`
22
+ 6. `setup`
23
+ 7. `data`, `computed`
24
+ 8. `watch`, lifecycle hooks (`beforeCreate` → `serverPrefetch` 순서)
25
+ 9. `methods`
26
+ 10. `template`/`render`
27
+
28
+ ---
29
+
30
+ ## 2. 요소 속성 순서
31
+
32
+ 1. `is`
33
+ 2. `v-for`
34
+ 3. `v-if`, `v-else-if`, `v-else`, `v-show`, `v-cloak`
35
+ 4. `v-pre`, `v-once`
36
+ 5. `id`
37
+ 6. `ref`, `key`
38
+ 7. `v-model`
39
+ 8. 기타 바인딩/속성
40
+ 9. `v-on`
41
+ 10. `v-html`, `v-text`
42
+
43
+ ---
44
+
45
+ ## 3. 컴포넌트/인스턴스 옵션 사이 빈 줄
46
+
47
+ 여러 줄 속성 사이에는 빈 줄을 추가해 가독성을 높인다.
48
+
49
+ ```js
50
+ // Good (Composition API)
51
+ defineProps({
52
+ value: {
53
+ type: String,
54
+ required: true
55
+ },
56
+
57
+ focused: {
58
+ type: Boolean,
59
+ default: false
60
+ },
61
+
62
+ label: String,
63
+ })
64
+
65
+ const formattedValue = computed(() => { /* ... */ })
66
+
67
+ const inputClasses = computed(() => { /* ... */ })
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 4. SFC 최상위 요소 순서
73
+
74
+ `<script>`, `<template>`, `<style>` 순서를 프로젝트 전체에서 일관되게 유지한다. `<style>`은 항상 마지막.
75
+
76
+ ```vue
77
+ <!-- Option 1: script first -->
78
+ <script>/* ... */</script>
79
+ <template>...</template>
80
+ <style>/* ... */</style>
81
+
82
+ <!-- Option 2: template first -->
83
+ <template>...</template>
84
+ <script>/* ... */</script>
85
+ <style>/* ... */</style>
86
+ ```
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: Vue 3 스타일 가이드 - Priority D (Use with Caution)
3
+ source: https://vuejs.org/style-guide/rules-use-with-caution
4
+ fetched: 2026-05-18
5
+ category: style-guide
6
+ vue_version: 3
7
+ ---
8
+
9
+ # Priority D: Use with Caution
10
+
11
+ 드문 엣지 케이스나 레거시 마이그레이션을 위해 존재하며, 과용 시 유지보수가 어려워진다.
12
+
13
+ ---
14
+
15
+ ## 1. scoped에서 요소 선택자 지양
16
+
17
+ `scoped`에서 요소 선택자는 class 선택자보다 훨씬 느리다. 반드시 class를 사용한다.
18
+
19
+ ```vue
20
+ <!-- Bad: 요소 선택자 (느림) -->
21
+ <style scoped>
22
+ button { background-color: red; }
23
+ </style>
24
+
25
+ <!-- Good: class 선택자 (빠름) -->
26
+ <template>
27
+ <button class="btn btn-close">×</button>
28
+ </template>
29
+ <style scoped>
30
+ .btn-close { background-color: red; }
31
+ </style>
32
+ ```
33
+
34
+ **이유:** Vue는 `scoped` 사용 시 `button[data-v-f3f3eg9]` 형태로 변환하는데, 이 속성-요소 복합 선택자는 `.btn-close[data-v-f3f3eg9]`보다 현저히 느리다.
35
+
36
+ ---
37
+
38
+ ## 2. 암묵적 부모-자식 통신 지양
39
+
40
+ `this.$parent`나 prop 직접 변경 대신 props down / events up 패턴을 따른다.
41
+
42
+ ```vue
43
+ <!-- Bad: prop 직접 변경 -->
44
+ <script setup>
45
+ const props = defineProps({ todo: { type: Object, required: true } })
46
+
47
+ function renameTodo() {
48
+ props.todo.text = 'renamed by child' // ❌ 부모 상태 직접 변경
49
+ }
50
+ </script>
51
+
52
+ <!-- Good: emit으로 업데이트 요청 -->
53
+ <script setup>
54
+ const props = defineProps({ todo: { type: Object, required: true } })
55
+ const emit = defineEmits(['update:todo'])
56
+
57
+ function renameTodo() {
58
+ emit('update:todo', { ...props.todo, text: 'renamed by parent' }) // ✅
59
+ }
60
+ </script>
61
+ ```
62
+
63
+ ```vue
64
+ <!-- Bad: this.$parent 사용 -->
65
+ <!-- Good: emit('delete') 사용 -->
66
+ <script setup>
67
+ const emit = defineEmits(['delete'])
68
+ </script>
69
+ <template>
70
+ <button @click="emit('delete')">×</button>
71
+ </template>
72
+ ```
package/dist/cli.js CHANGED
@@ -186,6 +186,48 @@ const commands = [
186
186
  console.log(renderResult(result, dryRun));
187
187
  },
188
188
  },
189
+ {
190
+ name: 'status',
191
+ description: 'Observability dashboard (--watch, --json, --interval N)',
192
+ handler: async (args) => {
193
+ const { runDashboard } = await import('./core/dashboard-cli.js');
194
+ const watch = args.includes('--watch');
195
+ const json = args.includes('--json');
196
+ const intervalIdx = args.indexOf('--interval');
197
+ const intervalSec = intervalIdx !== -1 ? Number(args[intervalIdx + 1]) || 5 : 5;
198
+ await runDashboard({ watch, json, intervalSec });
199
+ },
200
+ },
201
+ {
202
+ name: 'maintenance',
203
+ description: 'Maintenance utilities (--backfill [--phase A|B|all] [--force] [--dry-run])',
204
+ handler: async (args) => {
205
+ if (args.includes('--backfill')) {
206
+ const phaseArg = args[args.indexOf('--phase') + 1];
207
+ const phase = (phaseArg === 'A' || phaseArg === 'B' || phaseArg === 'all') ? phaseArg : 'A';
208
+ const force = args.includes('--force');
209
+ const dryRun = args.includes('--dry-run');
210
+ const { runBackfill } = await import('./core/observability-backfill.js');
211
+ try {
212
+ const result = await runBackfill({ phase, force, dryRun });
213
+ const dryTag = dryRun ? ' [dry-run]' : '';
214
+ console.log(`\n [forgen] Backfill complete${dryTag}:`);
215
+ console.log(` Phase A — matched: ${result.phaseA.matched}, surfaced: ${result.phaseA.surfaced}, acted_on: ${result.phaseA.acted_on}`);
216
+ if (phase !== 'A')
217
+ console.log(` Phase B — acted_on: ${result.phaseB.acted_on}`);
218
+ console.log(` Total: ${result.total} events, ${result.durationMs}ms\n`);
219
+ }
220
+ catch (e) {
221
+ console.error(` [forgen] Backfill 실패: ${e instanceof Error ? e.message : String(e)}`);
222
+ console.error(' --force 플래그로 강행하거나 --dry-run 으로 미리 확인하세요.');
223
+ process.exit(1);
224
+ }
225
+ }
226
+ else {
227
+ console.log('Usage:\n forgen maintenance --backfill [--phase A|B|all] [--force] [--dry-run]');
228
+ }
229
+ },
230
+ },
189
231
  {
190
232
  name: 'parity',
191
233
  description: 'Run host parity checks. Usage: forgen parity codex [--dry-run]',
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Forgen — Dashboard CLI (P3)
3
+ *
4
+ * `fgx status [--watch] [--json] [--interval N]`
5
+ * ANSI box-drawing 기반 상태 대시보드. TUI 라이브러리 없음.
6
+ */
7
+ export interface DashboardOptions {
8
+ watch?: boolean;
9
+ json?: boolean;
10
+ intervalSec?: number;
11
+ }
12
+ export declare function runDashboard(opts: DashboardOptions): Promise<void>;