model.abstract.md

database 모듈은 모두 lib/<model>/<model>.abstract.md 파일을 하나 둡니다. 모듈이 지키고 있지만 코드로는 드러나지 않는 규칙을 몇 줄의 markdown으로 적는 곳입니다. 모듈을 고치기 전에 읽고, 그 규칙이 바뀌면 함께 고칩니다.
코드가 말하지 못하는 것
libs/shared의 user 모듈을 보면, constant 파일과 abstract가 같은 두 필드에 대해 서로 다른 것을 말합니다.
constant 파일이 보여 주는 것
accountId와 phone은 secret이고, 없어도 되는 문자열입니다.
accountId: field.secret(String).optional()
abstract만 말하는 것
두 값은 active·dormant·restricted 계정끼리는 겹칠 수 없지만, 탈퇴한 계정과는 겹쳐도 됩니다.
  • 다른 곳에는 적혀 있지 않습니다. 필드와 type 어디에도 없고, user.document.ts는 여러 메서드에서 같은 검사를 되풀이할 뿐 규칙으로 밝히지 않습니다.
  • 모르면 가입이 깨집니다. 이 규칙을 모른 채 유일성 인덱스를 추가하면, 계정을 한 번이라도 지운 사용자는 누구도 다시 가입하지 못합니다.
  • abstract가 하는 일이 바로 이것입니다. 모듈이 지키지만 코드로 말하지 못하는 불변식, 즉 항상 참이어야 하는 규칙을 담고, constant 파일이 이미 하는 말은 담지 않습니다.
네 부분
abstract는 네 부분으로 되어 있고, 마지막 부분만 선택입니다:
apps/koyo/lib/ticket/ticket.abstract.md
# <model> Abstract
파일 이름에 쓴 그대로의 모듈 이름을 담은 제목 한 줄입니다.
한 문장
모듈이 맡는 일을 제목 바로 아래에 소제목 없이 사실로 적습니다.
## Rules
두 개에서 다섯 개의 항목으로, 각각 코드에서 유추할 수 없는 불변식입니다.
## Workflow
선택 사항이며, 이 소제목 아래 목록이나 소제목 없는 화살표 한 줄로 적습니다.
Akan.js 저장소의 abstract 33개 중 31개가 이 구성으로 쓰여 있고, 그중 여섯 개에 ## Workflow 목록이 있습니다. 나머지 둘은 app 루트 service인 _akan과 _minimal의 것으로, 자동 생성된 초안을 손대지 않은 채 들고 있습니다.

실제 예시

libs/shared/lib/user/user.abstract.md의 전문입니다. constant, document, service, signal, store 파일과 컴포넌트 다섯 개를 가진 모듈이지만 abstract는 열여섯 줄입니다:
libs/shared/lib/user/user.abstract.md
코드와 나란히 읽으면서 무엇이 있고 무엇이 없는지 보세요:
  • type이 없습니다. 필드 type, 클래스, 메서드 시그니처를 부르는 항목이 하나도 없습니다.
  • 제약과 결합만 있습니다. 모든 규칙이 데이터베이스 혼자서는 표현할 수 없는 제약이거나, 이 모듈과 다른 모듈 사이의 결합입니다.
  • 마지막 규칙은 적혀 있지 않으면 깨뜨려 보고서야 알게 됩니다. 제한, 휴면, 탈퇴, 활성화는 모두 summary 집계와 함께 움직입니다.
  • 파일 하나에 언어 하나. 이 저장소에서는 한국어 abstract가 흔하고 영어도 똑같이 괜찮지만, 한 파일 안에서 언어를 바꾸지는 않습니다.

스캐폴드 바꿔 쓰기

akan create-module은 첫 abstract를 대신 만들어 줍니다. 이 초안을 스캐폴드라고 부르며, 제목 한 줄, 문장 하나, 시작 규칙 두 개가 담긴 ## Rules 목록으로 이미 정해진 모양을 갖췄습니다. 처음 제대로 고칠 때 이 줄들을 이 모듈이 맡는 내용으로 바꿔 씁니다.
libs/shared를 쓰는 앱에서 akan create-module project가 만드는 파일입니다:
apps/koyo/lib/project/project.abstract.md
  • libs/shared가 없으면 첫 규칙이 닫혀 있습니다. 슬라이스가 가드를 정할 때까지 아무도 project를 만들거나 고치거나 지우지 못한다고 적히며, 스캐폴드의 None 가드와 맞습니다.
줄마다 바뀌는 모습:
스캐폴드바뀌는 모습
# project Abstract파일 이름 그대로 미리 적혀 있습니다. 그대로 둡니다.
Project represents …모듈이 맡는 일을 사실로 적은 문장으로 고쳐 씁니다.
## Rules그대로 두고, 모듈의 실제 불변식으로 채워 모두 두 개에서 다섯 개가 되게 합니다.
- Anyone may read a project; …스캐폴드 슬라이스의 가드를 옮긴 문장이므로, 가드를 바꿀 때마다 함께 고칩니다.
- Removal is soft: …그대로 둡니다. 모델 삭제는 언제나 soft delete입니다.
## Workflow스캐폴드에는 없습니다. 모듈에 흐름이 생기면 이 소제목이나 화살표 한 줄로 더합니다.
최신으로 유지하기
같은 모듈의 constant, document, service, signal, store, 컴포넌트를 고치기 전에 먼저 읽습니다. 갱신은 모듈의 의미가 바뀔 때만 합니다:
변경
갱신
그대로
모듈의 의미가 바뀔 때
비즈니스 불변식
✓
위의 유일성 규칙처럼 항상 참이어야 하는 규칙입니다.
workflow나 상태 전이
✓
prepare에서 active로 가는 것처럼 레코드가 움직이는 방식입니다.
권한
✓
관리자가 제한을 조정하는 것처럼 누가 무엇을 할 수 있는지입니다.
공개 동작
✓
모듈을 쓰는 쪽에서 관찰할 수 있는 동작입니다.
코드 모양만 바뀔 때
포맷팅
✓
포매터가 정하는 공백과 줄바꿈입니다.
import
✓
import를 추가하거나 지우거나 정렬하는 일입니다.
스타일
✓
동작을 바꾸지 않는 코드 스타일 변경입니다.
✓이렇게 합니다하지 않습니다

MIT 라이선스 하에 배포되었습니다.

내 AI에 이 문서 연결하기

MCPhttps://akanjs.com/mcp
Copyright © 2026 Akan.js 모든 권리 보유.시스템 관리자bassman