# React 프론트엔드 구조 원칙 **작성일**: 2025-11-29 **수정일**: 2025-12-02 (배열/객체 필드 검증 필수 원칙 추가) **참고**: 311_FastAPI_구조_원칙.md, 312_문서_작성_원칙.md ## 1. 컴포넌트 설계 원칙 ### Single Responsibility Principle (SRP) - 각 컴포넌트는 하나의 책임만 수행 - 큰 컴포넌트는 작은 서브 컴포넌트나 훅으로 분리 - UI 렌더링과 비즈니스 로직 분리 ### 컴포넌트 분리 기준 - 300줄 이상: 서브 컴포넌트 또는 커스텀 훅으로 분리 검토 - 1000줄 이상: Monolithic Component로 간주, 리팩토링 필수 - UI + API + State + Events 모두 혼재: 계층 분리 필요 ## 2. 비즈니스 로직 분리 ### Custom Hooks 패턴 - 데이터 fetching 로직: `useFetch`, `useQuery` 등 커스텀 훅으로 추출 - 상태 관리 로직: `useState` 복잡도가 높으면 커스텀 훅으로 분리 - UI 컴포넌트는 렌더링과 이벤트 핸들링만 담당 ### 계층 분리 ``` UI Components (렌더링) ↓ Custom Hooks (비즈니스 로직) ↓ API Services (통신) ↓ State Management (전역 상태) ``` ## 3. 상태 관리 원칙 ### Immutability - 상태 직접 변경 금지: 항상 새로운 객체/배열 생성 - 예측 가능한 상태 업데이트 보장 - React 리렌더링 최적화 ### 상태 관리 전략 - 컴포넌트 내부 상태: `useState` (로컬 UI 상태) - 전역 상태: Context API 또는 상태 관리 라이브러리 (Zustand/Recoil) - 서버 상태: React Query, SWR 등 전용 라이브러리 ### Prop Drilling 회피 - 3단계 이상 props 전달 시 Context API 또는 상태 관리 도입 - 불필요한 중간 컴포넌트 통과 제거 ## 4. 파일 및 폴더 구조 ### 권장 구조 ``` src/ ├── components/ # 재사용 가능한 UI 컴포넌트 │ ├── ui/ # 기본 UI 컴포넌트 (버튼, 입력 등) │ └── features/ # 기능별 컴포넌트 ├── hooks/ # 커스텀 훅 ├── services/ # API 통신 로직 ├── stores/ # 전역 상태 관리 (선택) ├── utils/ # 유틸리티 함수 ├── types/ # TypeScript 타입 정의 └── pages/ # 페이지 컴포넌트 ``` ### 파일 명명 규칙 - 컴포넌트: `PascalCase.tsx` (예: `ChatInterface.tsx`) - 훅: `use` 접두사 + `PascalCase.ts` (예: `useChat.ts`) - 유틸: `camelCase.ts` (예: `formatDate.ts`) - 타입: `PascalCase.ts` (예: `Message.ts`) ## 5. 네이밍 규칙 ### 명확한 네이밍 - 구체적이고 설명적인 이름 사용 - 축약어 지양, 의도가 명확한 이름 - 예: `handleSendMessage` > `handleSend`, `chatHistory` > `data` ### 변수/함수 네이밍 - 컴포넌트: `PascalCase` - 함수: `camelCase`, 동사로 시작 (`handle`, `fetch`, `update`) - 상수: `UPPER_SNAKE_CASE` - boolean: `is`, `has`, `should` 접두사 ## 6. 코드 품질 원칙 ### useEffect 의존성 관리 - 의존성 배열 정확히 명시 - 중복 호출 및 무한 루프 방지 - cleanup 함수 적절히 사용 ### 성능 최적화 - 불필요한 리렌더링 방지: `React.memo`, `useMemo`, `useCallback` 적절히 활용 - 대용량 리스트: 가상화 (virtualization) 고려 - 이미지/리소스: lazy loading 적용 ### 타입 안전성 - TypeScript 타입 정의 명확히 - `any` 타입 최소화 - 인터페이스/타입 재사용 ## 7. 금지 사항 - ❌ 하드코딩된 값: 상수, 설정값은 환경변수 또는 설정 파일로 관리 - ❌ Monolithic Component: 1000줄 이상 컴포넌트 - ❌ 컴포넌트 내 비즈니스 로직: 커스텀 훅으로 분리 - ❌ 상태 직접 변경: Immutability 원칙 위반 - ❌ console.log 디버그 코드: 프로덕션 코드에 남기지 않음 - ❌ 순환 import - ❌ Prop Drilling: 3단계 이상 전달 시 상태 관리 도입 ## 8. 환경별 코드 분리 원칙 **핵심 원칙**: 개발/프로덕션 환경 구분 필수 - 개발용 기능은 `process.env.NODE_ENV === "development"` 조건으로 숨김 - 프로덕션 배포 전 개발 기능 노출 여부 확인 - 환경별 다른 동작이 필요한 경우 조건부 렌더링/실행 ## 9. 에러 처리 일관성 원칙 **핵심 원칙**: 환경별 일관된 에러 로깅 및 HTTP 상태 코드별 처리 - `console.error` 대신 환경별 로깅 유틸리티 사용 - 프로덕션 환경에서도 에러 로그 기록 - 로깅 유틸리티는 개발/프로덕션 환경에 따라 적절히 처리 ### HTTP 상태 코드별 처리 규칙 **에러 메시지 디자인 원칙**: HTTP 레벨 에러와 사용자 메시지를 분리 - **404 Not Found**: 리소스가 아직 생성되지 않음 → 재시도/폴링 계속 (예: 평가 진행 중) - **504 Gateway Timeout**: 게이트웨이 타임아웃 → 사용자에게 "분석 시간이 초과되었습니다" 또는 재시도 안내 - **502 Bad Gateway**: 백엔드 연결 실패 → 사용자에게 "서버 연결 오류" 안내, 재시도 제안 - **500 Internal Server Error**: 서버 오류 → 즉시 중단, 사용자에게 "서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요" 안내 **금지 사항**: - ❌ 모든 에러에 동일한 템플릿 메시지 사용 (예: "(템플릿) 평가 처리 중 오류가 발생했습니다") - ❌ HTTP 상태 코드를 사용자에게 직접 노출 - ❌ 에러 원인 파악 없이 일반적인 메시지만 표시 **권장 사항**: - 에러 유형별로 명확한 사용자 메시지 제공 - 원인 파악은 HTTP 상태 코드와 백엔드 로그로 교차 검증 - 폴링/재시도 가능한 에러(404, 504)와 치명적 에러(500)를 구분하여 처리 ## 10. 데이터 검증 원칙 **핵심 원칙**: 백엔드 응답 구조 검증 및 폴백 처리 - 백엔드 응답 구조 검증 (빈 배열, 누락 필드) - 데이터 누락 시 사용자에게 명확한 안내 메시지 제공 - 예상치 못한 데이터 구조에 대한 폴백 처리 ### 배열/객체 필드 검증 필수 **문제**: 백엔드가 배열을 예상했지만 `null` 또는 `undefined`를 반환할 경우 `TypeError: Cannot read property 'map' of null` 발생 **해결책**: - 배열 필드: `Array.isArray(data.field) ? data.field : []` 또는 `data.field ?? []` - 객체 필드: 옵셔널 체이닝(`?.`) 사용 - 기본값 설정: `const items = result.page_evaluations ?? [];` **예시**: ```typescript // ❌ 금지: 직접 map 사용 result.page_evaluations.map(...) // ✅ 권장: Array.isArray 체크 const evaluations = Array.isArray(result.page_evaluations) ? result.page_evaluations : []; evaluations.map(...) ``` ## 11. 체크리스트 코드 작성 전/후 확인: - [ ] 각 컴포넌트가 단일 책임을 수행하는가? - [ ] 비즈니스 로직이 커스텀 훅으로 분리되었는가? - [ ] 상태 변경이 Immutability 원칙을 따르는가? - [ ] 파일 크기가 300줄 이하인가? (예외: 핵심 컴포넌트는 가급적 유지) - [ ] 하드코딩된 값이 없는가? - [ ] Prop Drilling이 3단계 이상인가? (상태 관리 필요) - [ ] TypeScript 타입이 명확히 정의되었는가? - [ ] useEffect 의존성이 정확한가? ## 12. 참고 - 상위 원칙: 이 문서는 일반적인 React 프로젝트 원칙을 다룹니다. - 프로젝트별 특화 규칙: 각 프로젝트의 README나 문서에 추가 규칙 명시 - 백엔드 원칙: `311_FastAPI_구조_원칙.md` 참고 - 문서 작성 원칙: `312_문서_작성_원칙.md` 참고