Files
sam-design/src/DEVELOPMENT_GUIDELINES.md
정재웅 060b9ce2ef 프로젝트 초기 설정 및 구조 추가
- Vite + React 프로젝트 구조 설정
- 불필요한 PDF 파일 삭제

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 13:01:43 +09:00

25 KiB

📘 SAM MES 솔루션 개발 가이드라인

📋 목차

  1. 시작하기
  2. 프로젝트 구조
  3. 코딩 규칙
  4. 컴포넌트 개발
  5. 스타일링 가이드
  6. TypeScript 가이드
  7. 상태 관리
  8. 파일 명명 규칙
  9. Git 워크플로우
  10. 테스팅
  11. 성능 최적화
  12. 접근성
  13. 보안
  14. 문서화
  15. 베스트 프랙티스

🚀 시작하기

프로젝트 개요

SAM MES는 중소 및 중견기업을 위한 완전한 제조실행시스템(MES) 솔루션입니다.

핵심 기술

  • React 18+ (TypeScript)
  • Tailwind CSS v4.0
  • shadcn/ui 컴포넌트
  • Recharts (데이터 시각화)
  • Figma Make 플랫폼

개발 환경 설정

  1. 프로젝트 파일 구조 파악
  2. TECH_STACK.md 문서 읽기
  3. DEVELOPMENT_ENVIRONMENT.md 문서 읽기
  4. 기존 컴포넌트 코드 분석

📁 프로젝트 구조

디렉토리 구조

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 문서 업데이트 (필요시)

배포 전 체크리스트

[ ] 모든 테스트 통과
[ ] 브라우저 호환성 확인
[ ] 성능 측정 완료
[ ] 보안 취약점 점검
[ ] 백업 완료
[ ] 롤백 계획 수립

🎓 학습 리소스

필수 문서

  1. TECH_STACK.md - 기술 스택
  2. DEVELOPMENT_ENVIRONMENT.md - 개발 환경
  3. guidelines/Guidelines.md - 추가 가이드

공식 문서

추천 학습 경로

  1. 1주차: React & TypeScript 기초
  2. 2주차: Tailwind CSS & shadcn/ui
  3. 3주차: 프로젝트 구조 파악
  4. 4주차: 실제 컴포넌트 개발

🎯 핵심 원칙 요약

코드 작성 원칙

  1. 타입 안정성: 모든 코드에 TypeScript 타입 적용
  2. 재사용성: DRY 원칙 준수, 공통 컴포넌트 활용
  3. 가독성: 명확한 변수명, 적절한 주석
  4. 성능: 불필요한 리렌더링 방지
  5. 접근성: 모든 사용자가 사용 가능하도록

UI/UX 원칙

  1. 반응형: 모든 화면 크기 대응
  2. 일관성: 디자인 시스템 준수
  3. 피드백: 로딩, 에러, 성공 상태 표시
  4. 접근성: 키보드, 스크린 리더 지원

협업 원칙

  1. 문서화: 코드와 변경사항 문서화
  2. 커뮤니케이션: 불확실한 부분 질문
  3. 코드 리뷰: 건설적인 피드백
  4. 지식 공유: 학습 내용 팀과 공유

📞 도움 받기

질문하기 전 체크

  1. 공식 문서 확인
  2. 기존 코드 참고
  3. 에러 메시지 검색

질문 형식

제목: [컴포넌트명] 간단한 문제 설명

환경:
- 파일: components/MyComponent.tsx
- 브라우저: Chrome 120

문제:
[상세한 문제 설명]

시도한 해결책:
1. ...
2. ...

에러 메시지:
[에러 메시지 복사]

🎉 결론

이 가이드라인은 SAM MES 솔루션 개발의 기준이 됩니다.

핵심 포인트: TypeScript로 타입 안정성 확보 Tailwind CSS로 일관된 스타일링 반응형 디자인으로 모든 기기 지원 shadcn/ui로 빠른 개발 베스트 프랙티스 준수

이 가이드를 따르면 높은 품질의 코드를 작성하고 유지보수가 쉬운 시스템을 구축할 수 있습니다.


문서 작성일: 2025년 10월 17일 버전: 1.0.0 작성자: SAM MES 개발팀

Happy Coding! 🚀