📝 docs: 여러 문서 및 파일 삭제
This commit is contained in:
150
.claude/skills/dev-api-state/SKILL.md
Normal file
150
.claude/skills/dev-api-state/SKILL.md
Normal file
@@ -0,0 +1,150 @@
|
||||
---
|
||||
name: dev-api-state
|
||||
description: |
|
||||
API 연동 패턴(useFetch / useAsyncData / $fetch)과 Pinia 상태관리 코드를
|
||||
상황에 맞게 자동 선택·생성합니다. BFF 패턴, 에러 핸들링, 로딩 상태를 포함합니다.
|
||||
|
||||
다음 상황에서 반드시 사용하세요:
|
||||
- "이 API 연동 + 스토어 만들어줘", "Pinia store 작성해줘"
|
||||
- "API 데이터 페칭 어떻게 해?", "useFetch vs useAsyncData 언제 써?"
|
||||
- API 키 보호를 위한 BFF(server/api/) 패턴이 필요할 때
|
||||
---
|
||||
|
||||
# API 연동 & 상태관리 (dev-api-state)
|
||||
|
||||
API 스펙 → useFetch/useAsyncData 패턴 선택 → Pinia Setup Store 코드 자동 생성.
|
||||
|
||||
## 언제 사용하는가
|
||||
|
||||
- 새 API 연동 코드와 Pinia 스토어를 함께 작성할 때
|
||||
- `useFetch` / `$fetch` / `useAsyncData` 중 적절한 패턴을 결정할 때
|
||||
- API 키를 클라이언트에 노출하지 않기 위한 BFF 패턴이 필요할 때
|
||||
|
||||
## 데이터 페칭 패턴 선택 기준
|
||||
|
||||
| 상황 | 권장 패턴 |
|
||||
|---|---|
|
||||
| SSR 페이지 초기 데이터 | `useAsyncData` + `$fetch` |
|
||||
| 컴포넌트 마운트 후 데이터 | `useFetch` |
|
||||
| 사용자 액션으로 트리거 | `$fetch` (직접 호출) |
|
||||
| API 키 보호 필요 | `server/api/` BFF + `useFetch` |
|
||||
| 복잡한 캐싱/의존성 | `useAsyncData` with key |
|
||||
|
||||
---
|
||||
|
||||
## 작업 순서
|
||||
|
||||
### Phase 1: API 스펙 파악
|
||||
|
||||
1. 엔드포인트, 요청/응답 타입을 파악한다.
|
||||
2. 아래를 확인한다:
|
||||
- 인증 헤더 필요 여부
|
||||
- API 키 노출 위험 여부 → BFF 패턴 적용
|
||||
- 캐시 전략 (항상 최신 vs TTL)
|
||||
|
||||
### Phase 2: 타입 정의
|
||||
|
||||
```ts
|
||||
// types/product.ts
|
||||
export interface Product {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
imageUrl: string
|
||||
}
|
||||
|
||||
export interface ProductListResponse {
|
||||
data: Product[]
|
||||
total: number
|
||||
page: number
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: BFF 레이어 (필요 시)
|
||||
|
||||
API 키 보호가 필요한 경우 server/api/ 경유:
|
||||
|
||||
```ts
|
||||
// server/api/products/index.get.ts
|
||||
export default defineEventHandler(async (event) => {
|
||||
const query = getQuery(event)
|
||||
const response = await $fetch<ProductListResponse>(
|
||||
`${process.env.API_BASE}/products`,
|
||||
{
|
||||
headers: { 'x-api-key': process.env.API_KEY! },
|
||||
query,
|
||||
}
|
||||
)
|
||||
return response
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 4: Pinia Setup Store 생성
|
||||
|
||||
Setup Store 패턴을 기본으로 사용한다:
|
||||
|
||||
```ts
|
||||
// stores/product.ts
|
||||
import type { Product } from '~/types/product'
|
||||
|
||||
export const useProductStore = defineStore('product', () => {
|
||||
const items = ref<Product[]>([])
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
const fetchProducts = async (page = 1) => {
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const { data } = await useFetch('/api/products', { query: { page } })
|
||||
items.value = data.value?.data ?? []
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '알 수 없는 오류'
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return { items, isLoading, error, fetchProducts }
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 5: 컴포넌트 연결 예시
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
const productStore = useProductStore()
|
||||
const { items, isLoading, error } = storeToRefs(productStore)
|
||||
|
||||
onMounted(() => productStore.fetchProducts())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="isLoading" aria-live="polite">로딩 중...</div>
|
||||
<div v-else-if="error" role="alert">{{ error }}</div>
|
||||
<ul v-else>
|
||||
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
|
||||
</ul>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 출력 형식
|
||||
|
||||
```
|
||||
## API 연동: <기능명>
|
||||
|
||||
### 선택된 패턴
|
||||
- 페칭: useFetch | useAsyncData | $fetch
|
||||
- BFF: 사용 | 미사용
|
||||
- 이유: [선택 근거]
|
||||
|
||||
### 파일 목록
|
||||
- `types/<domain>.ts`
|
||||
- `server/api/...` (BFF 사용 시)
|
||||
- `stores/<domain>.ts`
|
||||
|
||||
### 코드
|
||||
[타입 → BFF → 스토어 → 컴포넌트 순]
|
||||
```
|
||||
Reference in New Issue
Block a user