Files
frontend/apps/_template/app

App Layer

App은 애플리케이션 전체에 영향을 미치는 기술적, 비즈니스적 사항을 다루는 최상위 레이어입니다.

목적

  • 애플리케이션의 진입점(entrypoint) 제공
  • 전역 Context Providers 설정
  • 라우터 구성
  • 글로벌 스타일 정의
  • 전역 상태 저장소 설정
  • 애널리틱스 및 모니터링 설정

특징

  • 슬라이스 없음: App 레이어는 Shared처럼 슬라이스가 없고 세그먼트로만 구성됩니다
  • 전체 앱 관심사: 특정 비즈니스 도메인이 아닌 앱 전체와 관련된 코드만 포함
  • 최상위 레이어: 모든 하위 레이어의 모듈을 자유롭게 import 가능

구조 (Next.js App Router)

Next.js를 사용하는 경우, App 레이어는 주로 app/ 디렉토리로 표현됩니다:

app/
├── (routes)/              # 라우트 그룹 및 페이지
│   ├── (auth)/
│   │   ├── login/
│   │   │   └── page.tsx
│   │   └── register/
│   │       └── page.tsx
│   └── (main)/
│       ├── dashboard/
│       │   └── page.tsx
│       └── settings/
│           └── page.tsx
├── layout.tsx            # 루트 레이아웃
├── page.tsx              # 홈 페이지
├── globals.css           # 글로벌 스타일
├── providers.tsx         # 전역 Providers 설정
└── error.tsx             # 글로벌 에러 핸들러

일반적인 FSD 세그먼트 구조

FSD 표준 세그먼트를 사용하는 경우:

app/
├── entrypoint/           # 애플리케이션 진입점 (프레임워크별)
│   └── index.tsx
├── providers/            # Context Providers
│   ├── query-provider.tsx
│   ├── theme-provider.tsx
│   └── index.tsx
├── styles/               # 글로벌 스타일
│   ├── globals.css
│   └── theme.css
├── store/                # 글로벌 상태 저장소 설정
│   └── index.ts
└── routes/               # 라우터 설정
    └── index.tsx

예시

Next.js Providers 설정

// app/providers.tsx
'use client';

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ThemeProvider } from 'next-themes';
import { useState } from 'react';

export function Providers({ children }: { children: React.ReactNode }) {
  const [queryClient] = useState(() => new QueryClient({
    defaultOptions: {
      queries: {
        staleTime: 60 * 1000,
      },
    },
  }));

  return (
    <QueryClientProvider client={queryClient}>
      <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
        {children}
      </ThemeProvider>
    </QueryClientProvider>
  );
}

// app/layout.tsx
import { Providers } from './providers';
import './globals.css';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body>
        <Providers>
          {children}
        </Providers>
      </body>
    </html>
  );
}

글로벌 설정

// app/config/analytics.ts
export function initAnalytics() {
  if (typeof window !== 'undefined') {
    // 애널리틱스 초기화
  }
}

// app/config/monitoring.ts
export function initMonitoring() {
  // 에러 모니터링 설정
}

Next.js App Router와 FSD

Next.js의 app/ 디렉토리는 FSD의 App 레이어와 Pages 레이어를 동시에 담당합니다:

  • 루트 레벨 파일들 (layout.tsx, providers.tsx, globals.css): App 레이어
  • 라우트 폴더들 (dashboard/, login/ 등): Pages 레이어

각 페이지별 비즈니스 로직은:

  • 재사용되지 않는 UI는 페이지 슬라이스(app/dashboard/ 등) 안에 유지
  • 재사용되는 기능은 features/ 레이어로 분리
  • 여러 페이지에서 재사용되는 큰 UI 블록은 widgets/ 레이어로 분리

레이어 의존성 규칙

✅ 허용되는 의존성:

  • 모든 하위 레이어 (pages, widgets, features, entities, shared)
  • 같은 app 레이어 내의 다른 세그먼트
  • 외부 라이브러리

❌ 금지된 의존성:

  • 없음 (App은 최상위 레이어)

주의사항

  1. 비대화 방지: App 레이어가 너무 커지면 관리가 어려워집니다. 대부분의 로직은 하위 레이어에 배치하세요
  2. 전역 관심사만: 특정 페이지나 기능에만 관련된 코드는 해당 레이어로 이동
  3. 라우터 레벨 로직: 라우터 및 서버 레벨 로직은 이 레이어에 유지
  4. Processes 레이어 사용 지양: Processes 레이어는 deprecated되었으므로 해당 로직은 app이나 features에 배치

FSD v2.1 권장사항

최신 FSD 버전(v2.1)은 "pages-first" 접근 방식을 권장합니다:

  • 더 많은 코드를 페이지 슬라이스에 유지
  • 큰 UI 블록과 재사용되지 않는 비즈니스 로직은 즉시 추출하지 말고 페이지에 보관
  • 실제로 재사용이 필요할 때만 features나 widgets로 분리

이 접근 방식은 과도한 추상화를 방지하고 코드를 더 쉽게 탐색할 수 있게 합니다.