# Features Layer **Features**는 앱의 주요 사용자 상호작용과 기능을 구현하는 레이어입니다. 사용자가 실제로 수행하는 작업들로, 주로 비즈니스 엔티티와 관련이 있습니다. ## 목적 - 사용자가 중요하게 생각하는 주요 상호작용 구현 - 재사용 가능한 비즈니스 기능 제공 - 여러 페이지에서 사용되는 기능의 중복 제거 ## Feature로 만들어야 하는 경우 > ⚠️ **중요**: 모든 것을 feature로 만들 필요는 없습니다. Feature로 만드는 것이 좋은 지표: - **여러 페이지에서 재사용됨**: 예를 들어, 여러 에디터가 있고 모두 댓글 기능이 있다면, 댓글은 재사용 가능한 feature입니다 - **중요한 비즈니스 기능**: 신규 프로젝트 참여자가 Features 폴더를 보고 앱의 주요 기능을 빠르게 파악할 수 있어야 합니다 Feature가 너무 많으면 중요한 기능이 묻히므로, 신규 참여자의 경험을 최적화하여 결정하세요. ## 구조 각 feature 슬라이스는 다음 세그먼트로 구성됩니다: ``` features/ └── [feature-name]/ ├── ui/ # 상호작용을 수행하는 UI (폼, 버튼 등) ├── api/ # 액션 수행에 필요한 API 호출 (선택적) ├── model/ # 검증 및 내부 상태 관리 (선택적) ├── lib/ # 유틸리티 함수 (선택적) ├── config/ # feature flags (선택적) └── index.ts # Public API ``` ### 세그먼트 설명 - **ui**: 사용자 상호작용을 위한 UI 컴포넌트 (폼, 모달, 버튼 등) - **api**: feature 실행에 필요한 API 요청 함수 - **model**: 폼 검증, 내부 상태, 비즈니스 로직 - **lib**: feature 내부에서만 사용되는 유틸리티 - **config**: feature flags, feature별 설정값 - **index.ts**: 슬라이스의 Public API (외부에서 사용할 수 있는 것만 export) ## 예시 ```typescript // features/auth-login/ui/login-form.tsx import { useState } from 'react'; import { loginUser } from '../api/login-user'; import type { LoginCredentials } from '../model/types'; export function LoginForm() { const [credentials, setCredentials] = useState({ email: '', password: '' }); const handleSubmit = async (e: React.SubmitEvent) => { e.preventDefault(); await loginUser(credentials); }; return (
setCredentials({ ...credentials, email: e.target.value })} /> setCredentials({ ...credentials, password: e.target.value })} />
); } // features/auth-login/api/login-user.ts import type { LoginCredentials } from '../model/types'; export async function loginUser(credentials: LoginCredentials) { const response = await fetch('/api/auth/login', { method: 'POST', body: JSON.stringify(credentials), }); return response.json(); } // features/auth-login/model/types.ts export interface LoginCredentials { email: string; password: string; } // features/auth-login/index.ts export { LoginForm } from './ui/login-form'; export { loginUser } from './api/login-user'; export type { LoginCredentials } from './model/types'; ``` ## 레이어 의존성 규칙 ✅ **허용되는 의존성**: - `shared` 레이어의 모듈 - `entities` 레이어의 모듈 - 같은 feature 슬라이스 내의 다른 세그먼트 ❌ **금지된 의존성**: - 다른 `features` 슬라이스 (feature 간 직접 의존 금지) - `widgets` 레이어 - `pages` 레이어 - `app` 레이어 > 💡 **팁**: 여러 features가 공통 기능을 필요로 한다면, 그 기능을 `shared` 레이어로 이동시키거나 `entities` 레이어에서 관리하세요. ## 명명 규칙 - 소문자와 대시 사용: `auth-login`, `post-create`, `comment-edit` - 동사 형태 권장: 사용자 액션을 나타내는 이름 사용 - 명확하고 구체적으로: 기능의 목적이 명확하게 드러나도록 ## 주의사항 1. **하나의 기능에만 집중**: 각 feature는 단일 사용자 시나리오를 구현해야 합니다 2. **재사용성 고려**: 여러 페이지에서 사용될 수 있도록 설계 3. **독립성 유지**: 다른 features에 의존하지 않고 독립적으로 작동 4. **적절한 추상화**: 너무 많은 feature를 만들지 말고, 중요한 기능 위주로 구성