CAF 소개: 클린 아키텍처 프론트엔드
Source: Dev.to
비즈니스 로직을 한 번만 작성하세요. React, Vue, Angular 혹은 다음 프레임워크에서 실행하세요. CAF (Clean Architecture Frontend)는 프레임워크에 구애받지 않는 코어를 제공하는 라이브러리로, 동일한 도메인과 유스케이스를 어댑터를 교체함으로써 모든 프론트엔드에서 실행할 수 있게 합니다.
프론트엔드 애플리케이션은 UI, 상태, 비즈니스 규칙을 혼합하는 경우가 많습니다. 프레임워크를 전환하거나 React, Vue, Angular 간에 로직을 공유해야 할 때, 보통 많은 코드를 다시 작성하게 됩니다. 클린 아키텍처가 도움이 되지만, 단일 프레임워크에 구애받지 않는 코어로 이를 잘 구현하는 것은 어렵습니다. CAF는 그 코어를 제공합니다: 프리미티브와 인터페이스를 통해 도메인과 유스케이스가 프레임워크에 얽매이지 않게 합니다.
CAF는 클린 아키텍처를 활용한 프론트엔드 구축을 위한 프레임워크에 구애받지 않는 코어입니다. 도메인 및 애플리케이션 레이어를 한 번 구현하면, React, Vue, Angular(및 향후 프레임워크)에서 작은 어댑터 패키지를 통해 연결됩니다. 단일 UI 스택에 종속되지 않습니다.
In short
- Framework‑agnostic – 하나의 코어, 다수의 UI.
- Clean Architecture – 도메인, 애플리케이션, 인프라스트럭처 레이어가 명확함.
- Reactive primitives – 단일 리액티브 엔진(
Pulse)과 프레젠테이션 로직을 위한Ploc. - Pluggable adapters – 라우팅, HTTP, UI가 인터페이스이며, 여러분(또는 생태계)이 구현합니다.
- TypeScript‑first – 타입이 지정된
UseCase,RequestResult, 그리고Ploc를 엔드‑투‑엔드로 사용.
핵심 개념
Pulse
단일 반응형 값(ref와 유사). 하나의 상태 조각(예: 로딩 플래그, 현재 사용자)을 위해 사용합니다.
Ploc
Presentation Logic Component – Pulse를 기반으로 한 상태ful 블록. UI와 관련된 상태와 메서드를 보유합니다.
UseCase
애플리케이션 작업(명령 또는 쿼리)입니다. RequestResult(loading, data, error)를 반환하여 UI가 로딩/오류/성공을 표시할 수 있게 합니다.
RouteRepository
라우팅에 대한 추상화. 앱이 이를 구현합니다(예: React Router 또는 Vue Router). RouteManager는 인증 및 네비게이션에 이를 사용합니다.
도메인 및 애플리케이션 코드는 오직 이러한 추상화에만 의존합니다. 인프라스트럭처(HTTP, 라우팅, 스토리지)와 UI 레이어는 프레임워크에 의존하지만, 코어는 그렇지 않습니다.
시작하기
1. CAFProvider 로 앱 연결하기
// main.tsx or App.tsx
import { CAFProvider } from '@c-a-f/infrastructure-react';
import { setupUserPloc } from './caf/setup';
const userPloc = setupUserPloc();
export default function App() {
return (
<CAFProvider>
{/* Your app UI goes here */}
</CAFProvider>
);
}
2. 컴포넌트에서 Ploc 사용하기
import { usePlocFromContext, usePloc } from '@c-a-f/infrastructure-react';
import type { UserPloc } from '../caf/application';
export function UserList() {
const ploc = usePlocFromContext('user');
if (!ploc) return null;
const [state] = usePloc(ploc);
return (
<div>
{state.loading && <p>Loading...</p>}
{state.error && <p>Error: {state.error}</p>}
<button onClick={() => ploc.loadUsers()} disabled={state.loading}>
Refresh
</button>
<ul>
{state.users.map((u) => (
<li key={u.id}>
{u.name} – {u.email}
</li>
))}
</ul>
</div>
);
}
동일한 UserPloc와 사용 사례는 Vue 또는 Angular UI를 구동할 수 있습니다; 변경되는 것은 훅(또는 컴포저블/인젝터)뿐입니다.
리포지토리 구조
CAF 리포지토리는 다음 패키지들을 포함하는 모노레포입니다:
- Core:
@c-a-f/core–UseCase,Ploc,Pulse,ApiRequest,RouteManager, 그리고 공유 인터페이스. - Infrastructure (adapters):
@c-a-f/infrastructure-react– React 훅(usePloc,useUseCase,CAFProvider,useRouteManager,useRouteRepository).@c-a-f/infrastructure-vue– Vue 컴포저블 및 프로바이더.@c-a-f/infrastructure-angular– Angular 서비스 및 인젝터.
- Optional modules: 검증(
@c-a-f/validation), 워크플로, 권한, i18n, 테스트, devtools, CLI 스캐폴딩 등.
예시
example-reactexample-vueexample-angularexample-vue-graphqlexample-angular-websocket
각 예시는 자체 caf/ 폴더(도메인, 애플리케이션, 인프라스트럭처)를 포함하고 있으며, 이를 프로젝트에 복사하여 사용할 수 있습니다.
대상 독자
- 팀: 단일 도메인/애플리케이션 레이어를 원하고 React, Vue, Angular 중 하나로 배포할 수 있는 유연성을 원하는 경우.
- 개발자: 테스트 가능성과 명확한 경계(도메인 vs. 애플리케이션 vs. 인프라스트럭처)를 중시하는 경우.
- 모든 사람: 프레임워크‑특정 “클린 아키텍처” 레시피에 지치고, 작은 공유 코어와 관례를 찾는 경우.
설치
npm install @c-a-f/core
npm install @c-a-f/infrastructure-react # or -vue, -angular
선택 사항: 프로젝트 스캐폴드
npm install -g @c-a-f/cli
caf-init
그런 다음 caf/ 폴더를 만들고 domain/, application/, infrastructure/ 디렉터리를 포함시키며, 레포지토리, 유스케이스, Ploc을 연결하는 설정을 합니다. 레포지토리의 문서와 README에는 정확한 레이아웃과 최소 흐름(예: GetUsers UseCase → Ploc → React/Vue/Angular UI)에 대한 안내가 포함되어 있습니다.
링크
- GitHub:
- npm organization:
- Documentation: (소개, 패키지, 시작하기, 모범 사례, ADRs)