# 코드 스타일 & 네이밍 컨벤션 > Nuxt 4 + TypeScript strict 환경 기준 > 최종 업데이트: 2026-04-07 --- ## 디렉토리 구조 ``` my-nuxt-app/ ├─ app/ │ ├─ assets/ │ ├─ components/ # PascalCase.vue │ │ └─ ui/ # shadcn-vue 컴포넌트 │ ├─ composables/ # useXxx.ts │ ├─ layouts/ # kebab-case.vue │ ├─ middleware/ # kebab-case.ts │ ├─ pages/ # kebab-case.vue │ ├─ plugins/ # kebab-case.ts │ ├─ stores/ # useXxxStore.ts │ ├─ utils/ # camelCase.ts │ ├─ app.vue │ ├─ app.config.ts # 테마/UI 등 공개 설정값 │ └─ error.vue ├─ server/ │ ├─ api/ # kebab-case.ts │ ├─ middleware/ │ └─ utils/ ├─ shared/ # 클라이언트/서버 공유 타입 및 유틸 ├─ public/ ├─ nuxt.config.ts ├─ tailwind.config.ts └─ tsconfig.json ``` --- ## 네이밍 컨벤션 ### 파일명 | 파일 종류 | 규칙 | 예시 | |-----------|------|------| | 컴포넌트 | `PascalCase.vue` | `UserProfile.vue` | | 페이지 / 레이아웃 / 미들웨어 / 플러그인 | `kebab-case` | `user-profile.vue` | | 컴포저블 | `useXxx.ts` | `useUserProfile.ts` | | 유틸 함수 | `camelCase.ts` | `formatDate.ts` | | Pinia store | `useXxxStore.ts` | `useAuthStore.ts` | | API 라우트 | `kebab-case.ts` | `user-profile.ts` | | 테스트 파일 | `*.spec.ts` / `*.test.ts` | `UserProfile.spec.ts` | ### 코드 내 | 대상 | 규칙 | 예시 | |------|------|------| | 변수 / 함수 | `camelCase` | `const userName`, `function fetchUser()` | | 컴포넌트명 | `PascalCase` | `UserProfile`, `AppHeader` | | **상수** | **`UPPER_SNAKE_CASE`** | `const MAX_RETRY_COUNT = 3` | | 타입 / 인터페이스 | `PascalCase` | `interface UserProfile` | ```typescript // DO const MAX_PAGE_SIZE = 100 const DEFAULT_LOCALE = 'ko' // DON'T const maxPageSize = 100 // 금지: 상수에 camelCase const defaultLocale = 'ko' // 금지 ``` --- ## TypeScript 엄격 모드 ### any 타입 사용 금지 `any`는 타입 안전성을 무력화한다. `unknown` 또는 명시적 타입을 사용한다. ```typescript // DON'T async function fetchUser(id: any): Promise { return await $fetch(`/api/users/${id}`) } // DO async function fetchUser(id: string): Promise { return await $fetch(`/api/users/${id}`) } // unknown 사용 시 타입 좁히기 function parseResponse(raw: unknown): User { if (!isUser(raw)) throw new Error('유효하지 않은 응답입니다.') return raw } ``` ### Props 타입 명시 ```vue ```