Loading...
Loading...
React/Next.js/TypeScript 코드를 리팩토링하는 스킬. 컴포넌트 분리, 커스텀 훅 추출, 디자인 패턴 적용, 코드 정리 등. "리팩토링", "refactor", "코드 개선", "분리해줘", "정리해줘" 등의 요청 시 사용.
npx skill4agent add ingpdw/pdw-fe-dev-tool fe-refactor$ARGUMENTSfunction Dashboard() {
// 사용자 데이터 로직
const [user, setUser] = useState(null);
useEffect(() => { fetchUser().then(setUser); }, []);
// 차트 데이터 로직
const [chartData, setChartData] = useState([]);
useEffect(() => { fetchChartData().then(setChartData); }, []);
return (
<div>
<header>{user?.name}</header>
<div>{/* 복잡한 차트 렌더링 */}</div>
<div>{/* 복잡한 테이블 렌더링 */}</div>
</div>
);
}function Dashboard() {
return (
<div>
<DashboardHeader />
<DashboardChart />
<DashboardTable />
</div>
);
}function ProductList() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetchProducts()
.then(setProducts)
.catch(setError)
.finally(() => setLoading(false));
}, []);
// ... 렌더링
}// hooks/useProducts.ts
function useProducts() {
return useQuery({
queryKey: ["products"],
queryFn: fetchProducts,
});
}
// components/ProductList.tsx
function ProductList() {
const { data: products, isLoading, error } = useProducts();
// ... 렌더링
}useEffectuseMemoconst [items, setItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]);
const [search, setSearch] = useState("");
useEffect(() => {
setFilteredItems(items.filter((i) => i.name.includes(search)));
}, [items, search]);const [items, setItems] = useState([]);
const [search, setSearch] = useState("");
const filteredItems = items.filter((i) => i.name.includes(search));"use client"; // 전체가 클라이언트
export default function ProductPage() {
const [count, setCount] = useState(0);
const products = useProducts(); // 서버에서 가져올 수 있는 데이터
return (
<div>
<h1>Products</h1>
<ProductList products={products} />
<Counter count={count} onChange={setCount} />
</div>
);
}// page.tsx (Server Component)
export default async function ProductPage() {
const products = await getProducts();
return (
<div>
<h1>Products</h1>
<ProductList products={products} />
<Counter /> {/* Client Component */}
</div>
);
}// Before: props로 모든 것을 전달
<Select options={options} label="Country" placeholder="Select..." onChange={onChange} />
// After: Compound Component
<Select value={value} onValueChange={onChange}>
<SelectTrigger>
<SelectValue placeholder="Select..." />
</SelectTrigger>
<SelectContent>
{options.map((opt) => (
<SelectItem key={opt.value} value={opt.value}>
{opt.label}
</SelectItem>
))}
</SelectContent>
</Select>// Before: 느슨한 타입
function handleResponse(data: any) {
return data.items.map((item: any) => item.name);
}
// After: 엄격한 타입
interface ApiResponse {
items: Array<{ name: string; id: string }>;
}
function handleResponse(data: ApiResponse) {
return data.items.map((item) => item.name);
}// components/user/index.ts
export { UserProfile } from "./UserProfile";
export { UserAvatar } from "./UserAvatar";
export { UserSettings } from "./UserSettings";
export type { UserProfileProps } from "./UserProfile";