# FieldConfig / DataPort v0.1

> 작성일: 2026-04-22
> 상태: working draft
> 목적: 컴포넌트를 하나씩 만들면서도 공통 규격이 흔들리지 않게 최소 계약을 먼저 고정한다.

---

## 1. 결정 원칙

1. `FieldConfig` 는 공통 필드 규격만 가진다.
2. 컴포넌트 전용 옵션은 `TableConfig`, `FormConfig`, `SearchConfig` 로 분리한다.
3. `DataPort` 는 데이터 전달 계약만 가진다.
4. 포트 연결은 `Connection` 으로만 표현하고, 중간 변환 규칙은 넣지 않는다.
5. 먼저 `table -> search -> form` 3개를 기준 컴포넌트로 삼아 규격을 검증한다.

---

## 2. FieldConfig v0.1

### 2.1 Core

아래 7개를 코어로 본다.

```ts
column
label
type
visible
order
required
editable
```

이 7개는 `table / form / search` 모두에서 의미가 있어야 한다.

### 2.2 Common Options

아래는 공통 옵션으로 허용하지만 코어는 아니다.

```ts
width
align
defaultValue
placeholder
```

원칙:

- `width`, `align` 은 table 표시 힌트다.
- `defaultValue`, `placeholder` 는 form/search 입력 힌트다.
- 특정 컴포넌트만 강하게 의존하는 옵션은 FieldConfig 에 넣지 않는다.

### 2.3 Type Options

타입별 확장은 여기까지만 둔다.

```ts
options   // select
ref       // entity
format    // number/date/datetime
computed  // 계산식
```

원칙:

- `options` 는 select 전용이다.
- `ref` 는 entity 전용이다.
- `format` 은 표시 힌트다.
- `computed` 는 계산 규칙 정의이고, 실제 실행 엔진은 별도 책임이다.

### 2.4 Meta

아래는 메타/동작 힌트로 본다.

```ts
pk
system
searchable
sortable
```

이 필드들은 렌더링 코어라기보다 빌더/저장/런타임 힌트에 가깝다.

---

## 3. 렌더링 계약 v0.1

### table

- `visible` 이 `true` 인 필드만 컬럼 후보가 된다.
- `order` 로 기본 순서를 정한다.
- `width`, `align`, `format` 을 우선 사용한다.
- `editable` 은 인라인 편집 가능 여부 판단에 사용한다.

### form

- `visible` 이 `true` 이고 `system !== true` 인 필드가 기본 표시 대상이다.
- `required`, `editable`, `defaultValue`, `placeholder` 를 사용한다.
- `computed` 는 readonly 처리와 함께 별도 계산 엔진에서 반영한다.

### search

- 기본적으로 `searchable !== false` 인 필드만 검색 후보로 본다.
- `type` 에 따라 검색 입력 UI 를 바꾼다.
- 상세 배치 방식은 `SearchConfig` 가 가진다.

---

## 4. DataPort v0.1

### 4.1 포트 타입

```ts
row
rows
value
params
```

여기서 멈춘다. `query`, `event`, `schema` 같은 확장은 아직 넣지 않는다.

### 4.2 포트 정의

```ts
interface DataPort {
  name: string;
  type: 'row' | 'rows' | 'value' | 'params';
  connectedTo?: string;
}
```

원칙:

- 포트는 데이터 계약만 가진다.
- 포트 자체에 변환 로직을 넣지 않는다.
- 실제 연결은 `Connection[]` 에서 관리한다.

### 4.3 Connection 정의

```ts
interface Connection {
  id: string;
  from: { componentId: string; port: string };
  to: { componentId: string; port: string };
}
```

원칙:

- `from.port` 값을 `to.port` 로 그대로 전달한다.
- 중간 `mapping`, `transform`, `condition` 은 v0.1 범위에서 제외한다.
- 지금 런타임 구현도 이 단순 브리지 모델과 일치한다.

### 4.4 예약 포트 이름

기본 컴포넌트는 아래 이름을 우선 사용한다.

```ts
searchParams
refreshTrigger
selectedRow
selectedRows
loadRow
formData
savedRow
clicked
```

초기 표준 연결:

- `search.searchParams -> table.searchParams`
- `table.selectedRow -> form.loadRow`
- `form.savedRow -> table.refreshTrigger`

---

## 5. 컴포넌트별 책임 분리

### TableConfig

여기에 둔다.

- 페이지 크기
- 선택 모드
- 체크박스 표시
- 인라인 편집
- 자동 로드
- 기본 정렬
- 툴바 표시

### FormConfig

여기에 둔다.

- 컬럼 수
- 섹션 구성
- 저장 방식
- 저장 후 동작

### SearchConfig

여기에 둔다.

- 자동 검색
- 초기화 버튼
- 날짜 범위 사용
- 배치 방식

즉, `FieldConfig` 는 필드 설명이고, `*Config` 는 컴포넌트 동작 설명이다.

---

## 6. v0.1 에서 하지 않는 것

- FieldConfig 에 컴포넌트별 레이아웃 옵션 넣기
- DataPort 에 변환 규칙 넣기
- Connection 에 조건식/스크립트 넣기
- search 전용 필드 타입 따로 만들기
- form/table/search 별도 필드 규격으로 분기하기

---

## 7. 다음 순서

1. `table` 구현에서 `FieldConfig core` 소비 범위를 검증한다.
2. `search` 구현에서 `searchable`, `type -> input` 규칙을 고정한다.
3. `form` 구현에서 `required`, `editable`, `defaultValue` 계약을 고정한다.
4. 그 다음에야 `computed`, `entity.ref`, `select.options` 를 강화한다.

한 줄로 정리하면:

`FieldConfig 는 필드 공통 설명`, `DataPort 는 데이터 전달 계약`, `컴포넌트 동작은 각 config`.
