- Vite + React 프로젝트 구조 설정 - 불필요한 PDF 파일 삭제 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
25 KiB
25 KiB
📘 SAM MES 솔루션 개발 가이드라인
📋 목차
- 시작하기
- 프로젝트 구조
- 코딩 규칙
- 컴포넌트 개발
- 스타일링 가이드
- TypeScript 가이드
- 상태 관리
- 파일 명명 규칙
- Git 워크플로우
- 테스팅
- 성능 최적화
- 접근성
- 보안
- 문서화
- 베스트 프랙티스
🚀 시작하기
프로젝트 개요
SAM MES는 중소 및 중견기업을 위한 완전한 제조실행시스템(MES) 솔루션입니다.
핵심 기술
- React 18+ (TypeScript)
- Tailwind CSS v4.0
- shadcn/ui 컴포넌트
- Recharts (데이터 시각화)
- Figma Make 플랫폼
개발 환경 설정
- 프로젝트 파일 구조 파악
TECH_STACK.md문서 읽기DEVELOPMENT_ENVIRONMENT.md문서 읽기- 기존 컴포넌트 코드 분석
📁 프로젝트 구조
디렉토리 구조
SAM-MES/
├── App.tsx # 메인 애플리케이션 엔트리
├── *.md # 프로젝트 문서들
├── components/ # React 컴포넌트
│ ├── [PageComponents].tsx # 페이지 레벨 컴포넌트 (30+)
│ ├── ui/ # shadcn/ui 컴포넌트 (53개)
│ │ ├── button.tsx
│ │ ├── dialog.tsx
│ │ ├── table.tsx
│ │ └── ...
│ └── figma/ # Figma 전용 컴포넌트
│ └── ImageWithFallback.tsx # 이미지 폴백 처리
├── styles/
│ └── globals.css # 글로벌 스타일 & 테마
├── guidelines/
│ └── Guidelines.md # 추가 가이드라인
└── [scripts].js # 유틸리티 스크립트
컴포넌트 분류
1. 페이지 컴포넌트 (components/)
Dashboard.tsx- CEO 대시보드SalesManagement.tsx- 판매관리ProductionManagement.tsx- 생산관리 (최대 규모)QualityManagement.tsx- 품질관리MaterialManagement.tsx- 자재관리ShippingManagement.tsx- 출고관리HRManagement.tsx- 인사관리ApprovalManagement.tsx- 전자결재AccountingManagement.tsx- 회계관리MasterData.tsx- 기준정보- 등 30+ 컴포넌트
2. UI 컴포넌트 (components/ui/)
- 53개의 재사용 가능한 UI 컴포넌트
- shadcn/ui 기반
- 수정 금지 (새로운 컴포넌트 생성 시에만)
3. 특수 컴포넌트 (components/figma/)
ImageWithFallback.tsx- 이미지 로딩 및 폴백- 수정 금지 (시스템 보호 파일)
📝 코딩 규칙
1. 일반 원칙
// ✅ DO: 명확하고 읽기 쉬운 코드
function calculateTotalPrice(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// ❌ DON'T: 불명확한 변수명과 로직
function calc(arr: any[]): any {
return arr.reduce((a, b) => a + b.p, 0);
}
2. 코드 포맷팅
// 들여쓰기: 2 스페이스
// 세미콜론: 사용
// 따옴표: 쌍따옴표 우선
// 줄 길이: 최대 100자 권장
export function MyComponent({ title, description }: Props) {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="p-4">
<h1>{title}</h1>
<p>{description}</p>
</div>
);
}
3. Import 순서
// 1. React 관련
import { useState, useEffect } from "react";
// 2. UI 컴포넌트 (shadcn/ui)
import { Button } from "./ui/button";
import { Dialog, DialogContent } from "./ui/dialog";
import { Card, CardContent, CardHeader } from "./ui/card";
// 3. 아이콘
import { Plus, Edit, Trash2 } from "lucide-react";
// 4. 외부 라이브러리
import { format } from "date-fns";
import { ko } from "date-fns/locale";
import { BarChart, Bar } from "recharts";
// 5. 타입 정의
interface Props {
title: string;
}
🎨 컴포넌트 개발
1. 컴포넌트 구조
import { useState } from "react";
import { Button } from "./ui/button";
// Props 타입 정의
interface MyComponentProps {
title: string;
onSave?: () => void;
}
// 컴포넌트 선언
export function MyComponent({ title, onSave }: MyComponentProps) {
// 1. State 선언
const [data, setData] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState(false);
// 2. 핸들러 함수
const handleClick = () => {
console.log("Clicked");
onSave?.();
};
// 3. useEffect (필요시)
useEffect(() => {
// 초기 데이터 로드
}, []);
// 4. 조건부 렌더링
if (isLoading) {
return <div>Loading...</div>;
}
// 5. JSX 반환
return (
<div className="p-4">
<h1>{title}</h1>
<Button onClick={handleClick}>저장</Button>
</div>
);
}
2. 페이지 컴포넌트 템플릿
import { useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card";
import { Button } from "./ui/button";
import { Plus, Download } from "lucide-react";
export function MyPage() {
const [activeTab, setActiveTab] = useState("list");
return (
<div className="min-h-screen bg-background p-4 md:p-6 lg:p-8">
{/* 헤더 */}
<div className="bg-card border border-border/20 rounded-xl p-6 mb-8">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
<div>
<h1 className="text-3xl font-bold text-foreground mb-2">페이지 제목</h1>
<p className="text-muted-foreground">페이지 설명</p>
</div>
<div className="flex space-x-3">
<Button variant="outline">
<Download className="h-4 w-4 mr-2" />
내보내기
</Button>
<Button>
<Plus className="h-4 w-4 mr-2" />
추가
</Button>
</div>
</div>
</div>
{/* 메인 콘텐츠 */}
<Card>
<CardHeader>
<CardTitle>섹션 제목</CardTitle>
</CardHeader>
<CardContent>
{/* 내용 */}
</CardContent>
</Card>
</div>
);
}
3. 반응형 컴포넌트 패턴
// 데스크톱: 테이블 / 모바일: 카드
export function ResponsiveList({ items }: Props) {
return (
<>
{/* 데스크톱 테이블 (hidden on mobile) */}
<div className="hidden md:block">
<Table>
<TableHeader>
<TableRow>
<TableHead>이름</TableHead>
<TableHead>상태</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{items.map((item) => (
<TableRow key={item.id}>
<TableCell>{item.name}</TableCell>
<TableCell>{item.status}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
{/* 모바일 카드 (visible on mobile) */}
<div className="md:hidden space-y-4">
{items.map((item) => (
<Card key={item.id}>
<CardContent className="p-4">
<div className="font-semibold">{item.name}</div>
<div className="text-sm text-muted-foreground">{item.status}</div>
</CardContent>
</Card>
))}
</div>
</>
);
}
🎨 스타일링 가이드
1. Tailwind CSS 기본 원칙
✅ DO: Tailwind 유틸리티 클래스 사용
<div className="flex items-center justify-between p-4 bg-card rounded-lg border border-border">
<h2 className="text-xl text-foreground">제목</h2>
<Button variant="outline" size="sm">버튼</Button>
</div>
❌ DON'T: 인라인 스타일 사용
// 피하기
<div style={{ display: "flex", padding: "16px" }}>
2. 색상 사용
// ✅ CSS 변수 사용 (테마 대응)
className="bg-primary text-primary-foreground"
className="bg-card text-card-foreground"
className="bg-destructive text-destructive-foreground"
className="border-border"
className="text-muted-foreground"
// ❌ 하드코딩된 색상 (피하기)
className="bg-blue-500 text-white"
3. 반응형 디자인
// Mobile First 접근
className="
p-4 // 모바일: 16px padding
md:p-6 // 태블릿: 24px padding
lg:p-8 // 데스크톱: 32px padding
flex-col // 모바일: 세로 방향
md:flex-row // 태블릿+: 가로 방향
text-sm // 모바일: 작은 텍스트
md:text-base // 태블릿+: 기본 크기
"
4. 간격 시스템
// Spacing Scale (4px 단위)
className="p-2" // 8px
className="p-4" // 16px
className="p-6" // 24px
className="p-8" // 32px
className="gap-2" // 8px
className="gap-4" // 16px
className="gap-6" // 24px
5. 폰트 크기/굵기 사용 제한
// ⚠️ 주의: 폰트 크기, 굵기, 라인 높이는 기본값 사용
// globals.css에 정의된 기본 스타일 활용
// ❌ 피하기 (특별한 요구사항 없으면)
className="text-2xl font-bold leading-tight"
// ✅ 권장 (기본값 사용)
<h1>제목</h1> // globals.css의 h1 스타일 자동 적용
<p>내용</p> // globals.css의 p 스타일 자동 적용
📘 TypeScript 가이드
1. 타입 정의
Interface vs Type
// ✅ Props는 interface 사용 (확장 가능)
interface ButtonProps {
label: string;
onClick?: () => void;
variant?: "primary" | "secondary";
}
// ✅ 유니온 타입은 type 사용
type Status = "active" | "inactive" | "pending";
// ✅ 복잡한 타입은 type 사용
type ComplexType = {
id: string;
data: Record<string, unknown>;
} & BaseType;
타입 재사용
// 공통 타입 정의
interface BaseEntity {
id: string;
createdAt: string;
updatedAt: string;
}
interface Product extends BaseEntity {
name: string;
price: number;
}
interface Order extends BaseEntity {
productId: string;
quantity: number;
}
2. 타입 안정성
✅ DO: 명시적 타입 지정
// State 타입 명시
const [items, setItems] = useState<Product[]>([]);
const [selectedId, setSelectedId] = useState<string | null>(null);
// 함수 매개변수 타입 명시
function calculateTotal(items: Product[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// 이벤트 핸들러 타입
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
console.log(event.currentTarget);
};
❌ DON'T: any 타입 사용
// ❌ 피하기
const [data, setData] = useState<any>([]);
function process(input: any): any { }
// ✅ 대신 사용
const [data, setData] = useState<unknown[]>([]);
function process(input: unknown): Result { }
3. 옵셔널 체이닝 & Nullish Coalescing
// ✅ 옵셔널 체이닝
const userName = user?.profile?.name;
// ✅ Nullish Coalescing
const displayName = user?.name ?? "Guest";
// ✅ 옵셔널 콜백
onSave?.();
🔄 상태 관리
1. useState 패턴
// ✅ 단순 상태
const [isOpen, setIsOpen] = useState(false);
const [count, setCount] = useState(0);
// ✅ 객체 상태 (불변성 유지)
const [user, setUser] = useState({ name: "", email: "" });
const updateName = (newName: string) => {
setUser(prev => ({ ...prev, name: newName }));
};
// ✅ 배열 상태
const [items, setItems] = useState<Item[]>([]);
const addItem = (item: Item) => {
setItems(prev => [...prev, item]);
};
const removeItem = (id: string) => {
setItems(prev => prev.filter(item => item.id !== id));
};
2. useEffect 패턴
// ✅ 컴포넌트 마운트 시 1회 실행
useEffect(() => {
// 초기 데이터 로드
fetchData();
}, []); // 빈 의존성 배열
// ✅ 특정 값 변경 시 실행
useEffect(() => {
if (selectedId) {
loadDetails(selectedId);
}
}, [selectedId]); // selectedId 변경 감지
// ✅ 클린업 함수
useEffect(() => {
const timer = setInterval(() => {
// 주기적 작업
}, 1000);
return () => {
clearInterval(timer); // 컴포넌트 언마운트 시 정리
};
}, []);
3. 로컬 상태 vs Props
// ✅ 로컬에서만 사용되는 UI 상태
const [isHovered, setIsHovered] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
// ✅ 부모로부터 받는 데이터
interface Props {
data: Product[]; // 읽기 전용 데이터
onUpdate: () => void; // 상태 변경은 부모가 처리
}
📂 파일 명명 규칙
1. 컴포넌트 파일
PascalCase.tsx
├── Dashboard.tsx
├── SalesManagement.tsx
├── ProductionManagement.tsx
└── UserProfile.tsx
2. UI 컴포넌트 (shadcn/ui)
kebab-case.tsx
├── button.tsx
├── dialog.tsx
├── table.tsx
└── dropdown-menu.tsx
3. 유틸리티 파일
camelCase.ts / kebab-case.ts
├── utils.ts
├── helpers.ts
└── use-mobile.ts
4. 문서 파일
UPPER_CASE.md / PascalCase.md
├── README.md
├── TECH_STACK.md
├── DEVELOPMENT_ENVIRONMENT.md
└── Guidelines.md
5. 스타일 파일
kebab-case.css / lowercase.css
├── globals.css
└── custom-styles.css
🔀 Git 워크플로우
1. 브랜치 전략
main # 프로덕션 브랜치
├── develop # 개발 브랜치
├── feature/* # 기능 개발
├── bugfix/* # 버그 수정
└── hotfix/* # 긴급 수정
2. 커밋 메시지 규칙
# 형식: <타입>: <제목>
feat: 판매관리 견적 산출 기능 추가
fix: 생산관리 모달 스크롤 오류 수정
style: Dashboard 레이아웃 개선
refactor: MaterialManagement 컴포넌트 리팩토링
docs: README 업데이트
test: QualityManagement 테스트 추가
chore: 의존성 업데이트
3. 커밋 타입
feat: 새로운 기능fix: 버그 수정style: UI/스타일 변경refactor: 코드 리팩토링docs: 문서 수정test: 테스트 추가/수정chore: 빌드, 설정 등
🧪 테스팅
1. 컴포넌트 테스트 체크리스트
// 수동 테스트 체크리스트
// [ ] 컴포넌트가 정상적으로 렌더링되는가?
// [ ] Props가 올바르게 전달되는가?
// [ ] 이벤트 핸들러가 작동하는가?
// [ ] 조건부 렌더링이 올바른가?
// [ ] 에러 상태가 처리되는가?
// [ ] 로딩 상태가 표시되는가?
2. 반응형 테스트
브레이크포인트 테스트:
[ ] Mobile (< 768px)
[ ] Tablet (768px - 1024px)
[ ] Desktop (> 1024px)
기기별 테스트:
[ ] iPhone (Safari)
[ ] Android (Chrome)
[ ] iPad (Safari)
[ ] Desktop (Chrome, Firefox, Safari)
3. 브라우저 호환성
[ ] Chrome (최신)
[ ] Firefox (최신)
[ ] Safari (최신)
[ ] Edge (최신)
⚡ 성능 최적화
1. 리렌더링 최적화
// ✅ useMemo - 비용이 큰 계산 메모이제이션
const expensiveValue = useMemo(() => {
return items.reduce((sum, item) => sum + item.price, 0);
}, [items]);
// ✅ useCallback - 함수 메모이제이션
const handleClick = useCallback((id: string) => {
console.log("Clicked:", id);
}, []);
// ✅ React.memo - 컴포넌트 메모이제이션
export const MemoizedComponent = memo(function MyComponent({ data }: Props) {
return <div>{data}</div>;
});
2. 조건부 렌더링
// ✅ 불필요한 컴포넌트 렌더링 방지
{isVisible && <ExpensiveComponent />}
// ✅ 로딩 상태
{isLoading ? <Skeleton /> : <Content />}
3. 이미지 최적화
// ✅ ImageWithFallback 컴포넌트 사용
import { ImageWithFallback } from "./components/figma/ImageWithFallback";
<ImageWithFallback
src={imageUrl}
alt="제품 이미지"
className="w-full h-auto"
/>
♿ 접근성 (Accessibility)
1. 시맨틱 HTML
// ✅ 의미있는 HTML 태그 사용
<header>
<nav>
<ul>
<li><a href="/">홈</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>제목</h1>
<p>내용</p>
</article>
</main>
<footer>
<p>Copyright 2025</p>
</footer>
2. ARIA 속성
// ✅ 스크린 리더를 위한 레이블
<button aria-label="메뉴 열기">
<Menu />
</button>
// ✅ 상태 표시
<div role="alert" aria-live="polite">
저장되었습니다.
</div>
// ✅ 숨김 콘텐츠
<DialogTitle className="sr-only">대화상자 제목</DialogTitle>
3. 키보드 네비게이션
// ✅ Tab 키로 이동 가능
<button>클릭 가능</button>
<a href="/page">링크</a>
// ✅ Enter/Space로 활성화
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter" || e.key === " ") {
handleClick();
}
};
🔒 보안
1. XSS 방지
// ✅ React는 기본적으로 XSS 방지
<div>{userInput}</div> // 자동 이스케이프
// ❌ dangerouslySetInnerHTML 사용 금지 (특별한 경우 제외)
<div dangerouslySetInnerHTML={{ __html: content }} />
2. 민감 정보 처리
// ❌ 클라이언트 코드에 민감 정보 하드코딩 금지
const API_KEY = "secret-key-123"; // 절대 금지!
// ✅ 환경 변수 사용 또는 서버사이드 처리
const API_URL = process.env.VITE_API_URL;
3. 입력 검증
// ✅ 사용자 입력 검증
const validateEmail = (email: string): boolean => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
};
const handleSubmit = (email: string) => {
if (!validateEmail(email)) {
alert("올바른 이메일을 입력하세요.");
return;
}
// 처리
};
📚 문서화
1. 컴포넌트 문서화
/**
* 사용자 프로필 카드 컴포넌트
*
* @param {string} name - 사용자 이름
* @param {string} email - 사용자 이메일
* @param {() => void} onEdit - 편집 버튼 클릭 핸들러
*
* @example
* <UserProfileCard
* name="홍길동"
* email="hong@example.com"
* onEdit={() => console.log("edit")}
* />
*/
export function UserProfileCard({ name, email, onEdit }: UserProfileCardProps) {
// ...
}
2. 복잡한 로직 주석
// ✅ 복잡한 비즈니스 로직에 주석 추가
function calculateDiscount(price: number, quantity: number): number {
// 10개 이상 구매 시 10% 할인
// 50개 이상 구매 시 20% 할인
// 100개 이상 구매 시 30% 할인
if (quantity >= 100) {
return price * 0.7;
} else if (quantity >= 50) {
return price * 0.8;
} else if (quantity >= 10) {
return price * 0.9;
}
return price;
}
3. TODO 주석
// TODO: 성능 최적화 필요
// FIXME: 특정 조건에서 버그 발생
// HACK: 임시 해결책, 추후 개선 필요
// NOTE: 중요한 정보 또는 주의사항
✨ 베스트 프랙티스
1. DRY (Don't Repeat Yourself)
// ❌ 중복 코드
function formatUserName1(name: string) {
return name.trim().toUpperCase();
}
function formatProductName(name: string) {
return name.trim().toUpperCase();
}
// ✅ 재사용 가능한 함수
function formatName(name: string): string {
return name.trim().toUpperCase();
}
const userName = formatName(user.name);
const productName = formatName(product.name);
2. 단일 책임 원칙
// ❌ 하나의 컴포넌트가 너무 많은 역할
function ComplexComponent() {
// 데이터 로딩
// 폼 처리
// 차트 렌더링
// 테이블 렌더링
// ... 1000+ 줄
}
// ✅ 책임 분리
function DataContainer() {
return (
<>
<DataForm />
<DataChart />
<DataTable />
</>
);
}
3. 명확한 변수명
// ❌ 불명확한 이름
const d = new Date();
const arr = [...items];
const temp = x * y;
// ✅ 명확한 이름
const currentDate = new Date();
const sortedItems = [...items];
const totalPrice = quantity * unitPrice;
4. Early Return 패턴
// ❌ 중첩된 조건문
function processUser(user: User) {
if (user) {
if (user.isActive) {
if (user.hasPermission) {
// 처리
}
}
}
}
// ✅ Early Return
function processUser(user: User) {
if (!user) return;
if (!user.isActive) return;
if (!user.hasPermission) return;
// 처리
}
5. 에러 처리
// ✅ Try-Catch로 에러 처리
async function fetchData() {
try {
const response = await fetch("/api/data");
const data = await response.json();
return data;
} catch (error) {
console.error("데이터 로드 실패:", error);
return null;
}
}
// ✅ 에러 상태 표시
const [error, setError] = useState<string | null>(null);
{error && (
<Alert variant="destructive">
<AlertTitle>오류</AlertTitle>
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
🚨 일반적인 실수 & 해결책
1. Key Props 누락
// ❌ key 없이 리스트 렌더링
{items.map(item => <div>{item.name}</div>)}
// ✅ 고유한 key 사용
{items.map(item => (
<div key={item.id}>{item.name}</div>
))}
2. State 직접 수정
// ❌ State 직접 수정
const [items, setItems] = useState([]);
items.push(newItem); // 금지!
// ✅ 새로운 배열 생성
setItems([...items, newItem]);
setItems(prev => [...prev, newItem]);
3. useEffect 의존성 배열 누락
// ❌ 의존성 배열 누락
useEffect(() => {
fetchData(userId);
}); // 무한 루프!
// ✅ 의존성 명시
useEffect(() => {
fetchData(userId);
}, [userId]);
4. 불필요한 리렌더링
// ❌ 매번 새로운 객체 생성
<Component style={{ margin: 10 }} />
// ✅ 상수로 분리
const componentStyle = { margin: 10 };
<Component style={componentStyle} />
📋 체크리스트
코드 리뷰 전 체크리스트
코드 품질:
[ ] TypeScript 타입 오류 없음
[ ] ESLint 경고 없음
[ ] 불필요한 console.log 제거
[ ] 주석 작성 (복잡한 로직)
[ ] 변수명이 명확함
기능:
[ ] 요구사항 모두 구현
[ ] 에러 처리 구현
[ ] 로딩 상태 구현
[ ] 엣지 케이스 처리
UI/UX:
[ ] 반응형 디자인 동작
[ ] 모바일/데스크톱 테스트
[ ] 접근성 준수
[ ] 키보드 네비게이션 가능
성능:
[ ] 불필요한 리렌더링 없음
[ ] 큰 리스트 최적화
[ ] 이미지 최적화
[ ] 번들 크기 확인
문서화:
[ ] README 업데이트 (필요시)
[ ] 변경 사항 기록
[ ] API 문서 업데이트 (필요시)
배포 전 체크리스트
[ ] 모든 테스트 통과
[ ] 브라우저 호환성 확인
[ ] 성능 측정 완료
[ ] 보안 취약점 점검
[ ] 백업 완료
[ ] 롤백 계획 수립
🎓 학습 리소스
필수 문서
TECH_STACK.md- 기술 스택DEVELOPMENT_ENVIRONMENT.md- 개발 환경guidelines/Guidelines.md- 추가 가이드
공식 문서
추천 학습 경로
- 1주차: React & TypeScript 기초
- 2주차: Tailwind CSS & shadcn/ui
- 3주차: 프로젝트 구조 파악
- 4주차: 실제 컴포넌트 개발
🎯 핵심 원칙 요약
코드 작성 원칙
- 타입 안정성: 모든 코드에 TypeScript 타입 적용
- 재사용성: DRY 원칙 준수, 공통 컴포넌트 활용
- 가독성: 명확한 변수명, 적절한 주석
- 성능: 불필요한 리렌더링 방지
- 접근성: 모든 사용자가 사용 가능하도록
UI/UX 원칙
- 반응형: 모든 화면 크기 대응
- 일관성: 디자인 시스템 준수
- 피드백: 로딩, 에러, 성공 상태 표시
- 접근성: 키보드, 스크린 리더 지원
협업 원칙
- 문서화: 코드와 변경사항 문서화
- 커뮤니케이션: 불확실한 부분 질문
- 코드 리뷰: 건설적인 피드백
- 지식 공유: 학습 내용 팀과 공유
📞 도움 받기
질문하기 전 체크
- 공식 문서 확인
- 기존 코드 참고
- 에러 메시지 검색
질문 형식
제목: [컴포넌트명] 간단한 문제 설명
환경:
- 파일: components/MyComponent.tsx
- 브라우저: Chrome 120
문제:
[상세한 문제 설명]
시도한 해결책:
1. ...
2. ...
에러 메시지:
[에러 메시지 복사]
🎉 결론
이 가이드라인은 SAM MES 솔루션 개발의 기준이 됩니다.
핵심 포인트: ✅ TypeScript로 타입 안정성 확보 ✅ Tailwind CSS로 일관된 스타일링 ✅ 반응형 디자인으로 모든 기기 지원 ✅ shadcn/ui로 빠른 개발 ✅ 베스트 프랙티스 준수
이 가이드를 따르면 높은 품질의 코드를 작성하고 유지보수가 쉬운 시스템을 구축할 수 있습니다.
문서 작성일: 2025년 10월 17일 버전: 1.0.0 작성자: SAM MES 개발팀
Happy Coding! 🚀