Files
frontend/apps/_template/shared
2026-02-26 11:55:09 +09:00
..
2026-02-26 11:55:09 +09:00
2026-02-26 11:55:09 +09:00
2026-02-26 11:55:09 +09:00
2026-02-26 11:55:09 +09:00
2026-02-26 11:55:09 +09:00
2026-02-26 11:55:09 +09:00

Shared Layer

Shared는 애플리케이션의 기반을 형성하는 레이어입니다. 외부 세계(백엔드, 서드파티 라이브러리, 환경)와의 연결을 생성하고, 높은 응집력을 가진 자체 라이브러리를 정의하는 곳입니다.

목적

  • 외부 시스템 및 라이브러리와의 통합
  • 프로젝트 전체에서 사용되는 공통 코드 제공
  • 비즈니스 로직이 없는 재사용 가능한 유틸리티 및 UI 제공
  • 글로벌 설정 및 환경 변수 관리

특징

  • 슬라이스 없음: Shared 레이어는 비즈니스 도메인이 없으므로 슬라이스로 나뉘지 않습니다
  • 세그먼트 구성: 기술적 목적에 따라 세그먼트로 직접 구성됩니다
  • 자유로운 import: Shared 내의 모든 파일은 서로를 참조하고 import할 수 있습니다

구조

shared/
├── ui/                # 애플리케이션 UI Kit
│   ├── button/
│   ├── input/
│   ├── modal/
│   └── index.ts
├── api/               # API 클라이언트 및 백엔드 엔드포인트 함수
│   ├── client.ts
│   └── index.ts
├── lib/               # 내부 라이브러리 모음
│   ├── dates/         # 날짜 관련 유틸리티
│   ├── colors/        # 색상 관련 유틸리티
│   ├── text/          # 텍스트 처리 유틸리티
│   └── index.ts
├── config/            # 환경 변수, 글로벌 feature flags
│   ├── env.ts
│   └── index.ts
├── types/             # 공통 타입 정의
│   └── index.ts
├── i18n/              # 번역 설정, 글로벌 번역 문자열
│   └── index.ts
└── routes/            # 라우트 상수 또는 패턴
    └── index.ts

세그먼트 설명

📁 ui

애플리케이션의 UI Kit로, 비즈니스 로직을 포함하지 않는 재사용 가능한 UI 컴포넌트들입니다.

  • Button, Input, Modal 같은 기본 컴포넌트
  • 비즈니스 로직은 없지만 UI 로직은 포함 가능 (예: Autocomplete, SearchBar)
  • 비즈니스 테마 컴포넌트도 허용 (예: 회사 로고, 페이지 레이아웃)

📁 api

API 클라이언트 및 특정 백엔드 엔드포인트 요청 함수입니다.

  • HTTP 클라이언트 설정 (Axios, Fetch 등)
  • 인증 인터셉터
  • 공통 에러 핸들링

📁 lib

내부 라이브러리 모음으로, 각 라이브러리는 하나의 관심사에 집중해야 합니다.

⚠️ 중요: helpers나 utils 폴더처럼 덤프 폴더로 만들지 마세요. 각 라이브러리는 명확한 초점 영역(예: dates, colors, text)을 가져야 하며, README로 문서화해야 합니다.

📁 config

환경 변수, 글로벌 feature flags 및 앱 전체 설정입니다.

📁 types

프로젝트 전체에서 사용되는 공통 타입 정의입니다.

📁 i18n

번역 설정 코드 및 글로벌 번역 문자열입니다.

📁 routes

라우트 상수 또는 라우트 매칭 패턴입니다.

예시

// shared/ui/button/button.tsx
interface ButtonProps {
  children: React.ReactNode;
  variant?: 'primary' | 'secondary';
  onClick?: () => void;
}

export function Button({ children, variant = 'primary', onClick }: ButtonProps) {
  return (
    <button
      className={variant === 'primary' ? 'bg-blue-500' : 'bg-gray-500'}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

// shared/api/client.ts
import axios from 'axios';

export const apiClient = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL,
  timeout: 10000,
});

// shared/lib/dates/format-date.ts
import dayjs from 'dayjs';

export function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {
  return dayjs(date).format(format);
}

// shared/config/env.ts
export const ENV = {
  apiUrl: process.env.NEXT_PUBLIC_API_URL!,
  isDev: process.env.NODE_ENV === 'development',
} as const;

레이어 의존성 규칙

✅ 허용되는 의존성:

  • 같은 shared 레이어 내의 다른 세그먼트 (자유로운 cross-import)
  • 외부 라이브러리 및 패키지

❌ 금지된 의존성:

  • entities 레이어
  • features 레이어
  • widgets 레이어
  • pages 레이어
  • app 레이어

💡 원칙: Shared는 가장 낮은 레이어이므로 상위 레이어에 의존하지 않습니다.

세그먼트 명명 규칙

세그먼트 이름은 내용의 목적을 설명해야 하며, 본질을 설명하면 안 됩니다.

❌ 나쁜 예시: components, hooks, types (본질을 설명) ✅ 좋은 예시: ui, api, lib/dates, config (목적을 설명)

주의사항

  1. 비즈니스 로직 없음: Shared는 순수한 기술적 코드만 포함
  2. 높은 재사용성: 앱 전체에서 사용될 수 있어야 함
  3. 명확한 라이브러리 구조: lib 내부는 관심사별로 명확하게 분리
  4. 문서화: 각 라이브러리는 README로 사용법과 목적을 문서화