5.1 KiB
5.1 KiB
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 (목적을 설명)
주의사항
- 비즈니스 로직 없음: Shared는 순수한 기술적 코드만 포함
- 높은 재사용성: 앱 전체에서 사용될 수 있어야 함
- 명확한 라이브러리 구조:
lib내부는 관심사별로 명확하게 분리 - 문서화: 각 라이브러리는 README로 사용법과 목적을 문서화