diff --git a/frontend/app/test-autocomplete-mapping/page.tsx b/frontend/app/test-autocomplete-mapping/page.tsx new file mode 100644 index 00000000..234c75f6 --- /dev/null +++ b/frontend/app/test-autocomplete-mapping/page.tsx @@ -0,0 +1,141 @@ +"use client"; + +import React, { useState } from "react"; +import { AutocompleteSearchInputComponent } from "@/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputComponent"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Label } from "@/components/ui/label"; +import { Input } from "@/components/ui/input"; + +export default function TestAutocompleteMapping() { + const [selectedValue, setSelectedValue] = useState(""); + const [customerName, setCustomerName] = useState(""); + const [address, setAddress] = useState(""); + const [phone, setPhone] = useState(""); + + return ( +
+ + + AutocompleteSearchInput 필드 자동 매핑 테스트 + + 거래처를 선택하면 아래 입력 필드들이 자동으로 채워집니다 + + + + {/* 검색 컴포넌트 */} +
+ + { + setSelectedValue(value); + console.log("선택된 항목:", fullData); + }} + /> +
+ + {/* 구분선 */} +
+

+ 자동으로 채워지는 필드들 +

+
+ {/* 거래처명 */} +
+ + setCustomerName(e.target.value)} + placeholder="자동으로 채워집니다" + /> +
+ + {/* 주소 */} +
+ + setAddress(e.target.value)} + placeholder="자동으로 채워집니다" + /> +
+ + {/* 전화번호 */} +
+ + setPhone(e.target.value)} + placeholder="자동으로 채워집니다" + /> +
+
+
+ + {/* 상태 표시 */} +
+

현재 상태

+
+
+                {JSON.stringify(
+                  {
+                    selectedValue,
+                    customerName,
+                    address,
+                    phone,
+                  },
+                  null,
+                  2
+                )}
+              
+
+
+
+
+ + {/* 사용 안내 */} + + + 사용 방법 + + +
    +
  1. 위의 검색 필드에 거래처명이나 코드를 입력하세요
  2. +
  3. 드롭다운에서 원하는 거래처를 선택하세요
  4. +
  5. 아래 입력 필드들이 자동으로 채워지는 것을 확인하세요
  6. +
  7. 필요한 경우 자동으로 채워진 값을 수정할 수 있습니다
  8. +
+
+
+
+ ); +} + diff --git a/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputComponent.tsx b/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputComponent.tsx index 0bb78db2..42baabdc 100644 --- a/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputComponent.tsx +++ b/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputComponent.tsx @@ -7,7 +7,7 @@ import { Button } from "@/components/ui/button"; import { useEntitySearch } from "../entity-search-input/useEntitySearch"; import { EntitySearchResult } from "../entity-search-input/types"; import { cn } from "@/lib/utils"; -import { AutocompleteSearchInputConfig } from "./types"; +import { AutocompleteSearchInputConfig, FieldMapping } from "./types"; interface AutocompleteSearchInputProps extends Partial { config?: AutocompleteSearchInputConfig; @@ -81,10 +81,46 @@ export function AutocompleteSearchInputComponent({ setIsOpen(true); }; + // 필드 자동 매핑 처리 + const applyFieldMappings = (item: EntitySearchResult) => { + if (!config?.enableFieldMapping || !config?.fieldMappings) { + return; + } + + config.fieldMappings.forEach((mapping: FieldMapping) => { + if (!mapping.sourceField || !mapping.targetField) { + return; + } + + const value = item[mapping.sourceField]; + + // DOM에서 타겟 필드 찾기 (id로 검색) + const targetElement = document.getElementById(mapping.targetField); + + if (targetElement) { + // input, textarea 등의 값 설정 + if ( + targetElement instanceof HTMLInputElement || + targetElement instanceof HTMLTextAreaElement + ) { + targetElement.value = value?.toString() || ""; + + // React의 change 이벤트 트리거 + const event = new Event("input", { bubbles: true }); + targetElement.dispatchEvent(event); + } + } + }); + }; + const handleSelect = (item: EntitySearchResult) => { setSelectedData(item); setInputValue(item[displayField] || ""); onChange?.(item[valueField], item); + + // 필드 자동 매핑 실행 + applyFieldMappings(item); + setIsOpen(false); }; diff --git a/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputConfigPanel.tsx b/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputConfigPanel.tsx index dadcdb3c..96a212b1 100644 --- a/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputConfigPanel.tsx +++ b/frontend/lib/registry/components/autocomplete-search-input/AutocompleteSearchInputConfigPanel.tsx @@ -9,7 +9,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover import { Switch } from "@/components/ui/switch"; import { Button } from "@/components/ui/button"; import { Plus, X, Check, ChevronsUpDown } from "lucide-react"; -import { AutocompleteSearchInputConfig } from "./types"; +import { AutocompleteSearchInputConfig, FieldMapping, ValueFieldStorage } from "./types"; import { tableManagementApi } from "@/lib/api/tableManagement"; import { cn } from "@/lib/utils"; @@ -30,6 +30,10 @@ export function AutocompleteSearchInputConfigPanel({ const [openTableCombo, setOpenTableCombo] = useState(false); const [openDisplayFieldCombo, setOpenDisplayFieldCombo] = useState(false); const [openValueFieldCombo, setOpenValueFieldCombo] = useState(false); + const [openStorageTableCombo, setOpenStorageTableCombo] = useState(false); + const [openStorageColumnCombo, setOpenStorageColumnCombo] = useState(false); + const [storageTableColumns, setStorageTableColumns] = useState([]); + const [isLoadingStorageColumns, setIsLoadingStorageColumns] = useState(false); // 전체 테이블 목록 로드 useEffect(() => { @@ -73,6 +77,31 @@ export function AutocompleteSearchInputConfigPanel({ loadColumns(); }, [localConfig.tableName]); + // 저장 대상 테이블의 컬럼 목록 로드 + useEffect(() => { + const loadStorageColumns = async () => { + const storageTable = localConfig.valueFieldStorage?.targetTable; + if (!storageTable) { + setStorageTableColumns([]); + return; + } + + setIsLoadingStorageColumns(true); + try { + const response = await tableManagementApi.getColumnList(storageTable); + if (response.success && response.data) { + setStorageTableColumns(response.data.columns); + } + } catch (error) { + console.error("저장 테이블 컬럼 로드 실패:", error); + setStorageTableColumns([]); + } finally { + setIsLoadingStorageColumns(false); + } + }; + loadStorageColumns(); + }, [localConfig.valueFieldStorage?.targetTable]); + useEffect(() => { setLocalConfig(config); }, [config]); @@ -117,6 +146,29 @@ export function AutocompleteSearchInputConfigPanel({ updateConfig({ additionalFields: fields }); }; + // 필드 매핑 관리 함수 + const addFieldMapping = () => { + const mappings = localConfig.fieldMappings || []; + updateConfig({ + fieldMappings: [ + ...mappings, + { sourceField: "", targetField: "", label: "" }, + ], + }); + }; + + const updateFieldMapping = (index: number, updates: Partial) => { + const mappings = [...(localConfig.fieldMappings || [])]; + mappings[index] = { ...mappings[index], ...updates }; + updateConfig({ fieldMappings: mappings }); + }; + + const removeFieldMapping = (index: number) => { + const mappings = [...(localConfig.fieldMappings || [])]; + mappings.splice(index, 1); + updateConfig({ fieldMappings: mappings }); + }; + return (
@@ -164,6 +216,9 @@ export function AutocompleteSearchInputConfigPanel({ +

+ 검색할 데이터가 저장된 테이블을 선택하세요 +

@@ -211,6 +266,9 @@ export function AutocompleteSearchInputConfigPanel({ +

+ 사용자에게 보여줄 필드 (예: 거래처명) +

@@ -258,6 +316,9 @@ export function AutocompleteSearchInputConfigPanel({ +

+ 검색 테이블에서 가져올 값의 컬럼 (예: customer_code) +

@@ -270,6 +331,196 @@ export function AutocompleteSearchInputConfigPanel({ />
+ {/* 값 필드 저장 위치 설정 */} +
+
+

값 필드 저장 위치 (고급)

+

+ 위에서 선택한 "값 필드"의 데이터를 어느 테이블/컬럼에 저장할지 지정합니다. +
+ 미설정 시 화면의 연결 테이블에 컴포넌트의 바인딩 필드로 자동 저장됩니다. +

+
+ + {/* 저장 테이블 선택 */} +
+ + + + + + + + + + 테이블을 찾을 수 없습니다. + + {/* 기본값 옵션 */} + { + updateConfig({ + valueFieldStorage: { + ...localConfig.valueFieldStorage, + targetTable: undefined, + targetColumn: undefined, + }, + }); + setOpenStorageTableCombo(false); + }} + className="text-xs sm:text-sm" + > + +
+ 기본값 + 화면의 연결 테이블 사용 +
+
+ {allTables.map((table) => ( + { + updateConfig({ + valueFieldStorage: { + ...localConfig.valueFieldStorage, + targetTable: table.tableName, + targetColumn: undefined, // 테이블 변경 시 컬럼 초기화 + }, + }); + setOpenStorageTableCombo(false); + }} + className="text-xs sm:text-sm" + > + +
+ {table.displayName || table.tableName} + {table.displayName && {table.tableName}} +
+
+ ))} +
+
+
+
+
+

+ 값을 저장할 테이블 (기본값: 화면 연결 테이블) +

+
+ + {/* 저장 컬럼 선택 */} + {localConfig.valueFieldStorage?.targetTable && ( +
+ + + + + + + + + + 컬럼을 찾을 수 없습니다. + + {storageTableColumns.map((column) => ( + { + updateConfig({ + valueFieldStorage: { + ...localConfig.valueFieldStorage, + targetColumn: column.columnName, + }, + }); + setOpenStorageColumnCombo(false); + }} + className="text-xs sm:text-sm" + > + +
+ {column.displayName || column.columnName} + {column.displayName && {column.columnName}} +
+
+ ))} +
+
+
+
+
+

+ 값을 저장할 컬럼명 +

+
+ )} + + {/* 설명 박스 */} +
+

+ 저장 위치 동작 +

+
+ {localConfig.valueFieldStorage?.targetTable ? ( + <> +

+ 선택한 값({localConfig.valueField})을 +

+

+ + {localConfig.valueFieldStorage.targetTable} + {" "} + 테이블의{" "} + + {localConfig.valueFieldStorage.targetColumn || "(컬럼 미지정)"} + {" "} + 컬럼에 저장합니다. +

+ + ) : ( +

기본값: 화면의 연결 테이블에 컴포넌트의 바인딩 필드로 저장됩니다.

+ )} +
+
+
+
@@ -375,6 +626,175 @@ export function AutocompleteSearchInputConfigPanel({
)} + + {/* 필드 자동 매핑 설정 */} +
+
+

필드 자동 매핑

+

+ 선택한 항목의 필드를 화면의 다른 입력 필드에 자동으로 채워넣습니다 +

+
+ +
+
+ + + updateConfig({ enableFieldMapping: checked }) + } + /> +
+

+ 활성화하면 항목 선택 시 설정된 필드들이 자동으로 채워집니다 +

+
+ + {localConfig.enableFieldMapping && ( +
+
+ + +
+ +
+ {(localConfig.fieldMappings || []).map((mapping, index) => ( +
+
+ + 매핑 #{index + 1} + + +
+ + {/* 표시명 */} +
+ + + updateFieldMapping(index, { label: e.target.value }) + } + placeholder="예: 거래처명" + className="h-8 text-xs sm:h-10 sm:text-sm" + /> +

+ 이 매핑의 설명 (선택사항) +

+
+ + {/* 소스 필드 (테이블의 컬럼) */} +
+ + +

+ 가져올 데이터의 컬럼명 +

+
+ + {/* 타겟 필드 (화면의 input ID) */} +
+ + + updateFieldMapping(index, { targetField: e.target.value }) + } + placeholder="예: customer_name_input" + className="h-8 text-xs sm:h-10 sm:text-sm" + /> +

+ 값을 채울 화면 컴포넌트의 ID (예: input의 id 속성) +

+
+ + {/* 예시 설명 */} +
+

+ {mapping.sourceField && mapping.targetField ? ( + <> + {mapping.label || "이 필드"}: 테이블의{" "} + + {mapping.sourceField} + {" "} + 값을 화면의{" "} + + {mapping.targetField} + {" "} + 컴포넌트에 자동으로 채웁니다 + + ) : ( + "소스 필드와 타겟 필드를 모두 선택하세요" + )} +

+
+
+ ))} +
+ + {/* 사용 안내 */} + {localConfig.fieldMappings && localConfig.fieldMappings.length > 0 && ( +
+

+ 사용 방법 +

+
    +
  • 화면에서 이 검색 컴포넌트로 항목을 선택하면
  • +
  • 설정된 매핑에 따라 다른 입력 필드들이 자동으로 채워집니다
  • +
  • 타겟 필드 ID는 화면 디자이너에서 설정한 컴포넌트 ID와 일치해야 합니다
  • +
+
+ )} +
+ )} +
); } diff --git a/frontend/lib/registry/components/autocomplete-search-input/README.md b/frontend/lib/registry/components/autocomplete-search-input/README.md index 3018d5c6..688d0c3a 100644 --- a/frontend/lib/registry/components/autocomplete-search-input/README.md +++ b/frontend/lib/registry/components/autocomplete-search-input/README.md @@ -9,9 +9,12 @@ - 추가 정보 표시 가능 - X 버튼으로 선택 초기화 - 외부 클릭 시 자동 닫힘 +- **필드 자동 매핑**: 선택한 항목의 값을 화면의 다른 입력 필드에 자동으로 채움 ## 사용 예시 +### 기본 사용 + ```tsx ``` +### 필드 자동 매핑 사용 + +```tsx + { + console.log("선택됨:", code, fullData); + // 필드 매핑은 자동으로 실행됩니다 + }} +/> + + + + + +``` + ## 설정 옵션 +### 기본 설정 + - `tableName`: 검색할 테이블명 - `displayField`: 표시할 필드 - `valueField`: 값으로 사용할 필드 @@ -38,3 +84,31 @@ - `showAdditionalInfo`: 추가 정보 표시 여부 - `additionalFields`: 추가로 표시할 필드들 +### 값 필드 저장 위치 설정 (고급) + +- `valueFieldStorage`: 값 필드 저장 위치 지정 + - `targetTable`: 저장할 테이블명 (미설정 시 화면 연결 테이블) + - `targetColumn`: 저장할 컬럼명 (미설정 시 바인딩 필드) + +### 필드 자동 매핑 설정 + +- `enableFieldMapping`: 필드 자동 매핑 활성화 여부 +- `fieldMappings`: 매핑할 필드 목록 + - `sourceField`: 소스 테이블의 컬럼명 (예: customer_name) + - `targetField`: 타겟 필드 ID (예: 화면의 input id 속성) + - `label`: 표시명 (선택사항) + +## 필드 자동 매핑 동작 방식 + +1. 사용자가 검색 컴포넌트에서 항목을 선택합니다 +2. 선택된 항목의 데이터에서 `sourceField`에 해당하는 값을 가져옵니다 +3. 화면에서 `targetField` ID를 가진 컴포넌트를 찾습니다 +4. 해당 컴포넌트에 값을 자동으로 채워넣습니다 +5. React의 change 이벤트를 트리거하여 상태 업데이트를 유발합니다 + +## 주의사항 + +- 타겟 필드 ID는 화면 디자이너에서 설정한 컴포넌트 ID와 정확히 일치해야 합니다 +- 필드 매핑은 input, textarea 타입의 요소에만 동작합니다 +- 여러 필드를 한 번에 매핑할 수 있습니다 + diff --git a/frontend/lib/registry/components/autocomplete-search-input/types.ts b/frontend/lib/registry/components/autocomplete-search-input/types.ts index 4e006062..802f27c7 100644 --- a/frontend/lib/registry/components/autocomplete-search-input/types.ts +++ b/frontend/lib/registry/components/autocomplete-search-input/types.ts @@ -1,3 +1,18 @@ +// 값 필드 저장 설정 +export interface ValueFieldStorage { + targetTable?: string; // 저장할 테이블명 (기본값: 화면의 연결 테이블) + targetColumn?: string; // 저장할 컬럼명 (기본값: 바인딩 필드) +} + +// 필드 매핑 설정 +export interface FieldMapping { + sourceField: string; // 소스 테이블의 컬럼명 (예: customer_name) + targetField: string; // 매핑될 타겟 필드 ID (예: 화면의 input ID) + label?: string; // 표시명 + targetTable?: string; // 저장할 테이블 (선택사항, 기본값은 화면 연결 테이블) + targetColumn?: string; // 저장할 컬럼명 (선택사항, targetField가 화면 ID가 아닌 경우) +} + export interface AutocompleteSearchInputConfig { tableName: string; displayField: string; @@ -7,5 +22,10 @@ export interface AutocompleteSearchInputConfig { placeholder?: string; showAdditionalInfo?: boolean; additionalFields?: string[]; + // 값 필드 저장 위치 설정 + valueFieldStorage?: ValueFieldStorage; + // 필드 자동 매핑 설정 + enableFieldMapping?: boolean; // 필드 자동 매핑 활성화 여부 + fieldMappings?: FieldMapping[]; // 매핑할 필드 목록 } diff --git a/frontend/lib/registry/components/autocomplete-search-input/사용_가이드.md b/frontend/lib/registry/components/autocomplete-search-input/사용_가이드.md new file mode 100644 index 00000000..d8261e8f --- /dev/null +++ b/frontend/lib/registry/components/autocomplete-search-input/사용_가이드.md @@ -0,0 +1,300 @@ +# AutocompleteSearchInput 컴포넌트 사용 가이드 + +## 📌 이 컴포넌트는 무엇인가요? + +검색 가능한 드롭다운 선택 박스입니다. +거래처, 품목, 직원 등을 검색해서 선택할 때 사용합니다. + +--- + +## ⚙️ 패널 설정 방법 + +### 1. 기본 검색 설정 (필수) + +#### 테이블명 +- **의미**: 어디서 검색할 것인가? +- **예시**: `customer_mng` (거래처 테이블) + +#### 표시 필드 +- **의미**: 사용자에게 무엇을 보여줄 것인가? +- **예시**: `customer_name` → 화면에 "삼성전자" 표시 + +#### 값 필드 +- **의미**: 실제로 어떤 값을 가져올 것인가? +- **예시**: `customer_code` → "CUST-0001" 가져오기 + +#### 검색 필드 (선택) +- **의미**: 어떤 컬럼으로 검색할 것인가? +- **예시**: `customer_name`, `customer_code` 추가 +- **동작**: 이름으로도 검색, 코드로도 검색 가능 + +--- + +### 2. 값 필드 저장 위치 (고급, 선택) + +#### 저장 테이블 +- **기본값**: 화면의 연결 테이블에 자동 저장 +- **변경 시**: 다른 테이블에 저장 가능 + +#### 저장 컬럼 +- **기본값**: 컴포넌트의 바인딩 필드 +- **변경 시**: 다른 컬럼에 저장 가능 + +> 💡 **대부분은 기본값을 사용하면 됩니다!** + +--- + +## 📖 사용 예제 + +### 예제 1: 거래처 선택 (가장 일반적) + +#### 패널 설정 +``` +테이블명: customer_mng +표시 필드: customer_name +값 필드: customer_code +검색 필드: customer_name, customer_code +플레이스홀더: 거래처명 또는 코드 입력 +``` + +#### 동작 +``` +사용자 입력: "삼성" +드롭다운 표시: "삼성전자", "삼성물산", ... +선택: "삼성전자" +저장 값: "CUST-0001" (customer_code) +``` + +#### 결과 +``` +order_mng 테이블 +┌───────────┬───────────────┐ +│ order_id │ customer_code │ +├───────────┼───────────────┤ +│ ORD-0001 │ CUST-0001 │ ✅ +└───────────┴───────────────┘ +``` + +--- + +### 예제 2: 거래처명을 직접 저장 + +#### 패널 설정 +``` +테이블명: customer_mng +표시 필드: customer_name +값 필드: customer_name ← 이름을 가져옴 +플레이스홀더: 거래처명 입력 +``` + +#### 동작 +``` +사용자 선택: "삼성전자" +저장 값: "삼성전자" (customer_name) +``` + +#### 결과 +``` +order_mng 테이블 +┌───────────┬───────────────┐ +│ order_id │ customer_name │ +├───────────┼───────────────┤ +│ ORD-0001 │ 삼성전자 │ ✅ +└───────────┴───────────────┘ +``` + +--- + +### 예제 3: 품목 선택 (추가 정보 표시) + +#### 패널 설정 +``` +테이블명: item_mng +표시 필드: item_name +값 필드: item_code +검색 필드: item_name, item_code, category +플레이스홀더: 품목명, 코드, 카테고리로 검색 + +추가 정보 표시: ON +추가 필드: item_code, unit_price +``` + +#### 동작 +``` +드롭다운: +┌────────────────────────────┐ +│ 삼성 노트북 │ +│ item_code: ITEM-0123 │ +│ unit_price: 1,500,000 │ +├────────────────────────────┤ +│ LG 그램 노트북 │ +│ item_code: ITEM-0124 │ +│ unit_price: 1,800,000 │ +└────────────────────────────┘ +``` + +--- + +## 🎯 필드 선택 가이드 + +### 언제 표시 필드 ≠ 값 필드 인가? + +**대부분의 경우 (권장)** +``` +표시 필드: customer_name (이름 - 사람이 읽기 쉬움) +값 필드: customer_code (코드 - 데이터베이스에 저장) + +이유: +✅ 외래키 관계 유지 +✅ 데이터 무결성 +✅ 이름이 바뀌어도 코드는 그대로 +``` + +### 언제 표시 필드 = 값 필드 인가? + +**특수한 경우** +``` +표시 필드: customer_name +값 필드: customer_name + +사용 케이스: +- 이름 자체를 저장해야 할 때 +- 외래키가 필요 없을 때 +- 간단한 참조용 데이터 +``` + +--- + +## 💡 자주 묻는 질문 + +### Q1. 저장 위치를 설정하지 않으면? + +**A**: 자동으로 화면의 연결 테이블에 바인딩 필드로 저장됩니다. + +``` +화면: 수주 등록 (연결 테이블: order_mng) +컴포넌트 바인딩 필드: customer_code + +→ order_mng.customer_code에 자동 저장 ✅ +``` + +--- + +### Q2. 값 필드와 저장 위치의 차이는? + +**A**: +- **값 필드**: 검색 테이블에서 무엇을 가져올지 +- **저장 위치**: 가져온 값을 어디에 저장할지 + +``` +값 필드: customer_mng.customer_code (어떤 값?) +저장 위치: order_mng.customer_code (어디에?) +``` + +--- + +### Q3. 검색 필드는 왜 여러 개 추가하나요? + +**A**: 여러 방법으로 검색할 수 있게 하기 위해서입니다. + +``` +검색 필드: [customer_name, customer_code] + +사용자가 "삼성" 입력 → customer_name에서 검색 +사용자가 "CUST" 입력 → customer_code에서 검색 +``` + +--- + +### Q4. 추가 정보 표시는 언제 사용하나요? + +**A**: 선택할 때 참고할 정보를 함께 보여주고 싶을 때 사용합니다. + +``` +추가 정보 표시: ON +추가 필드: [address, phone] + +드롭다운: +┌────────────────────────────┐ +│ 삼성전자 │ +│ address: 서울시 서초구 │ +│ phone: 02-1234-5678 │ +└────────────────────────────┘ +``` + +--- + +## 🚀 빠른 시작 + +### 1단계: 기본 설정만 입력 + +``` +테이블명: [검색할 테이블] +표시 필드: [사용자에게 보여줄 컬럼] +값 필드: [저장할 컬럼] +``` + +### 2단계: 화면 디자이너에서 바인딩 필드 설정 + +``` +컴포넌트 ID: customer_search +바인딩 필드: customer_code +``` + +### 3단계: 완료! + +이제 사용자가 선택하면 자동으로 저장됩니다. + +--- + +## ✅ 체크리스트 + +설정 전: +- [ ] 어느 테이블에서 검색할지 알고 있나요? +- [ ] 사용자에게 무엇을 보여줄지 정했나요? +- [ ] 어떤 값을 저장할지 정했나요? + +설정 후: +- [ ] 검색이 정상적으로 되나요? +- [ ] 드롭다운에 원하는 항목이 보이나요? +- [ ] 선택 후 값이 저장되나요? + +--- + +## 📊 설정 패턴 비교 + +| 패턴 | 표시 필드 | 값 필드 | 사용 케이스 | +|------|----------|---------|------------| +| 1 | customer_name | customer_code | 이름 표시, 코드 저장 (일반적) | +| 2 | customer_name | customer_name | 이름 표시, 이름 저장 (특수) | +| 3 | item_name | item_code | 품목명 표시, 품목코드 저장 | +| 4 | employee_name | employee_id | 직원명 표시, ID 저장 | + +--- + +## 🎨 실전 팁 + +### 1. 검색 필드는 2-3개가 적당 +``` +✅ 좋음: [name, code] +✅ 좋음: [name, code, category] +❌ 과함: [name, code, address, phone, email, ...] +``` + +### 2. 플레이스홀더는 구체적으로 +``` +❌ "검색..." +✅ "거래처명 또는 코드 입력" +✅ "품목명, 코드, 카테고리로 검색" +``` + +### 3. 추가 정보는 선택에 도움되는 것만 +``` +✅ 도움됨: 가격, 주소, 전화번호 +❌ 불필요: 등록일, 수정일, ID +``` + +--- + +이 가이드로 autocomplete-search-input 컴포넌트를 쉽게 사용할 수 있습니다! 🎉 +