이 프로젝트의 코딩 컨벤션과 스타일 가이드. 새 파일 생성, 코드 수정, 리팩토링 시 참조.
// Good
useEffect(() => { ... }, [deps1]);
useEffect(() => { ... }, [deps2]);
// Bad
useEffect(() => { ... }, [deps1]);
useEffect(() => { ... }, [deps2]);
// 1) 외부 라이브러리
import { useEffect, useState } from 'react';
// 2) 내부 절대 경로 (~/)
import { useEventCallback } from '~/hooks';
// 3) 상대 경로 (컴포넌트, 훅, 유틸)
import Controls from './components/Controls';
import { useTimerSequence } from './hooks';
// 4) 스타일
import css from './Component.module.scss';
// 5) 타입 (import type)
import type { TimerConfig } from './types';
import type { FC } from 'react';
배럴 파일 (index.ts):
// 컴포넌트 default re-export
export { default } from './Component';
// 모듈 named re-export
export { default as moduleName } from './moduleName';
// 타입 re-export
export type { TypeName } from './types';
개별 파일: 파일 끝에 export default
타입 파일:
// types/TimerConfig.ts
interface TimerConfig { ... }
export default TimerConfig;
export type { ThemeName, BellName };
// types/index.ts
export type { default as TimerConfig, ThemeName } from './TimerConfig';
useEventCallback으로 감싸서 안정적인 참조 유지const handleClick = useEventCallback(() => { ... });
const mounted = useMounted();
useEffect(() => {
if (mounted) {
// localStorage 접근
}
}, [mounted]);
import css from './Component.module.scss'className={css.root}cn() 유틸 사용import { cn } from '~/lib/utils';
<div className={cn(css.root, {
[css.active]: isActive,
})} />
style={{ '--color': value } as CSSProperties}src/
├── components/
│ ├── [Domain]/ # 도메인별 컴포넌트
│ │ ├── Component.tsx
│ │ ├── Component.module.scss
│ │ ├── index.ts # 배럴 파일
│ │ ├── components/ # 하위 컴포넌트
│ │ ├── hooks/ # 도메인 전용 훅
│ │ ├── types/ # 도메인 전용 타입
│ │ └── utils/ # 도메인 전용 유틸
│ └── ui/ # shadcn/ui 컴포넌트
├── hooks/ # 공통 훅
├── lib/ # 공통 유틸리티
├── providers/ # Context Providers
└── main.tsx
import * as DialogPrimitive from '@radix-ui/react-dialog';
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
}
// Radix UI - namespace import
import * as SelectPrimitive from '@radix-ui/react-select';
// lucide-react - named import
import { PlusCircle, Check } from 'lucide-react';
// eslint-disable-next-line react-refresh/only-export-components
export { useMyContext };