← 가이드 목록으로 ← Back to guides

TypeScript 실무 프로젝트 구조와 Best Practices TypeScript Real-world Project Structure & Best Practices

대규모 TypeScript 프로젝트에서는 체계적인 구조와 일관된 코드 품질이 필수입니다. 모노레포, ESLint/Prettier, 테스트 전략으로 유지보수하기 쉬운 코드베이스를 만드세요.

Large-scale TypeScript projects require systematic structure and consistent code quality. Build a maintainable codebase with monorepos, ESLint/Prettier, and testing strategies.

프로젝트 디렉토리 구조 Project Directory Structure

Feature 기반 구조는 대규모 프로젝트에서 확장성과 유지보수성을 높입니다.

Feature-based structure improves scalability and maintainability in large projects.

# 권장 프로젝트 구조
src/
├── features/
│   ├── auth/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── services/
│   │   ├── types.ts
│   │   └── index.ts
│   └── users/
├── shared/
│   ├── components/
│   ├── hooks/
│   ├── utils/
│   └── types/
├── lib/
│   ├── api.ts
│   └── config.ts
└── app/
    ├── layout.tsx
    └── page.tsx
# Recommended project structure
src/
├── features/
│   ├── auth/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── services/
│   │   ├── types.ts
│   │   └── index.ts
│   └── users/
├── shared/
│   ├── components/
│   ├── hooks/
│   ├── utils/
│   └── types/
├── lib/
│   ├── api.ts
│   └── config.ts
└── app/
    ├── layout.tsx
    └── page.tsx

tsconfig.json 최적화 Optimizing tsconfig.json

// tsconfig.json - 프로덕션 권장 설정
{
  "compilerOptions": {
    // 타입 체크 강화
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,

    // 모듈 설정
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,

    // 경로 별칭
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@features/*": ["./src/features/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
// tsconfig.json - Production recommended settings
{
  "compilerOptions": {
    // Strict type checking
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,

    // Module settings
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,

    // Path aliases
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@features/*": ["./src/features/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

ESLint & Prettier 설정 ESLint & Prettier Configuration

// eslint.config.js (Flat Config)
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.strictTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
    rules: {
      '@typescript-eslint/no-unused-vars': 'error',
      '@typescript-eslint/no-explicit-any': 'warn',
    },
  }
);
// eslint.config.js (Flat Config)
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.strictTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
    rules: {
      '@typescript-eslint/no-unused-vars': 'error',
      '@typescript-eslint/no-explicit-any': 'warn',
    },
  }
);

📦 pnpm 모노레포 설정 📦 pnpm Monorepo Setup

# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'

# 디렉토리 구조
monorepo/
├── apps/
│   ├── web/      # Next.js 앱
│   └── api/      # NestJS API
├── packages/
│   ├── ui/       # 공유 컴포넌트
│   ├── config/   # ESLint, TS 설정
│   └── utils/    # 공유 유틸리티
└── pnpm-workspace.yaml

⚠️ 흔한 실수들 ⚠️ Common Mistakes

  • any 타입 남용으로 타입 안전성 상실
  • 순환 의존성 (Circular Dependencies)
  • 타입 정의와 구현 파일 분리 미흡
  • 런타임 vs 컴파일타임 타입 혼동
  • Overusing any type losing type safety
  • Circular dependencies
  • Poor separation of type definitions and implementation
  • Confusion between runtime and compile-time types

💡 타입 안전 팁 💡 Type Safety Tips

  • unknownany 대신 사용
  • Type Guards로 런타임 타입 검증
  • as const로 리터럴 타입 보존
  • Zod/Valibot으로 런타임 검증과 타입 추론 통합
  • Use unknown instead of any
  • Validate runtime types with Type Guards
  • Preserve literal types with as const
  • Integrate runtime validation with Zod/Valibot