Next.js

AI를 위한 Vercel: React Best Practices 공개

중년개발자
중년개발자

@loxo

25일 전

34

Vercel에서 React, Next.js AI를 위한 React Best Practices를 공개했습니다.

사용법

  • GitHub의 AGENTS.md 파일을 다운로드하여 개발 툴에 룰 적용
  • Antigravity 적용 예시
    • 프로젝트 > .agent > rules > vercel.md 로 저장하여 사용
    • 12000자 제약이 있어서 여러 파일로 분할하여 저장 (vercel1.md, vercel2.md 등) 첨부 파일로 나누어 놓았습니다.

검증

  • prompt: Vercel React Best Practices rules 를 적용하여 프로젝트 전체 소스에 대한 소스 코드 리뷰 보고서를 만들어줘

결과

🔍 Vercel React Best Practices 프론트엔드 검토 결과

검토일: 2026-01-19
대상: postgresql 프론트엔드 (apps/web)
기준: Vercel React Best Practices


📊 전체 평가: B+ (양호)

코드베이스가 대체로 잘 구성되어 있으며, 주요 Best Practices를 잘 따르고 있습니다.


✅ 잘 따르고 있는 패턴들

1. Eliminating Waterfalls (CRITICAL)

tsx
// Home page: 병렬 데이터 페칭 + HydrationBoundary 사용 // src/app/(home)/page.tsx export default async function HomePage(props: HomePageProps) { const queryClient = getQueryClient(); const initialData = await postService.getPosts({...}); queryClient.setQueryData(['posts', condition], {...}); return ( <HydrationBoundary state={dehydrate(queryClient)}> <Suspense> <BoardPageClient board="home" /> </Suspense> </HydrationBoundary> ); }
  • SSR 데이터 Prefetch + Hydration 패턴을 올바르게 사용 ✓
  • Suspense 경계 적절히 배치 ✓

2. React Compiler 활성화 ✓ (next.config.ts)

ts
reactCompiler: true,
  • Manual memoization (memo, useMemo, useCallback) 불필요 - 컴파일러가 자동 최적화

3. Query Client 싱글톤 패턴

ts
// src/lib/query-client.ts let browserQueryClient: QueryClient | undefined = undefined; export function getQueryClient() { if (typeof window === 'undefined') { return makeQueryClient(); // Server: 매번 새로 생성 } else { if (!browserQueryClient) browserQueryClient = makeQueryClient(); return browserQueryClient; // Browser: 싱글톤 } }

4. BFF (Backend For Frontend) 패턴

ts
// src/services/post.service.ts function transformForList(post: Post): Post { return { ...post, contentPreview: truncateToLines(post.content, 10, 50), content: '', // 목록 뷰에서 전체 content 제거 → 페이로드 감소 }; }
  • RSC 경계에서 직렬화 최소화 원칙 준수 ✓

5. Functional setState Updates

tsx
// src/components/comment/CommentSection.tsx setLocalCommentsCount(prev => prev + 1); // ✓ 올바른 패턴 setLocalCommentsCount(prev => Math.max(0, prev - 1)); // ✓

6. Derived State 패턴

tsx
// src/app/boards/[slug]/BoardPageClient.tsx // useEffect 대신 Derived State 사용 (React 권장) const urlSearchTerm = searchParams.get('q') || ''; const [prevUrlSearchTerm, setPrevUrlSearchTerm] = useState(urlSearchTerm); if (urlSearchTerm !== prevUrlSearchTerm) { setPrevUrlSearchTerm(urlSearchTerm); setSearchTerm(urlSearchTerm); setIsSearching(false); }

7. Hydration Mismatch 방지

tsx
// src/components/post/PostCard.tsx <Typography ... suppressHydrationWarning> {formatDistanceToNow(new Date(post.createdAt), {...})} </Typography>

⚠️ 개선이 필요했던 사항들 (수정됨)

1. 🔴 CRITICAL: Barrel File Imports 문제 → ✅ 수정됨

문제: @mui/icons-material, @mui/material, lucide-react barrel file import로 인한 번들 크기 증가

해결: next.config.tsoptimizePackageImports 추가

ts
experimental: { optimizePackageImports: ['@mui/icons-material', '@mui/material', 'lucide-react'], }

2. 🟠 HIGH: Post Detail 페이지 - 중복 Fetch 문제 → ✅ 수정됨

문제: generateMetadataPostDetailPage에서 동일한 API를 2번 호출

해결: React.cache 도입

tsx
import { cache } from 'react'; const getPost = cache(async (id: string) => { const { data } = await coreApi.get<Post>(`/v1/posts/${id}`); return data; });

3. 🟠 MEDIUM: 조건부 렌더링 개선 → ✅ 수정됨

문제: && 연산자 사용 시 falsy 값(0, NaN) 렌더링 위험

해결: 명시적 삼항 연산자 사용

tsx
// Before {post.tags.length > 0 && (...)} // After {post.tags.length > 0 ? (...) : null}

📈 추가 권장사항 (미래 개선)

1. LRU 캐시 도입 (서버 측)

Vercel의 Fluid Compute 환경에서 cross-request 캐싱 고려:

ts
import { LRUCache } from 'lru-cache'; const postCache = new LRUCache<string, Post>({ max: 1000, ttl: 5 * 60 * 1000 // 5 minutes });

2. content-visibility CSS (긴 목록 최적화)

css
.post-card { content-visibility: auto; contain-intrinsic-size: 0 200px; }

3. UseTransition for Non-Urgent Updates

tsx
import { startTransition } from 'react'; const handleSearchSubmit = useCallback((e: React.FormEvent) => { e.preventDefault(); startTransition(() => { router.push(`${basePath}?q=${searchTerm}`); }); }, [...]);

4. 제 3자 라이브러리 Lazy Loading

tsx
const GoogleAnalytics = dynamic( () => import('@next/third-parties/google').then(m => m.GoogleAnalytics), { ssr: false } );

📊 요약 체크리스트

카테고리상태우선순위
Waterfalls 제거✅ 양호-
Bundle Size 최적화✅ 수정됨CRITICAL
서버 측 성능 (React.cache)✅ 수정됨HIGH
클라이언트 데이터 페칭✅ 양호 (TanStack Query)-
Re-render 최적화✅ 양호 (React Compiler)-
렌더링 성능✅ 양호-
조건부 렌더링✅ 수정됨MEDIUM

참고 자료

#Vercel#React#Next.js#AI#Best Practices

댓글 1

Ctrl + Enter를 눌러 등록할 수 있습니다
※ AI 다듬기는 내용을 정제하는 보조 기능이며, 최종 내용은 사용자가 확인해야 합니다.