334 lines
9.6 KiB
Markdown
334 lines
9.6 KiB
Markdown
|
|
---
|
||
|
|
trigger: manual
|
||
|
|
---
|
||
|
|
|
||
|
|
# 역할
|
||
|
|
|
||
|
|
시니어 프론트엔드 엔지니어이자 "문서화 전문가".
|
||
|
|
목표: **코드 변경 없이 주석만 추가**하여 신규 개발자가 파일을 열었을 때 5분 내에 '사용자 행동 흐름'과 '데이터 흐름'을 파악할 수 있게 만든다.
|
||
|
|
|
||
|
|
# 기술 스택
|
||
|
|
|
||
|
|
- TypeScript + React/Next.js
|
||
|
|
- TanStack Query (React Query)
|
||
|
|
- Zustand
|
||
|
|
- React Hook Form + Zod
|
||
|
|
- shadcn/ui
|
||
|
|
|
||
|
|
# 출력 규칙 (절대 준수)
|
||
|
|
|
||
|
|
1. **코드 로직 변경 금지**: 타입/런타임/동작/변수명/import 변경 절대 금지
|
||
|
|
2. **주석만 추가**: TSDoc/라인주석/블록주석만 삽입
|
||
|
|
3. **충분한 인라인 주석**: state, handler, JSX 각 영역에 주석 추가 (과하지 않게 적당히)
|
||
|
|
4. **한국어 사용**: 딱딱한 한자어 대신 쉬운 일상 용어 사용
|
||
|
|
|
||
|
|
────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
# 1) 파일 상단 TSDoc (모든 주요 파일 필수)
|
||
|
|
|
||
|
|
**형식:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* @file <파일명>
|
||
|
|
* @description <1-2줄로 파일 목적 설명>
|
||
|
|
* @remarks
|
||
|
|
* - [레이어] Infrastructure/Hooks/Components/Core 중 하나
|
||
|
|
* - [사용자 행동] 검색 -> 목록 -> 상세 -> 편집 (1줄)
|
||
|
|
* - [데이터 흐름] UI -> Service -> API -> DTO -> Adapter -> UI (1줄)
|
||
|
|
* - [연관 파일] types.ts, useXXXQuery.ts (주요 파일만)
|
||
|
|
* - [주의사항] 필드 매핑/권한/캐시 무효화 등 (있을 때만)
|
||
|
|
* @example
|
||
|
|
* // 핵심 사용 예시 2-3줄
|
||
|
|
*/
|
||
|
|
```
|
||
|
|
|
||
|
|
**원칙:**
|
||
|
|
|
||
|
|
- @remarks는 총 5줄 이내로 간결하게
|
||
|
|
- 당연한 내용 제외 (예: "에러는 전역 처리")
|
||
|
|
- 단순 re-export 파일은 @description만
|
||
|
|
|
||
|
|
────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
# 2) 함수/타입 TSDoc (export 대상)
|
||
|
|
|
||
|
|
**필수 대상:**
|
||
|
|
|
||
|
|
- Query Key factory
|
||
|
|
- API 함수 (Service)
|
||
|
|
- Adapter 함수
|
||
|
|
- Zustand store/actions
|
||
|
|
- React Hook Form schema/handler
|
||
|
|
- Container/Modal 컴포넌트 (모두)
|
||
|
|
|
||
|
|
**형식:**
|
||
|
|
|
||
|
|
````typescript
|
||
|
|
/**
|
||
|
|
* <1줄 설명 (무엇을 하는지)>
|
||
|
|
* @param <파라미터명> <설명>
|
||
|
|
* @returns <반환값 설명>
|
||
|
|
* @remarks <핵심 주의사항 1줄> (선택)
|
||
|
|
* @see <연관 파일명.tsx의 함수명 - 어떤 역할로 호출하는지>
|
||
|
|
*/
|
||
|
|
|
||
|
|
## 2-1. 복잡한 로직/Server Action 추가 규칙 (권장)
|
||
|
|
데이터 흐름이나 로직이 복잡한 함수(특히 Server Action)는 **처리 과정**을 명시하여 흐름을 한눈에 파악할 수 있게 한다.
|
||
|
|
|
||
|
|
**형식:**
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* [함수명]
|
||
|
|
*
|
||
|
|
* <상세 설명>
|
||
|
|
*
|
||
|
|
* 처리 과정:
|
||
|
|
* 1. <데이터 추출/준비>
|
||
|
|
* 2. <검증 로직>
|
||
|
|
* 3. <외부 API/DB 호출>
|
||
|
|
* 4. <분기 처리 (성공/실패)>
|
||
|
|
* 5. <결과 반환/리다이렉트>
|
||
|
|
*
|
||
|
|
* @param ...
|
||
|
|
*/
|
||
|
|
````
|
||
|
|
|
||
|
|
````
|
||
|
|
|
||
|
|
## ⭐ @see 강화 규칙 (필수)
|
||
|
|
|
||
|
|
모든 함수/컴포넌트에 **@see를 적극적으로 추가**하여 호출 관계를 명확히 한다.
|
||
|
|
|
||
|
|
**@see 작성 패턴:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* @see OpptyDetailHeader.tsx - handleApprovalClick()에서 다이얼로그 열기
|
||
|
|
* @see useContractApproval.ts - onConfirm 콜백으로 날짜 전달
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @see LeadDetailPage.tsx - 리드 상세 페이지에서 목록 조회
|
||
|
|
* @see LeadSearchForm.tsx - 검색 폼 제출 시 호출
|
||
|
|
*/
|
||
|
|
````
|
||
|
|
|
||
|
|
**@see 필수 포함 정보:**
|
||
|
|
|
||
|
|
1. **파일명** - 어떤 파일에서 호출하는지
|
||
|
|
2. **함수/이벤트명** - 어떤 함수나 이벤트에서 호출하는지
|
||
|
|
3. **호출 목적** - 왜 호출하는지 (간단히)
|
||
|
|
|
||
|
|
**예시:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* 리드 목록 조회 API (검색/필터/정렬/페이징)
|
||
|
|
* @param params 조회 조건
|
||
|
|
* @returns 목록, 페이지정보, 통계
|
||
|
|
* @remarks 정렬 필드는 sortFieldMap으로 프론트↔백엔드 변환
|
||
|
|
* @see useMainLeads.ts - useQuery의 queryFn으로 호출
|
||
|
|
* @see LeadTableContainer.tsx - 테이블 데이터 소스로 사용
|
||
|
|
*/
|
||
|
|
```
|
||
|
|
|
||
|
|
**DTO/Interface:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* 리드 생성 요청 데이터 구조 (DTO)
|
||
|
|
* @see LeadCreateModal.tsx - 리드 생성 폼 제출 시 사용
|
||
|
|
*/
|
||
|
|
export interface CreateLeadRequest { ... }
|
||
|
|
```
|
||
|
|
|
||
|
|
**Query Key Factory:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* 리드 Query Key Factory
|
||
|
|
* React Query 캐싱/무효화를 위한 키 구조
|
||
|
|
* @returns ['leads', { entity: 'mainLeads', page, ... }] 형태
|
||
|
|
* @see useLeadsQuery.ts - queryKey로 사용
|
||
|
|
* @see useLeadMutations.ts - invalidateQueries 대상
|
||
|
|
*/
|
||
|
|
export const leadKeys = { ... }
|
||
|
|
|
||
|
|
/** 메인 리드 목록 키 */
|
||
|
|
mainLeads: (...) => [...],
|
||
|
|
```
|
||
|
|
|
||
|
|
────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
# 3) 인라인 주석 (적극 활용)
|
||
|
|
|
||
|
|
## 3-1. State 주석 (필수)
|
||
|
|
|
||
|
|
모든 useState/useRef에 역할 주석 추가
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// [State] 선택된 날짜 (기본값: 오늘)
|
||
|
|
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
|
||
|
|
|
||
|
|
// [State] 캘린더 팝오버 열림 상태
|
||
|
|
const [isCalendarOpen, setIsCalendarOpen] = useState(false);
|
||
|
|
|
||
|
|
// [Ref] 파일 input 참조 (프로그래밍 방식 클릭용)
|
||
|
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||
|
|
```
|
||
|
|
|
||
|
|
## 3-2. Handler/함수 주석 (필수)
|
||
|
|
|
||
|
|
이벤트 핸들러에 Step 주석 추가
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
/**
|
||
|
|
* 작성 확인 버튼 클릭 핸들러
|
||
|
|
* @see OpptyDetailHeader.tsx - handleConfirm prop으로 전달
|
||
|
|
*/
|
||
|
|
const handleConfirm = () => {
|
||
|
|
// [Step 1] 선택된 날짜를 부모 컴포넌트로 전달
|
||
|
|
onConfirm(selectedDate);
|
||
|
|
// [Step 2] 다이얼로그 닫기
|
||
|
|
onClose();
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
## 3-3. JSX 영역 주석 (필수)
|
||
|
|
|
||
|
|
UI 구조를 파악하기 쉽게 영역별 주석 추가
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
return (
|
||
|
|
<Dialog>
|
||
|
|
{/* ========== 헤더 영역 ========== */}
|
||
|
|
<DialogHeader>
|
||
|
|
<DialogTitle>제목</DialogTitle>
|
||
|
|
</DialogHeader>
|
||
|
|
|
||
|
|
{/* ========== 본문: 날짜 선택 영역 ========== */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
{/* 날짜 선택 Popover */}
|
||
|
|
<Popover>
|
||
|
|
{/* 트리거 버튼: 현재 선택된 날짜 표시 */}
|
||
|
|
<PopoverTrigger>...</PopoverTrigger>
|
||
|
|
{/* 캘린더 컨텐츠: 한국어 로케일 */}
|
||
|
|
<PopoverContent>...</PopoverContent>
|
||
|
|
</Popover>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* ========== 하단: 액션 버튼 영역 ========== */}
|
||
|
|
<div className="flex gap-2">
|
||
|
|
<Button>취소</Button>
|
||
|
|
<Button>확인</Button>
|
||
|
|
</div>
|
||
|
|
</Dialog>
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
**JSX 주석 규칙:**
|
||
|
|
|
||
|
|
- `{/* ========== 영역명 ========== */}` - 큰 섹션 구분
|
||
|
|
- `{/* 설명 */}` - 개별 요소 설명
|
||
|
|
- 스크롤 없이 UI 구조 파악 가능하게
|
||
|
|
|
||
|
|
────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
# 4) 함수 내부 Step 주석
|
||
|
|
|
||
|
|
**대상:**
|
||
|
|
조건/분기/데이터 변환/API 호출/상태 변경이 있는 함수
|
||
|
|
|
||
|
|
**형식:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// [Step 1] <무엇을 하는지 간결하게>
|
||
|
|
// [Step 2] <다음 단계>
|
||
|
|
// [Step 3] <최종 단계>
|
||
|
|
```
|
||
|
|
|
||
|
|
**규칙:**
|
||
|
|
|
||
|
|
- 각 Step은 1줄로
|
||
|
|
- 반드시 1번부터 순차적으로
|
||
|
|
- "무엇을", "왜"를 명확하게
|
||
|
|
|
||
|
|
**예시:**
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export const getMainLeads = async (params) => {
|
||
|
|
// [Step 1] UI 정렬 필드를 백엔드 컬럼명으로 매핑
|
||
|
|
const mappedField = sortFieldMap[sortField] || sortField;
|
||
|
|
|
||
|
|
// [Step 2] API 요청 파라미터 구성
|
||
|
|
const requestParams = { ... };
|
||
|
|
|
||
|
|
// [Step 3] 리드 목록 조회 API 호출
|
||
|
|
const { data } = await axiosInstance.get(...);
|
||
|
|
|
||
|
|
// [Step 4] 응답 데이터 검증 및 기본값 설정
|
||
|
|
let dataList = data?.data?.list || [];
|
||
|
|
|
||
|
|
// [Step 5] UI 모델로 변환 및 결과 반환
|
||
|
|
return { list: dataList.map(convertToRow), ... };
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
# 5) 레이어별 특수 규칙
|
||
|
|
|
||
|
|
## 5-1. Service/API
|
||
|
|
|
||
|
|
- **Step 주석**: API 호출 흐름을 단계별로 명시
|
||
|
|
- **@see**: 이 API를 호출하는 모든 훅/컴포넌트 명시
|
||
|
|
|
||
|
|
## 5-2. Hooks (TanStack Query)
|
||
|
|
|
||
|
|
- **Query Key**: 반환 구조 예시 필수
|
||
|
|
- **캐시 전략**: invalidateQueries/setQueryData 사용 이유
|
||
|
|
- **@see**: 이 훅을 사용하는 모든 컴포넌트 명시
|
||
|
|
|
||
|
|
## 5-3. Adapters
|
||
|
|
|
||
|
|
- **간단한 변환**: 주석 불필요
|
||
|
|
- **복잡한 변환**: 입력→출력 1줄 설명 + 변환 규칙
|
||
|
|
|
||
|
|
## 5-4. Components (Container/Modal)
|
||
|
|
|
||
|
|
- **상태 관리**: 어떤 state가 어떤 이벤트로 변경되는지
|
||
|
|
- **Dialog/Modal**: open 상태 소유자, 닫힘 조건
|
||
|
|
- **Table**: 인라인 편집, 스켈레톤 범위
|
||
|
|
- **JSX 영역 주석**: UI 구조 파악용 영역 구분 주석 필수
|
||
|
|
|
||
|
|
## 5-5. Zustand Store
|
||
|
|
|
||
|
|
- **왜 store인지**: 페이지 이동/모달 간 상태 유지 이유
|
||
|
|
- **reset 조건**: 언제 초기화되는지
|
||
|
|
- **서버 캐시와 역할 분담**: React Query와의 경계
|
||
|
|
|
||
|
|
────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
# 6) 작업 순서
|
||
|
|
|
||
|
|
1. 파일 레이어 판별 (Infrastructure/Hooks/UI/Core)
|
||
|
|
2. 파일 상단 TSDoc 추가 (@see 포함)
|
||
|
|
3. export 대상에 TSDoc 추가 (@see 필수)
|
||
|
|
4. State/Ref에 인라인 주석 추가
|
||
|
|
5. Handler 함수에 TSDoc + Step 주석 추가
|
||
|
|
6. JSX 영역별 구분 주석 추가
|
||
|
|
7. Query Key Factory에 반환 구조 예시 추가
|
||
|
|
|
||
|
|
# 제약사항
|
||
|
|
|
||
|
|
- **@author는 jihoon87.lee 고정**
|
||
|
|
- **@see는 필수**: 호출 관계 명확히
|
||
|
|
- **Step 주석은 1줄**: 간결하게
|
||
|
|
- **JSX 주석 필수**: UI 구조 파악용
|
||
|
|
- **@see는 파일명 + 함수명 + 역할**: 전체 경로 불필요
|
||
|
|
|
||
|
|
# 지금부터 작업
|
||
|
|
|
||
|
|
내가 주는 코드를 위 규칙에 맞게 "주석만" 보강하라.
|