사람함께에이전트▾
사람 — 직접 정하고 책임지는 비즈니스 규칙과 흐름. 직접 읽어보세요.
함께 — 개념은 알아두고, 세부 규칙은 에이전트가 따릅니다.
에이전트 — 에이전트가 따르는 규칙과 레퍼런스. 필요할 때 찾아보세요.
모듈 규칙▾
Akan.js 데이터베이스 모듈
Akan.js의 데이터베이스 모듈은 서버와 클라이언트 간의 원활한 통합을 통해 도메인별 기능을 구축하는 구조화된 접근 방식을 제공합니다. 각 모듈은 데이터 모델부터 UI 컴포넌트까지 관련된 모든 기능을 일관되고 타입 안전한 구조로 캡슐화합니다.
📦도메인 캡슐화
일관된 구조로 도메인별 로직 캡슐화
🔗풀스택 통합
MongoDB, NestJS 서버 및 React 클라이언트 간의 원활한 통합
🔒타입 안전성
자동 생성된 타입으로 전체 스택에 걸쳐 타입 안전성 보장
⚡자동 CRUD
표준화된 패턴을 통한 자동 CRUD 작업 제공
파일 구조
완전한 데이터베이스 모듈은 다음 구조를 따릅니다. 레스토랑 주방을 정리하는 것처럼 생각하세요 - 각 스테이션은 특정 역할을 가지며, 함께 원활한 식사 경험을 만들어냅니다.
Module Directory Structure
field설명
constant.ts
via() 함수 패턴을 사용하여 타입 안전한 스키마 정의를 위한 데이터 모델 정의
document.ts
from(), by(), into(), beyond()를 사용한 필터, 메서드, 미들웨어가 포함된 MongoDB 스키마
service.ts
의존성 주입과 함께 serve()를 사용한 비즈니스 로직 구현
signal.ts
타입 안전한 클라이언트-서버 통신을 위한 slice()와 endpoint() 사용 API 엔드포인트
store.ts
자동 슬라이스 통합이 포함된 store()를 사용한 클라이언트 측 상태 관리
모델 스키마 생성
via() 함수 패턴을 사용하여 데이터 모델을 정의합니다. 이 접근 방식은 유효성 검사, 기본값, 관계와 함께 타입 안전한 필드 정의를 제공합니다.
product.constant.ts
모델 정의의 핵심 개념을 이해해봅시다:
field설명
enumOf()
주어진 이름과 값으로 타입 안전한 enum 클래스를 생성합니다. 엄격한 타입 검사를 위해 리터럴 타입을 보존하려면 'as const'를 사용하세요.
via((field) => ({...}))
field() 함수는 각 속성을 타입, 기본값, 유효성 검사, nullable 필드를 위한 .optional() 같은 옵션과 함께 정의합니다.
Class Hierarchy
Input → Object → Light → Model 순서입니다. 각 계층은 특정 기능을 추가합니다. Light 클래스는 최적화된 목록 쿼리를 위해 특정 필드를 선택합니다.
데이터베이스 스키마 구현
함수형 패턴을 사용하여 필터, 문서 메서드, 미들웨어가 포함된 MongoDB 스키마를 생성합니다. 이 파일은 constant 정의와 실제 데이터베이스 작업을 연결합니다.
product.document.ts
문서 계층 함수들을 이해해봅시다:
field설명
from() - Filter Definition
필수 파라미터를 위한 .arg()와 선택적 파라미터를 위한 .opt()로 재사용 가능한 쿼리 패턴을 정의합니다. .query() 메서드는 MongoDB 쿼리 객체를 반환합니다.
by() - Document Methods
개별 문서에서 작동하는 인스턴스 메서드가 있는 문서 클래스를 생성합니다. 메서드는 문서를 수정할 수 있으며 체이닝을 위해 'this'를 반환해야 합니다.
into() - Model Operations
컬렉션 수준 작업이 있는 모델 클래스를 생성합니다. 필터에서 쿼리 메서드를 자동 생성합니다 (예: inCategory 필터에서 queryInCategory).
beyond() - Middleware
onSchema 메서드를 통해 인덱스, pre/post 훅, 가상 필드 같은 스키마 수준 구성을 추가합니다.
서비스의 비즈니스 로직
서비스는 애플리케이션의 비즈니스 로직을 포함합니다. 문서 작업을 조율하고, 모듈 간 의존성을 처리하며, 복잡한 워크플로우를 구현합니다.
product.service.ts
서비스 계층의 핵심 요소:
field설명
serve()
문서 모델에서 CRUD 작업(getProduct, loadProductMany 등)을 자동으로 상속받는 서비스 클래스를 생성합니다.
service<T>()
다른 서비스를 위한 의존성 주입입니다. 선언된 서비스는 메서드에서 this.serviceName으로 자동 사용 가능합니다.
Method Chaining
문서 메서드가 'this'를 반환하여 product.sell(5).save() 같은 체이닝이 가능합니다. 변경사항을 저장하려면 항상 .save()를 호출하세요.
API 엔드포인트 정의
시그널은 클라이언트를 서비스에 연결하는 API 계층을 정의합니다. 데이터 가져오기를 위한 슬라이스와 변이를 위한 엔드포인트를 포함하며, 모두 타입 안전한 파라미터와 가드가 있습니다.
product.signal.ts
시그널 계층 구성 요소 이해하기:
field설명
slice()
페이지네이션, 검색, 실시간 업데이트를 지원하는 데이터 가져오기 엔드포인트를 정의합니다. URL 파라미터에는 .param()을, 쿼리 스트링에는 .search()를 사용합니다.
endpoint() + mutation()
데이터를 수정하는 mutation 엔드포인트를 정의합니다. 첫 번째 인수는 반환 타입, 그 다음 가드, 파라미터(.param()), 바디 데이터(.body())입니다.
guards
Admin, User, Every, Public 가드로 접근 제어합니다. .with(Self)를 사용하여 현재 사용자 컨텍스트를 exec 함수에 주입합니다.
srv.product.with()
모듈 간 작업을 위해 여러 서비스를 결합합니다. 결합된 모든 서비스는 exec 함수에서 this.serviceName으로 사용 가능합니다.
클라이언트 측 상태 관리
스토어는 클라이언트 측 상태를 관리하고 API와 상호작용하는 메서드를 제공합니다. 슬라이스와 자동으로 통합되며 UI 컴포넌트를 위한 일관된 인터페이스를 제공합니다.
product.store.ts
스토어 계층 이해하기:
field설명
store(sig.module, state)
시그널에 연결된 스토어 클래스를 생성합니다. 슬라이스를 위한 상태와 setter를 자동 생성합니다 (productList, setProduct, productForm 등).
fetch
시그널에서 자동 생성된 타입 안전한 API 클라이언트입니다. 메서드는 시그널 엔드포인트 이름과 일치합니다 (fetch.sellProduct, fetch.createProduct).
msg
딕셔너리 키를 사용하는 토스트 알림 헬퍼입니다. 번역을 지원하는 msg.loading(), msg.success(), msg.error()를 제공합니다.
UI 컴포넌트 구성
UI 컴포넌트는 목적에 따라 구성됩니다: 폼을 위한 Template, 카드를 위한 Unit, 상세 정보를 위한 View, 레이아웃을 위한 Zone, 액션을 위한 Util. 각각 일관된 패턴을 따릅니다.
field설명
Template - Form Components
상태를 위해 st.use.[model]Form()을, 업데이트를 위해 st.do.set[Field]On[Model]을 사용하는 폼 컴포넌트입니다. Layout.Template으로 감싸집니다.
Unit - Card Components
LightModel 데이터를 카드/리스트 형식으로 표시합니다. 모델을 prop으로 받고 선택적 액션과 함께 요약 정보를 렌더링합니다.
View - Detail Components
전체 모델 상세 정보를 표시합니다. 완전한 모델(Light가 아닌)을 받아 구조화된 레이아웃에 모든 관련 정보를 표시합니다.
Zone - Layout Components
Load.Units를 통해 데이터 로딩을 처리하고 Unit/View 컴포넌트를 구성하는 컨테이너 컴포넌트입니다. 종종 모달과 실시간 새로고침을 포함합니다.
Util - Action Components
재사용 가능한 액션 버튼과 유틸리티입니다(Process, Serve, Cancel). modelId와 disabled props를 받고, 클릭 시 스토어 메서드를 호출합니다.
데이터베이스 모듈의 데이터 흐름
모듈 계층을 통해 데이터가 어떻게 흐르는지 이해하면 문제를 디버깅하고 효율적인 기능을 설계하는 데 도움이 됩니다. 사용자 상호작용에서 데이터베이스까지의 전체 흐름입니다:
1
사용자 상호작용
사용자가 Unit/Template 컴포넌트의 버튼 클릭
2
스토어 액션
스토어 메서드 호출 (st.do.sellProduct)
3
API 호출
fetch.sellProduct()이 엔드포인트에 요청 전송
4
Signal → Service
Signal exec()가 검증된 파라미터로 서비스 메서드 호출
5
문서 작업
문서 메서드가 MongoDB에 업데이트 및 저장
6
UI 업데이트
스토어가 상태 업데이트, React가 컴포넌트 리렌더링
모듈 모범 사례
이러한 모범 사례를 따르면 모듈이 유지보수 가능하고 성능이 좋으며 Akan.js 생태계와 일관성을 유지합니다:
1️⃣명명 규칙
클래스/컴포넌트에는 PascalCase (ProductService, Product.Template.General), 파일과 메서드에는 camelCase (product.service.ts)를 사용합니다.
2️⃣코드 구성
비즈니스 로직은 서비스에 유지하고, 시그널은 API 정의에만 사용합니다. 문서 메서드는 간단한 상태 변이여야 합니다.
3️⃣성능
목록 쿼리에는 Light 클래스를 사용하고, 미들웨어에서 적절한 인덱스를 생성하며, 로더에서 병렬 fetch를 위해 Promise.all을 사용합니다.
4️⃣보안
모든 엔드포인트에 적절한 가드를 적용합니다. 현재 사용자 접근에는 .with(Self)를 사용합니다. Light 클래스에 민감한 데이터를 절대 노출하지 않습니다.
5️⃣UI 컴포넌트
관심사를 Template/Unit/View/Zone/Util로 분리합니다. 컴포넌트 재사용을 위해 동작 제어에 props(showControls, disabled)를 사용합니다.