@axboot-mcp/mcp-server 1.0.0

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 (78) hide show
  1. package/CLAUDE.md +119 -0
  2. package/MCP_TOOL_PLAN.md +710 -0
  3. package/MCP_USAGE.md +914 -0
  4. package/README.md +168 -0
  5. package/REPOSITORY_CONVENTIONS.md +250 -0
  6. package/SEARCH_PARAMS_MCP_TOOL_COMPLETE_PLAN.md +646 -0
  7. package/SEARCH_PARAMS_PLAN.md +2570 -0
  8. package/STORE_PATTERNS.md +1178 -0
  9. package/debug-dto.js +72 -0
  10. package/generate-banner-store.js +62 -0
  11. package/generation-plan.json +2176 -0
  12. package/generation-results.json +1817 -0
  13. package/package.json +45 -0
  14. package/scripts/batch-generate-all.js +159 -0
  15. package/scripts/batch-generate-mcp.js +329 -0
  16. package/scripts/batch-generate-stores-v2.js +272 -0
  17. package/scripts/batch-generate-stores.js +179 -0
  18. package/scripts/batch-plan.json +3810 -0
  19. package/scripts/batch-process.py +90 -0
  20. package/scripts/batch-regenerate.js +356 -0
  21. package/scripts/direct-generate.js +227 -0
  22. package/scripts/execute-batches.js +1911 -0
  23. package/scripts/generate-all-stores.js +144 -0
  24. package/scripts/generate-stores-mcp.js +161 -0
  25. package/scripts/generate-stores-v2.js +450 -0
  26. package/scripts/generate-stores-v3.js +412 -0
  27. package/scripts/generate-stores-v4.js +521 -0
  28. package/scripts/generate-stores.js +382 -0
  29. package/scripts/repos-to-process.json +1899 -0
  30. package/src/config/nh-layout-patterns.ts +166 -0
  31. package/src/docs/HOOK_GENERATION_PLAN.md +2226 -0
  32. package/src/docs/NH_STORE_PATTERNS.md +297 -0
  33. package/src/docs/README.md +216 -0
  34. package/src/docs/index.ts +28 -0
  35. package/src/docs/loader.ts +568 -0
  36. package/src/docs/patterns.json +419 -0
  37. package/src/docs/practical-examples.md +732 -0
  38. package/src/docs/quick-start.md +257 -0
  39. package/src/docs/requirements-analysis-guide.md +364 -0
  40. package/src/docs/rules.json +321 -0
  41. package/src/docs/store-pattern-analysis.md +664 -0
  42. package/src/docs/store-patterns-rules.md +1168 -0
  43. package/src/docs/store-patterns-usage-guide.md +1835 -0
  44. package/src/docs/troubleshooting.md +544 -0
  45. package/src/docs/type-selection-guide.md +572 -0
  46. package/src/docs//354/202/254/354/232/251/353/262/225/AntD-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +1515 -0
  47. package/src/docs//354/202/254/354/232/251/353/262/225/DataGrid-/354/202/254/354/232/251/353/262/225.md +866 -0
  48. package/src/docs//354/202/254/354/232/251/353/262/225/FormItem-/354/202/254/354/232/251/353/262/225.md +903 -0
  49. package/src/docs//354/202/254/354/232/251/353/262/225/FormModal-/354/202/254/354/232/251/353/262/225.md +1155 -0
  50. package/src/docs//354/202/254/354/232/251/353/262/225/MCP-/353/260/224/354/235/264/353/270/214/354/275/224/353/224/251-/352/260/200/354/235/264/353/223/234.md +1133 -0
  51. package/src/docs//354/202/254/354/232/251/353/262/225/MSW-Mock-/353/215/260/354/235/264/355/204/260-/354/202/254/354/232/251/353/262/225.md +579 -0
  52. package/src/docs//354/202/254/354/232/251/353/262/225/Search-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +738 -0
  53. package/src/docs//354/202/254/354/232/251/353/262/225/Store-/355/214/250/355/204/264-/354/202/254/354/232/251/353/262/225.md +1135 -0
  54. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/352/265/254/354/204/261-/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234/354/210/234/354/204/234.md +1805 -0
  55. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234-/355/224/204/353/241/254/355/224/204/355/212/270-/352/260/200/354/235/264/353/223/234.md +946 -0
  56. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/225/354/236/245/355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/354/203/201/354/204/270-/355/224/204/353/241/254/355/224/204/355/212/270/352/260/200/354/235/264/353/223/234.md +2422 -0
  57. package/src/features/store-features.ts +232 -0
  58. package/src/handlers/analyze-requirements.ts +403 -0
  59. package/src/handlers/analyze.ts +1373 -0
  60. package/src/handlers/generate-from-requirements.ts +250 -0
  61. package/src/handlers/generate-hook.ts +950 -0
  62. package/src/handlers/generate-interactive.ts +840 -0
  63. package/src/handlers/generate-listdatagrid.ts +521 -0
  64. package/src/handlers/generate-multi-stores.ts +577 -0
  65. package/src/handlers/generate-requirements-from-layout.ts +160 -0
  66. package/src/handlers/generate-search-params.ts +717 -0
  67. package/src/handlers/generate.ts +911 -0
  68. package/src/handlers/list-templates.ts +104 -0
  69. package/src/handlers/scan-metadata.ts +485 -0
  70. package/src/handlers/suggest-layout.ts +326 -0
  71. package/src/index.ts +959 -0
  72. package/src/prompts/search-params.md +793 -0
  73. package/src/templates/index.ts +107 -0
  74. package/src/templates/unified.ts +462 -0
  75. package/store-generation-error-patterns.md +225 -0
  76. package/test/useAgentStore.ts +136 -0
  77. package/test-server.js +78 -0
  78. package/tsconfig.json +20 -0
@@ -0,0 +1,738 @@
1
+ # Search 컴포넌트 사용법 가이드
2
+
3
+ AXBoot의 Search 컴포넌트 시스템은 검색 폼을 쉽게 구성할 수 있는 통합 솔루션입니다. 다양한 입력 타입과 레이아웃을 지원하며, TypeScript로 완전히 구현되어 있습니다.
4
+
5
+ ## 목차
6
+ 1. [개요](#개요)
7
+ 2. [기본 사용법](#기본-사용법)
8
+ 3. [SearchParamType 종류](#searchparamtype-종류)
9
+ 4. [개별 컴포넌트 사용법](#개별-컴포넌트-사용법)
10
+ 5. [고급 기능](#고급-기능)
11
+ 6. [스타일링](#스타일링)
12
+ 7. [실제 사용 예제](#실제-사용-예제)
13
+
14
+ ## 개요
15
+
16
+ Search 컴포넌트 시스템은 다음과 같은 구조로 구성되어 있습니다:
17
+
18
+ - **SearchParams**: 메인 컨테이너 컴포넌트
19
+ - **SearchParam**: 개별 검색 파라미터 컴포넌트 (타입별 라우팅)
20
+ - **SearchParamType**: 검색 파라미터 타입 enum
21
+ - **개별 컴포넌트들**: 각 타입별 구현체
22
+
23
+ ### 주요 특징
24
+ - 🔧 **TypeScript 완전 지원**: 타입 안정성 보장
25
+ - 🎨 **다양한 입력 타입**: INPUT, SELECT, DATE_RANGE, CHECKBOX 등
26
+ - 📱 **반응형 디자인**: 다양한 화면 크기 지원
27
+ - 🚀 **성능 최적화**: debounce와 memoization 활용
28
+ - 🎯 **쉬운 사용법**: 선언적 설정으로 빠른 구현
29
+
30
+ ## 기본 사용법
31
+
32
+ ### 1. 기본 설정
33
+
34
+ ```typescript
35
+ import { SearchParams, IParam, SearchParamType } from "@core/components/search";
36
+ import { Form } from "antd";
37
+
38
+ // 검색 파라미터 정의
39
+ const searchParams: IParam[] = [
40
+ {
41
+ name: "keyword",
42
+ type: SearchParamType.INPUT,
43
+ label: "키워드",
44
+ placeholder: "검색어를 입력하세요",
45
+ width: 200
46
+ },
47
+ {
48
+ name: "status",
49
+ type: SearchParamType.SELECT,
50
+ label: "상태",
51
+ options: [
52
+ { label: "전체", value: "" },
53
+ { label: "활성", value: "Y" },
54
+ { label: "비활성", value: "N" }
55
+ ]
56
+ }
57
+ ];
58
+
59
+ // 컴포넌트에서 사용
60
+ function MySearchForm() {
61
+ const [form] = Form.useForm();
62
+ const [paramsValue, setParamsValue] = useState({});
63
+
64
+ const handleSearch = () => {
65
+ console.log("검색 실행:", paramsValue);
66
+ };
67
+
68
+ return (
69
+ <SearchParams
70
+ form={form}
71
+ params={searchParams}
72
+ paramsValue={paramsValue}
73
+ onChangeParamsValue={setParamsValue}
74
+ onSearch={handleSearch}
75
+ />
76
+ );
77
+ }
78
+ ```
79
+
80
+ ### 2. 필수 Props
81
+
82
+ | Prop | 타입 | 설명 |
83
+ |------|------|------|
84
+ | `form` | FormInstance | Ant Design Form 인스턴스 |
85
+ | `params` | IParam[] | 검색 파라미터 배열 |
86
+ | `paramsValue` | ParamsValue | 현재 검색 값 |
87
+ | `onChangeParamsValue` | Function | 값 변경 핸들러 |
88
+ | `onSearch` | Function | 검색 실행 핸들러 |
89
+
90
+ ## SearchParamType 종류
91
+
92
+ ### 지원하는 검색 파라미터 타입
93
+
94
+ ```typescript
95
+ export enum SearchParamType {
96
+ INPUT, // 텍스트 입력
97
+ DATE_RANGE, // 날짜 범위
98
+ TIME_RANGE, // 시간 범위
99
+ NUMBER_RANGE, // 숫자 범위
100
+ SELECT, // 단일 선택
101
+ SELECT_MULTI, // 다중 선택
102
+ CHECKBOX, // 체크박스 그룹
103
+ DATE, // 단일 날짜
104
+ VALUES_FINDER, // 값 찾기 (검색 기능 포함)
105
+ SUBMIT_BUTTON, // 제출 버튼
106
+ BUTTON, // 일반 버튼
107
+ CASCADE, // 계층형 선택
108
+ RADIO, // 라디오 버튼
109
+ DTPICKER_DATE, // DatePicker 날짜
110
+ DTPICKER_DATE_RANGE, // DatePicker 날짜 범위
111
+ LINE_BREAK, // 줄 바꿈
112
+ GAP, // 간격
113
+ GROUP, // 그룹
114
+ }
115
+ ```
116
+
117
+ ## 개별 컴포넌트 사용법
118
+
119
+ ### 1. INPUT - 텍스트 입력
120
+
121
+ ```typescript
122
+ {
123
+ name: "searchKeyword",
124
+ type: SearchParamType.INPUT,
125
+ label: "검색어",
126
+ placeholder: "검색어를 입력하세요",
127
+ width: 200,
128
+ allowClear: true,
129
+ autoFocus: false
130
+ }
131
+ ```
132
+
133
+ **특징**:
134
+ - 자동 완성 및 클리어 버튼 지원
135
+ - autoFocus 옵션으로 자동 포커스
136
+ - 최소 너비 100px 보장
137
+
138
+ ### 2. SELECT - 단일 선택
139
+
140
+ ```typescript
141
+ {
142
+ name: "category",
143
+ type: SearchParamType.SELECT,
144
+ label: "카테고리",
145
+ width: 150,
146
+ options: [
147
+ { label: "전체", value: "" },
148
+ { label: "공지사항", value: "notice" },
149
+ { label: "FAQ", value: "faq" }
150
+ ],
151
+ showSearch: true,
152
+ allowClear: true,
153
+ defaultValue: ""
154
+ }
155
+ ```
156
+
157
+ **특징**:
158
+ - showSearch로 검색 기능 활성화
159
+ - 동적 로딩 상태 지원
160
+ - 기본값 설정 가능
161
+
162
+ ### 3. SELECT_MULTI - 다중 선택
163
+
164
+ ```typescript
165
+ {
166
+ name: "tags",
167
+ type: SearchParamType.SELECT_MULTI,
168
+ label: "태그",
169
+ options: [
170
+ { label: "긴급", value: "urgent" },
171
+ { label: "중요", value: "important" },
172
+ { label: "일반", value: "normal" }
173
+ ],
174
+ config: {
175
+ maxTagCount: "responsive",
176
+ mode: "multiple"
177
+ }
178
+ }
179
+ ```
180
+
181
+ **특징**:
182
+ - 반응형 태그 표시
183
+ - 커스텀 설정 지원
184
+
185
+ ### 4. DATE_RANGE - 날짜 범위
186
+
187
+ ```typescript
188
+ {
189
+ name: "dateRange",
190
+ type: SearchParamType.DATE_RANGE,
191
+ label: "기간",
192
+ placeholder: ["시작일", "종료일"],
193
+ picker: "date" as DateType,
194
+ allowClear: true
195
+ }
196
+ ```
197
+
198
+ **특징**:
199
+ - 빠른 선택 버튼 (오늘, 3일, 7일)
200
+ - 월/분기별 선택 지원
201
+ - 커스텀 포맷 설정
202
+
203
+ ### 5. CHECKBOX - 체크박스 그룹
204
+
205
+ ```typescript
206
+ {
207
+ name: "permissions",
208
+ type: SearchParamType.CHECKBOX,
209
+ label: "권한",
210
+ options: [
211
+ { label: "읽기", value: "read" },
212
+ { label: "쓰기", value: "write" },
213
+ { label: "삭제", value: "delete" }
214
+ ],
215
+ checkAllItem: true
216
+ }
217
+ ```
218
+
219
+ **특징**:
220
+ - 전체 선택/해제 기능
221
+ - indeterminate 상태 지원
222
+
223
+ ### 6. RADIO - 라디오 버튼
224
+
225
+ ```typescript
226
+ {
227
+ name: "status",
228
+ type: SearchParamType.RADIO,
229
+ label: "상태",
230
+ options: [
231
+ { label: "전체", value: "" },
232
+ { label: "활성", value: "Y" },
233
+ { label: "비활성", value: "N" }
234
+ ],
235
+ defaultValue: ""
236
+ }
237
+ ```
238
+
239
+ **특징**:
240
+ - 단일 선택만 가능
241
+ - 기본값 설정 지원
242
+
243
+ ### 7. VALUES_FINDER - 값 찾기
244
+
245
+ ```typescript
246
+ {
247
+ name: "userIds",
248
+ type: SearchParamType.VALUES_FINDER,
249
+ label: "사용자",
250
+ placeholder: "사용자를 선택하세요",
251
+ width: 250,
252
+ onSearch: async () => {
253
+ // API 호출로 사용자 목록 조회
254
+ const response = await UserService.getUsers();
255
+ return response.data.map(user => ({
256
+ label: user.name,
257
+ value: user.id
258
+ }));
259
+ },
260
+ config: {
261
+ single: false // 다중 선택 허용
262
+ }
263
+ }
264
+ ```
265
+
266
+ **특징**:
267
+ - 동적 데이터 로딩
268
+ - 검색 버튼 내장
269
+ - 단일/다중 선택 지원
270
+
271
+ ### 8. BUTTON - 일반 버튼
272
+
273
+ ```typescript
274
+ {
275
+ type: SearchParamType.BUTTON,
276
+ label: "초기화",
277
+ icon: <ReloadOutlined />,
278
+ onClick: () => {
279
+ form.resetFields();
280
+ setParamsValue({});
281
+ }
282
+ }
283
+ ```
284
+
285
+ ### 9. SUBMIT_BUTTON - 제출 버튼
286
+
287
+ ```typescript
288
+ {
289
+ type: SearchParamType.SUBMIT_BUTTON,
290
+ label: "검색",
291
+ icon: <SearchOutlined />
292
+ }
293
+ ```
294
+
295
+ ### 10. LINE_BREAK - 줄 바꿈
296
+
297
+ ```typescript
298
+ { type: SearchParamType.LINE_BREAK }
299
+ ```
300
+
301
+ ## 고급 기능
302
+
303
+ ### 1. 그룹핑 (GROUP)
304
+
305
+ ```typescript
306
+ {
307
+ type: SearchParamType.GROUP,
308
+ children: [
309
+ {
310
+ name: "minPrice",
311
+ type: SearchParamType.INPUT,
312
+ placeholder: "최소 금액"
313
+ },
314
+ {
315
+ name: "maxPrice",
316
+ type: SearchParamType.INPUT,
317
+ placeholder: "최대 금액"
318
+ }
319
+ ]
320
+ }
321
+ ```
322
+
323
+ ### 2. 조건부 표시
324
+
325
+ ```typescript
326
+ {
327
+ name: "advancedOption",
328
+ type: SearchParamType.SELECT,
329
+ label: "고급 옵션",
330
+ hidden: !showAdvanced, // 동적으로 숨김/표시
331
+ options: advancedOptions
332
+ }
333
+ ```
334
+
335
+ ### 3. 커스텀 스타일링
336
+
337
+ ```typescript
338
+ {
339
+ name: "customField",
340
+ type: SearchParamType.INPUT,
341
+ label: "커스텀 필드",
342
+ style: {
343
+ backgroundColor: "#f5f5f5",
344
+ borderRadius: "8px"
345
+ }
346
+ }
347
+ ```
348
+
349
+ ### 4. 동적 옵션 로딩
350
+
351
+ ```typescript
352
+ const [categoryOptions, setCategoryOptions] = useState([]);
353
+
354
+ useEffect(() => {
355
+ const loadCategories = async () => {
356
+ const categories = await CategoryService.getAll();
357
+ setCategoryOptions(categories.map(cat => ({
358
+ label: cat.name,
359
+ value: cat.id
360
+ })));
361
+ };
362
+ loadCategories();
363
+ }, []);
364
+
365
+ const params: IParam[] = [
366
+ {
367
+ name: "categoryId",
368
+ type: SearchParamType.SELECT,
369
+ label: "카테고리",
370
+ options: categoryOptions,
371
+ loading: categoryOptions.length === 0
372
+ }
373
+ ];
374
+ ```
375
+
376
+ ## 스타일링
377
+
378
+ ### 1. 기본 Props로 스타일링
379
+
380
+ ```typescript
381
+ <SearchParams
382
+ form={form}
383
+ params={params}
384
+ paramsValue={paramsValue}
385
+ onChangeParamsValue={setParamsValue}
386
+ onSearch={handleSearch}
387
+ size="small" // 크기: small, middle, large
388
+ variant="filled" // 스타일: filled, outlined, borderless
389
+ labelMinWidth={100} // 라벨 최소 너비
390
+ align="flex-start" // 정렬: flex-start, center, flex-end
391
+ style={{ // 커스텀 스타일
392
+ background: "#fafafa",
393
+ padding: "16px",
394
+ borderRadius: "8px"
395
+ }}
396
+ />
397
+ ```
398
+
399
+ ### 2. 추가 버튼 영역
400
+
401
+ ```typescript
402
+ const ExtraButtons = () => (
403
+ <>
404
+ <Button type="default" onClick={handleReset}>
405
+ 초기화
406
+ </Button>
407
+ <Button type="primary" onClick={handleExport}>
408
+ 내보내기
409
+ </Button>
410
+ </>
411
+ );
412
+
413
+ <SearchParams
414
+ // ... other props
415
+ extraButtons={ExtraButtons}
416
+ />
417
+ ```
418
+
419
+ ## 실제 사용 예제
420
+
421
+ ### 1. 사용자 관리 검색폼
422
+
423
+ ```typescript
424
+ import React, { useState } from 'react';
425
+ import { Form, Button } from 'antd';
426
+ import { SearchParams, IParam, SearchParamType } from '@core/components/search';
427
+ import { UserService } from 'services';
428
+
429
+ export function UserSearchForm() {
430
+ const [form] = Form.useForm();
431
+ const [paramsValue, setParamsValue] = useState({});
432
+ const [loading, setLoading] = useState(false);
433
+
434
+ const searchParams: IParam[] = [
435
+ {
436
+ name: "searchType",
437
+ type: SearchParamType.SELECT,
438
+ label: "검색 구분",
439
+ width: 120,
440
+ options: [
441
+ { label: "통합회원ID", value: "UNITY_MBER_USR_LOGIN_ID" },
442
+ { label: "기존회원ID", value: "USR_LOGIN_ID" },
443
+ { label: "전화번호", value: "USR_TELNO" },
444
+ { label: "핸드폰번호", value: "USR_HP_NO" }
445
+ ],
446
+ showSearch: false,
447
+ allowClear: false,
448
+ defaultValue: "UNITY_MBER_USR_LOGIN_ID"
449
+ },
450
+ {
451
+ name: "keyword",
452
+ type: SearchParamType.INPUT,
453
+ placeholder: "검색어를 입력하세요",
454
+ width: 200,
455
+ autoFocus: true
456
+ },
457
+ {
458
+ name: "userStatus",
459
+ type: SearchParamType.SELECT_MULTI,
460
+ label: "회원상태",
461
+ options: [
462
+ { label: "활성", value: "Y" },
463
+ { label: "비활성", value: "N" },
464
+ { label: "탈퇴", value: "W" }
465
+ ],
466
+ config: {
467
+ maxTagCount: "responsive"
468
+ }
469
+ },
470
+ { type: SearchParamType.LINE_BREAK },
471
+ {
472
+ name: "joinDateRange",
473
+ type: SearchParamType.DATE_RANGE,
474
+ label: "가입 기간",
475
+ placeholder: ["시작일", "종료일"]
476
+ },
477
+ {
478
+ name: "loginYn",
479
+ type: SearchParamType.RADIO,
480
+ label: "로그인 여부",
481
+ options: [
482
+ { label: "전체", value: "" },
483
+ { label: "로그인", value: "Y" },
484
+ { label: "미로그인", value: "N" }
485
+ ],
486
+ defaultValue: ""
487
+ }
488
+ ];
489
+
490
+ const handleSearch = async () => {
491
+ setLoading(true);
492
+ try {
493
+ const result = await UserService.searchUsers(paramsValue);
494
+ console.log('검색 결과:', result);
495
+ } catch (error) {
496
+ console.error('검색 실패:', error);
497
+ } finally {
498
+ setLoading(false);
499
+ }
500
+ };
501
+
502
+ const handleReset = () => {
503
+ form.resetFields();
504
+ setParamsValue({});
505
+ };
506
+
507
+ const ExtraButtons = () => (
508
+ <>
509
+ <Button onClick={handleReset}>초기화</Button>
510
+ <Button type="primary" onClick={handleSearch} loading={loading}>
511
+ 검색
512
+ </Button>
513
+ </>
514
+ );
515
+
516
+ return (
517
+ <SearchParams
518
+ form={form}
519
+ params={searchParams}
520
+ paramsValue={paramsValue}
521
+ onChangeParamsValue={setParamsValue}
522
+ onSearch={handleSearch}
523
+ spinning={loading}
524
+ size="middle"
525
+ extraButtons={ExtraButtons}
526
+ style={{
527
+ background: "#fff",
528
+ padding: "20px",
529
+ borderRadius: "8px",
530
+ marginBottom: "16px"
531
+ }}
532
+ />
533
+ );
534
+ }
535
+ ```
536
+
537
+ ### 2. 주문 관리 검색폼
538
+
539
+ ```typescript
540
+ export function OrderSearchForm() {
541
+ const [form] = Form.useForm();
542
+ const [paramsValue, setParamsValue] = useState({});
543
+
544
+ const searchParams: IParam[] = [
545
+ {
546
+ name: "orderNo",
547
+ type: SearchParamType.INPUT,
548
+ label: "주문번호",
549
+ placeholder: "주문번호 입력",
550
+ width: 150
551
+ },
552
+ {
553
+ name: "orderStatus",
554
+ type: SearchParamType.CHECKBOX,
555
+ label: "주문상태",
556
+ options: [
557
+ { label: "접수", value: "ORDER" },
558
+ { label: "결제완료", value: "PAID" },
559
+ { label: "배송중", value: "SHIPPING" },
560
+ { label: "완료", value: "COMPLETED" },
561
+ { label: "취소", value: "CANCELLED" }
562
+ ],
563
+ checkAllItem: true
564
+ },
565
+ {
566
+ name: "customerFinder",
567
+ type: SearchParamType.VALUES_FINDER,
568
+ label: "고객",
569
+ placeholder: "고객을 검색하세요",
570
+ width: 250,
571
+ onSearch: async () => {
572
+ const customers = await CustomerService.searchCustomers();
573
+ return customers.map(customer => ({
574
+ label: `${customer.name} (${customer.email})`,
575
+ value: customer.id
576
+ }));
577
+ }
578
+ },
579
+ { type: SearchParamType.LINE_BREAK },
580
+ {
581
+ type: SearchParamType.GROUP,
582
+ children: [
583
+ {
584
+ name: "minAmount",
585
+ type: SearchParamType.INPUT,
586
+ placeholder: "최소 금액",
587
+ width: 100
588
+ },
589
+ {
590
+ name: "maxAmount",
591
+ type: SearchParamType.INPUT,
592
+ placeholder: "최대 금액",
593
+ width: 100
594
+ }
595
+ ]
596
+ },
597
+ {
598
+ name: "orderDateRange",
599
+ type: SearchParamType.DTPICKER_DATE_RANGE,
600
+ label: "주문일",
601
+ format: "YYYY-MM-DD",
602
+ isTimeSelector: false
603
+ }
604
+ ];
605
+
606
+ return (
607
+ <SearchParams
608
+ form={form}
609
+ params={searchParams}
610
+ paramsValue={paramsValue}
611
+ onChangeParamsValue={setParamsValue}
612
+ onSearch={() => console.log('주문 검색:', paramsValue)}
613
+ labelMinWidth={80}
614
+ size="small"
615
+ />
616
+ );
617
+ }
618
+ ```
619
+
620
+ ### 3. 커스텀 검색 컴포넌트 확장
621
+
622
+ ```typescript
623
+ // 커스텀 검색 파라미터 컴포넌트
624
+ export const CustomSearchParam: SearchParamComponent = ({
625
+ name,
626
+ label,
627
+ options,
628
+ width,
629
+ style
630
+ }) => {
631
+ return (
632
+ <Form.Item
633
+ name={name}
634
+ label={label}
635
+ style={{ marginBottom: 0, ...style }}
636
+ >
637
+ <CustomComponent
638
+ options={options}
639
+ style={{ width }}
640
+ />
641
+ </Form.Item>
642
+ );
643
+ };
644
+
645
+ // SearchParam enum에 추가
646
+ export enum SearchParamType {
647
+ // ... 기존 타입들
648
+ CUSTOM = 'CUSTOM'
649
+ }
650
+
651
+ // SearchParamComponents에 추가
652
+ const SearchParamComponents = {
653
+ // ... 기존 컴포넌트들
654
+ [SearchParamType.CUSTOM]: CustomSearchParam
655
+ };
656
+ ```
657
+
658
+ ## 성능 최적화 팁
659
+
660
+ ### 1. 검색 디바운스
661
+
662
+ SearchParams는 기본적으로 100ms debounce를 적용합니다:
663
+
664
+ ```typescript
665
+ const onValuesChange = React.useMemo(
666
+ () => debounce((changedValues: any, values: Record<string, any>) => {
667
+ onChangeParamsValue?.(values, changedValues);
668
+ }, 100),
669
+ [onChangeParamsValue]
670
+ );
671
+ ```
672
+
673
+ ### 2. 옵션 메모이제이션
674
+
675
+ ```typescript
676
+ const categoryOptions = useMemo(() =>
677
+ categories.map(cat => ({
678
+ label: cat.name,
679
+ value: cat.id
680
+ })),
681
+ [categories]
682
+ );
683
+ ```
684
+
685
+ ### 3. 조건부 렌더링
686
+
687
+ ```typescript
688
+ const params = useMemo(() => [
689
+ {
690
+ name: "basicField",
691
+ type: SearchParamType.INPUT,
692
+ label: "기본 필드"
693
+ },
694
+ ...(showAdvanced ? [
695
+ {
696
+ name: "advancedField",
697
+ type: SearchParamType.SELECT,
698
+ label: "고급 필드",
699
+ options: advancedOptions
700
+ }
701
+ ] : [])
702
+ ], [showAdvanced, advancedOptions]);
703
+ ```
704
+
705
+ ## 에러 처리
706
+
707
+ ### 1. 폼 검증
708
+
709
+ ```typescript
710
+ const handleSearch = async () => {
711
+ try {
712
+ await form.validateFields();
713
+ const values = form.getFieldsValue();
714
+ // 검색 실행
715
+ } catch (errorInfo) {
716
+ console.log('검증 실패:', errorInfo);
717
+ }
718
+ };
719
+ ```
720
+
721
+ ### 2. API 에러 처리
722
+
723
+ ```typescript
724
+ const handleSearch = async () => {
725
+ try {
726
+ setLoading(true);
727
+ const result = await SearchService.search(paramsValue);
728
+ setSearchResults(result.data);
729
+ } catch (error) {
730
+ message.error('검색 중 오류가 발생했습니다.');
731
+ console.error('Search error:', error);
732
+ } finally {
733
+ setLoading(false);
734
+ }
735
+ };
736
+ ```
737
+
738
+ 이 가이드를 통해 AXBoot Search 컴포넌트 시스템을 효과적으로 활용하여 다양한 검색 인터페이스를 구현할 수 있습니다.