# Architecture Guide

FSD(Feature-Sliced Design) 기반 프로젝트 아키텍처 가이드입니다.

## Layer 구조

```
src/
├── app/          # 페이지, 레이아웃 (Next.js App Router)
├── shared/       # 공통 유틸, UI, 라이브러리
├── entities/     # 도메인 데이터 (CRUD + 스키마)
├── features/     # 사용자 액션 (폼, mutation, 검색)
├── widgets/      # 페이지 섹션 UI (도메인 UI 조합)
├── processes/    # 복합 cross-feature 플로우 (필요시)
└── i18n/         # 다국어 설정
```

### Layer 의존성 규칙

상위 레이어는 하위 레이어만 import할 수 있습니다.

```
app → widgets → features → entities → shared
```

| 규칙 | 설명 |
| --- | --- |
| `shared`는 다른 레이어를 import하지 않음 | 완전히 독립적인 기반 레이어 |
| `entities`는 `shared`만 import | 도메인 간 직접 참조 금지 |
| `features`는 `entities` + `shared` import | 사용자 액션 레이어 |
| `widgets`는 `features` + `entities` + `shared` import | UI 조합 레이어 |
| `app`은 모든 레이어 import 가능 | 최상위 조합 레이어 |

## app/ — 페이지 레이어

Next.js App Router 기반 페이지와 레이아웃을 담당합니다.

```
app/
├── layout.tsx              # 루트 레이아웃
├── page.tsx                # 루트 페이지 (리다이렉트)
├── (auth)/                 # 인증 라우트 그룹
│   ├── signin/page.tsx
│   └── signup/page.tsx
└── (dashboard)/            # 대시보드 라우트 그룹
    ├── main/page.tsx
    └── payment/page.tsx
```

| 파일 | 역할 |
| --- | --- |
| `page.tsx` | Server Component, URL 파라미터 검증, 데이터 존재 확인 |
| `layout.tsx` | 공통 레이아웃, Provider 설정 |
| `error.tsx` | 에러 바운더리 |
| `page.module.scss` | 페이지 전용 스타일 |

## shared/ — 공통 기반 레이어

모든 레이어에서 사용하는 공통 코드입니다.

```
shared/
├── constants/          # 앱 전역 상수
├── hooks/              # 공통 훅 (pagination, navigation 등)
├── libs/               # 라이브러리 래퍼 및 유틸리티
│   ├── api/
│   │   ├── axios/      # Axios 인스턴스, 인터셉터, 에러 처리
│   │   ├── cookie/     # 토큰 쿠키 관리
│   │   ├── gcp/        # GCP 업로드 API + 훅
│   │   └── zod/        # Zod 파싱 유틸 (getParsed 등)
│   ├── i18n/           # next-intl 설정
│   ├── modal/          # 전역 모달 시스템
│   ├── query/          # MutationCache (에러 핸들링)
│   ├── storage/        # localStorage 래퍼
│   └── toast/          # ToastBridge (전역 토스트)
├── schema/             # 공통 스키마 (에러, 응답 등)
├── types/              # 전역 타입 선언
└── ui/                 # 공통 UI 컴포넌트
    ├── custom-suspense/
    └── error-fallback/
```

## entities/ — 도메인 레이어

서버 데이터 구조와 순수 도메인 로직을 정의합니다.

```
entities/<domain>/
├── api/            # API 호출 함수 + API 전용 스키마
├── schema/         # 도메인 스키마 (Zod) + 타입
├── constants/      # 도메인 상수
└── util/           # 순수 도메인 로직 (검증, 변환 등)
```

**주의:** entities에는 `model/` 폴더를 사용하지 않습니다. 타입은 `schema/`, 로직은 `util/`에 배치합니다.

### 현재 도메인 목록

| Domain | 설명 | 하위 구조 |
| --- | --- | --- |
| `signin` | 인증 (로그인/토큰) | `api/`, `schema/`, `constants/`, `util/` |
| `member` | 멤버 정보 | `api/`, `schema/`, `util/` |
| `organization` | 조직 관리 | `api/`, `schema/`, `util/` |
| `user` | 사용자 (결제 상태 등) | `api/`, `schema/`, `util/` |
| `billing` | 결제/구독 | `api/`, `constants/` |

### Entity 예시

```
entities/signin/
├── api/
│   └── signin.api.ts         # postSigninApi, postSignupApi 등
├── schema/
│   └── signin.schema.ts      # Zod 스키마 + 추론 타입
├── constants/
│   └── signin.constants.ts   # TOKEN 키, 검증 패턴 등
└── util/
    └── signin.util.ts        # validateSignin, extractTokens 등
```

## features/ — 액션 레이어

사용자 인터랙션 단위의 기능을 구현합니다.

```
features/<feature>/
├── model/          # 비즈니스 로직 훅 (use-*.ts)
├── query/          # useQuery 훅 (읽기)
├── mutation/       # useMutation 훅 (쓰기)
└── ui/             # 기능 전용 UI 컴포넌트
```

### Query/Mutation 분리 규칙

| 타입 | 위치 | 파일명 예시 |
| --- | --- | --- |
| `useQuery`, `useSuspenseQuery` | `query/` | `member.query.ts` |
| `useMutation` | `mutation/` | `signin.mutation.ts` |
| 비즈니스 로직 훅 | `model/` | `use-signin.ts` |
| Query/Mutation 키 | 각 폴더의 `keys.ts` | `query/keys.ts` |

### model/ 구조 규칙

- 훅은 `model/` 폴더에 **플랫하게** 배치 (`model/hooks/` 하위 폴더 금지)
- Zustand store도 `model/`에 배치 (`use-*.store.ts`)
- 유틸 함수도 `model/`에 배치 가능 (`*.util.ts`)

```
features/signin/model/
├── index.ts
├── use-signin.ts                 # 로그인 통합 훅
├── use-signin-form.ts            # 폼 상태 관리
├── use-signin-submit.ts          # 제출 로직
├── use-forgot-password.ts        # 비밀번호 찾기
└── forgot-password.store.ts      # Zustand store
```

### 현재 Feature 목록

| Feature | 설명 | 하위 구조 |
| --- | --- | --- |
| `signin` | 로그인 | `model/`, `mutation/`, `ui/` |
| `signup` | 회원가입 | `model/`, `ui/` |
| `organization` | 조직 생성/관리 | `model/`, `mutation/`, `query/`, `ui/` |
| `member` | 멤버 조회 | `query/` |
| `user` | 사용자 정보 | `mutation/`, `query/` |
| `billing` | 결제 | `mutation/` |

## widgets/ — 위젯 레이어

페이지 섹션 단위의 도메인 UI를 구현합니다.

```
widgets/<widget>/
├── model/              # 위젯 비즈니스 로직 훅
├── ui/                 # UI 컴포넌트
│   ├── index.tsx       # 위젯 진입점
│   └── style.module.scss
└── (style.module.scss) # 위젯 루트 스타일 (ui/ 내에 위치 가능)
```

### model/ 구조 규칙 (Feature와 동일)

- 훅, store, util 모두 `model/`에 **플랫하게** 배치
- 하위 폴더(`model/store/`, `model/util/` 등) 금지
- 접미사로 파일 성격을 구분: `use-*.ts`, `use-*.store.ts`, `*.util.ts`

```
widgets/member/table/model/
├── use-member-selection.store.ts  # Zustand store
└── member-table.util.ts           # 유틸 함수
```

### 현재 Widget 목록

| Widget | 설명 |
| --- | --- |
| `member/table` | 멤버 테이블 (데스크톱/모바일 반응형) |
| `profile/modal` | 프로필 설정 모달 |
| `invitation-modal` | 초대 모달 |
| `organization-modal` | 조직 생성 모달 |
| `layouts/footer` | 푸터 |
| `layouts/provider` | 전역 Provider 조합 |

## 파일 분할 기준

| 조건 | 액션 |
| --- | --- |
| 파일이 **100줄** 초과 | 분할 검토 |
| 파일의 **책임이 2개 이상** | 분할 |
| 관련 기능이 100줄 미만 | 한 파일에 유지 |

## 새 도메인 추가 가이드

### 1. Entity 생성

```bash
# 필요한 폴더만 생성 (전부 필수는 아님)
entities/<domain>/
├── api/<domain>.api.ts
├── schema/<domain>.schema.ts
├── constants/<domain>.constants.ts    # 필요시
└── util/<domain>.util.ts              # 필요시
```

### 2. Feature 생성

```bash
features/<feature>/
├── model/use-<feature>.ts             # 통합 훅 (필수)
├── model/use-<feature>-form.ts        # 폼이 있을 경우
├── model/use-<feature>-submit.ts      # 제출 로직이 복잡할 경우
├── query/<feature>.query.ts           # 읽기 API가 있을 경우
├── query/keys.ts
├── mutation/<feature>.mutation.ts     # 쓰기 API가 있을 경우
├── mutation/keys.ts
└── ui/                                # 기능 전용 UI가 있을 경우
```

### 3. Widget 생성

```bash
widgets/<widget>/
├── model/use-<widget>.ts              # 비즈니스 로직 훅
└── ui/
    ├── index.tsx                      # 위젯 진입점
    └── style.module.scss
```

## 핵심 인프라

### 에러 처리 흐름

```
API 에러 발생
  → Axios Response Interceptor (401 토큰 갱신)
  → MutationCache onError (shared/libs/query/mutation-cache.ts)
  → ToastBridge (shared/libs/toast/toast-bridge.ts)
  → 토스트 UI 표시
```

- Mutation 에러는 `MutationCache`에서 중앙 처리
- 개별 mutation에서 `meta.errorMessage`로 커스텀 메시지 설정
- `meta.showErrorToast: false`로 특정 mutation의 토스트 비활성화

### 인증 흐름

```
로그인 → 토큰 쿠키 저장 (js-cookie)
  → Request Interceptor: Bearer 토큰 자동 첨부
  → 401 발생 시: Response Interceptor → 토큰 갱신 큐
  → 갱신 실패 시: 자동 로그아웃
```

### 모달 시스템

```
shared/libs/modal/
├── modal.ts                 # 모달 등록/해제 API
├── use-modal-store.ts       # Zustand 기반 모달 상태
├── use-modal.ts             # 모달 사용 훅
├── modal-renderer.tsx       # 전역 모달 렌더러
└── modal-store.schema.ts    # 모달 타입 정의
```
