@choblue/claude-code-toolkit 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
3b3477495f8b6aeafca6aa34cc433d15ccdd0622
|
|
@@ -253,7 +253,67 @@ function UserContent({ isLoading, error, data }: UserContentProps) {
|
|
|
253
253
|
|
|
254
254
|
---
|
|
255
255
|
|
|
256
|
-
## 8.
|
|
256
|
+
## 8. 에러 처리
|
|
257
|
+
|
|
258
|
+
### 원칙: 에러 처리를 각 함수/컴포넌트에 흩뿌리지 않는다
|
|
259
|
+
- 각 함수마다 try-catch를 덕지덕지 붙이지 않는다
|
|
260
|
+
- `useState`로 에러 상태를 직접 관리하지 않는다 (TanStack Query가 제공)
|
|
261
|
+
- 에러 처리는 **경계(Boundary)**에서 한 번에 처리한다
|
|
262
|
+
|
|
263
|
+
### API 에러: 서버 상태 라이브러리에 위임
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
// Bad - useState + useEffect로 에러 직접 관리
|
|
267
|
+
function UserList() {
|
|
268
|
+
const [error, setError] = useState<Error | null>(null);
|
|
269
|
+
const [data, setData] = useState(null);
|
|
270
|
+
const [loading, setLoading] = useState(false);
|
|
271
|
+
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
setLoading(true);
|
|
274
|
+
fetchUsers()
|
|
275
|
+
.then(setData)
|
|
276
|
+
.catch(setError)
|
|
277
|
+
.finally(() => setLoading(false));
|
|
278
|
+
}, []);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Good - 서버 상태 라이브러리가 에러를 관리
|
|
282
|
+
function UserList() {
|
|
283
|
+
const { data: users, isLoading, error } = useUserList();
|
|
284
|
+
if (error) return <ErrorDisplay error={error} />;
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 렌더링 에러: Error Boundary
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
<ErrorBoundary fallback={<ErrorFallback />}>
|
|
292
|
+
<UserContent />
|
|
293
|
+
</ErrorBoundary>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 전역 API 에러: interceptor 또는 라이브러리 설정에서 일괄 처리
|
|
297
|
+
- axios interceptor, QueryClient defaultOptions 등 프로젝트 설정에 따른다
|
|
298
|
+
- 개별 컴포넌트가 아닌 앱 수준에서 에러 알림(toast 등)을 처리한다
|
|
299
|
+
|
|
300
|
+
### 에러 UI 분기: early return 패턴
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
function UserPage({ userId }: UserPageProps) {
|
|
304
|
+
const { data: user, isLoading, error } = useUser(userId);
|
|
305
|
+
|
|
306
|
+
if (isLoading) return <Skeleton />;
|
|
307
|
+
if (error) return <ErrorDisplay error={error} />;
|
|
308
|
+
if (!user) return <EmptyState />;
|
|
309
|
+
|
|
310
|
+
return <UserContent user={user} />;
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 9. 금지 사항
|
|
257
317
|
|
|
258
318
|
- `any` 타입 사용 금지
|
|
259
319
|
- 인라인 스타일(`style={{}}`) 사용 금지 - 프로젝트 스타일링 방식을 따른다
|
|
@@ -263,4 +323,6 @@ function UserContent({ isLoading, error, data }: UserContentProps) {
|
|
|
263
323
|
- `React.FC` 사용 금지
|
|
264
324
|
- 배열 인덱스를 `key`로 사용 금지 (정적 리스트 제외)
|
|
265
325
|
- `useEffect` 내에서 상태 동기화 로직 작성 금지 (파생값으로 처리)
|
|
266
|
-
- Props drilling이 3단계 이상일 때 Context 또는 상태 관리 라이브러리 미사용 금지
|
|
326
|
+
- Props drilling이 3단계 이상일 때 Context 또는 상태 관리 라이브러리 미사용 금지
|
|
327
|
+
- 서버 상태(API 데이터)를 `useState` + `useEffect`로 관리 금지 (서버 상태 라이브러리 사용)
|
|
328
|
+
- 각 함수/컴포넌트마다 try-catch 남발 금지 (에러 경계에서 일괄 처리)
|
|
@@ -237,7 +237,56 @@ const queryClient = new QueryClient({
|
|
|
237
237
|
|
|
238
238
|
---
|
|
239
239
|
|
|
240
|
-
## 9.
|
|
240
|
+
## 9. 캐시 전략 가이드
|
|
241
|
+
|
|
242
|
+
데이터 특성에 따라 `staleTime`을 다르게 설정한다.
|
|
243
|
+
|
|
244
|
+
| 데이터 유형 | staleTime | 예시 |
|
|
245
|
+
|------------|-----------|------|
|
|
246
|
+
| 거의 안 바뀜 | `Infinity` | 코드 테이블, 카테고리 목록, 약관 |
|
|
247
|
+
| 가끔 바뀜 | `10~30분` | 사용자 프로필, 설정 |
|
|
248
|
+
| 자주 바뀜 | `1~5분` | 게시글 목록, 댓글 |
|
|
249
|
+
| 실시간 필요 | `0` | 채팅, 알림, 재고 수량 |
|
|
250
|
+
|
|
251
|
+
### 도메인별 staleTime 설정
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// queryKey 팩토리에서 기본 옵션을 함께 관리
|
|
255
|
+
export const categoryKeys = {
|
|
256
|
+
all: ['categories'] as const,
|
|
257
|
+
list: () => [...categoryKeys.all, 'list'] as const,
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// 거의 안 바뀌는 데이터
|
|
261
|
+
useQuery({
|
|
262
|
+
queryKey: categoryKeys.list(),
|
|
263
|
+
queryFn: fetchCategories,
|
|
264
|
+
staleTime: Infinity,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// 자주 바뀌는 데이터
|
|
268
|
+
useQuery({
|
|
269
|
+
queryKey: postKeys.list(filters),
|
|
270
|
+
queryFn: () => fetchPosts(filters),
|
|
271
|
+
staleTime: 1000 * 60, // 1분
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### 실시간 데이터: refetchInterval 사용
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// 폴링 방식 (WebSocket이 없을 때)
|
|
279
|
+
useQuery({
|
|
280
|
+
queryKey: ['notifications'],
|
|
281
|
+
queryFn: fetchNotifications,
|
|
282
|
+
staleTime: 0,
|
|
283
|
+
refetchInterval: 1000 * 30, // 30초마다 재요청
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 10. 금지 사항
|
|
241
290
|
|
|
242
291
|
- `useEffect`로 데이터 페칭 금지 - TanStack Query를 사용한다
|
|
243
292
|
- queryKey 하드코딩 금지 - queryKey 팩토리 패턴을 사용한다
|