사람함께에이전트▾
사람 — 직접 정하고 책임지는 비즈니스 규칙과 흐름. 직접 읽어보세요.
함께 — 개념은 알아두고, 세부 규칙은 에이전트가 따릅니다.
에이전트 — 에이전트가 따르는 규칙과 레퍼런스. 필요할 때 찾아보세요.
앱 & 라이브러리▾
도메인▾
스칼라▾
Scalar.Template.tsx
스칼라 Template은 상위 모델의 폼 안에서 스칼라 값 하나를 편집하는 작은 폼 조각입니다. 여러 모델이 같은 값을 가질 때 만듭니다. 예를 들어 Product, Order, Invoice가 모두
Price.Template을 재사용할 수 있습니다.이 파일은 값을 편집하는 일만 합니다. 초안을 읽고, 저장하고, 폼을 제출하는 일은 다른 곳이 맡습니다:
할 일
스칼라
Price.Template
상위 폼
Product.Template
편집 셸
Load.Edit
값 편집
Field.*
✓
스칼라 필드마다 컨트롤을 하나씩 그리고, 라벨은 스칼라 dictionary에서 가져옵니다.
new cnst.Price().set(value)
✓
바뀐 값을 새로 만들어
onChange로 넘깁니다.값 보관과 저장
st.use.productForm()
✓
상위 폼의 초안을 읽습니다. price는 그 안의 필드 하나입니다.
st.do.setPriceOnProduct
✓
바뀐 price 전체를 그 초안에 다시 씁니다.
불러오기 · 열기 · 제출
✓
Load.Edit 같은 편집 셸이 상위 Template을 감싸서 맡습니다.✓여기서 합니다여기서 하지 않습니다
이 페이지에서 쓰는 말
용어설명
다른 모델 안에 저장되는 작은 값 객체입니다.
amount와 currency를 가진 Price가 그 예입니다.상위 폼
스칼라를 필드로 가진 모델의 Template입니다. 예를 들면
Product.Template입니다.<model>Form
store가 들고 있는, 편집 중인 레코드의 초안입니다. 예를 들면
productForm입니다.st.do.set<Field>On<Model>
store가 필드마다 자동으로 만드는 setter입니다. 예를 들면
setPriceOnProduct입니다.파일 위치와 모양
Template은
lib/__scalar/ 아래 스칼라 자신의 폴더에 둡니다. 값을 정의하는 constant, 라벨을 담은 dictionary와 나란히 놓입니다:apps/koyo
경로
apps/<app>/lib/__scalar/<scalar>/<Scalar>.Template.tsx스칼라 자신의 폴더에, constant 파일 옆에 둡니다.
첫 줄
"use client";언제나 씁니다. 필드의 입력 이벤트 처리는 브라우저에서만 실행되기 때문입니다.
export
General이름 있는 화살표 함수 컴포넌트이고, 각각
value와 onChange를 받습니다.쓰는 모양
<Price.Template.General value={…} onChange={…} />상위 폼은
@apps/<app>/client에서 Price를 가져옵니다.- 스칼라의 UI 파일은 많아야 두 개입니다.
<Scalar>.Template.tsx는 값을 편집하고<Scalar>.Unit.tsx는 값을 보여 줍니다. 스칼라 폴더에는 Zone, View, Util이 없습니다. - 파일 이름은 폴더 이름을 따릅니다.
price/폴더에는 첫 글자만 대문자로 바꾼Price.Template.tsx를 둡니다.
스칼라 Template 예시
스칼라 Template은
value와 onChange를 받아 그 값만 편집합니다. 데이터를 불러오지 않고, 상위 폼을 제출하지도 않습니다:apps/koyo/lib/__scalar/price/Price.Template.tsx
value로 받고onChange로 돌려줍니다. 값의 주인은 상위 폼이므로 Template에는useState가 없습니다.patch는Price전체를 돌려줍니다.value를 복사하고, 바뀐 필드 하나만 적용한 결과를onChange에 넘깁니다.- 라벨은 스칼라의 dictionary에서 가져옵니다.
l("price.amount")는 같은 폴더의price.dictionary.ts를 읽습니다. - 안쪽 필드는 에이전트 툴이 되지 않습니다.
patch는 클로저라서data-akan-action이 붙지 않습니다. 에이전트는 대신 상위 폼의fillProductForm으로 price를 채웁니다.


스칼라는
{...value}가 아니라 new cnst.Price().set(value)로 복사합니다. 모델 인스턴스는 Date 필드를 prototype accessor 뒤에 두므로, spread와 Object.keys 모두 그 필드를 빠뜨립니다. 그러면 복사본은 아무 경고 없이 날짜를 전부 잃습니다.상위 폼에서 쓰기
상위 Template은 store로 움직이는 평범한 폼 그대로입니다. 안에 든 스칼라 값을 스칼라 Template에 넘기고, 돌아온 값은 자동 생성된 setter로 저장합니다:
apps/koyo/lib/product/Product.Template.tsx
productForm.price가 넘겨줄 값입니다. price는 상위 폼 초안 안에 필드 하나로 들어 있습니다.st.do.setPriceOnProduct는 새Price전체를 받습니다. store는 스칼라 필드를 포함한 모든 필드에 setter를 만들어 둡니다.Price는@apps/koyo/client에서 가져옵니다.st,usePage와 같은 import 한 줄입니다.


자동 생성 setter는 참조로 넘깁니다.
onChange={(v) => st.do.setNameOnProduct(v)} 같은 인라인 화살표 함수는 똑같이 동작하지만 data-akan-action을 내보내지 않아, 그 필드는 에이전트 툴도 E2E selector도 되지 못하고 lint 규칙 no-unpublished-form-setter에도 걸립니다. 위의 patch처럼 값을 실제로 바꾸는 wrapper는 그대로 허용됩니다.Field 또는 직접 만든 UI
스칼라 필드에는 언제나
Field.* 컨트롤을 쓰고, <input>을 직접 쓰지 않습니다. Field가 라벨과 검증을, store setter를 받으면 data-akan-action 속성까지 붙여 주기 때문입니다. 컨트롤은 값의 모양에 따라 고릅니다:| 스칼라 | 컨트롤 |
|---|---|
| ↳ 참고 | |
Price | Field.Number · Field.Text |
| 위 예시처럼 평범한 숫자 필드와 텍스트 필드입니다. | |
Address | Field.Text · Field.Postcode |
텍스트 필드를 쓰거나, 좌표까지 함께 돌려주는 카카오 주소 검색 Postcode를 씁니다. | |
Coordinate | Field.Coordinate |
@libs/shared/ui에 있는 지도 선택기로, 지도를 클릭한 곳이 좌표가 됩니다. | |
| 그 밖의 값 | <YourComponent> |
value와 onChange를 받는 앱 전용 컴포넌트를 만들고, 필요하면 akanjs/ui의 Input을 씁니다. | |
맞는 Field가 없으면
value와 onChange를 같은 방식으로 받는 앱 전용 컴포넌트를 만듭니다. 그러면 스칼라 Template에서 Field처럼 쓸 수 있습니다.자주 하는 실수
- spread로 복사하기.
{...value}는Date필드를 모두 빠뜨립니다. 복사본은new cnst.Price().set(value)로 만듭니다. - 값을
useState에 두기. 값은 이미 상위 폼의 초안에 있고, Template은 바뀐 값을 넘겨주기만 합니다. - 스칼라 Template 안에서 불러오거나 저장하기. 서버 호출은 store 액션에 두고, 폼 제출은 상위 폼을 감싼 편집 셸이 합니다.
- 상위 폼의 setter를 화살표 함수로 감싸기.
st.do.setPriceOnProduct를 그대로 넘깁니다.
이어서 읽기