Skip to content

Commit fcb5037

Browse files
authored
fix(IN-314): vercel 배포 에러 해결
원인: useSearchParams()를 사용하는 컴포넌트들이 Next.js 빌드 시 SSR 정적 분석 대상에 포함되어, 경계가 있어도 프리렌더링 단계에서 에러 발생. 해결: 패턴 → dynamic(ssr: false)로 교체하여 해당 컴포넌트들을 SSR 분석 대상에서 완전히 제외.
2 parents f607ea7 + 8062b73 commit fcb5037

5 files changed

Lines changed: 35 additions & 28 deletions

File tree

src/pages/influencer/ui/BookmarkedInfluencerPage.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
'use client'
22

3-
import { Suspense } from 'react'
3+
import dynamic from 'next/dynamic'
44
import { useSearchParams, useRouter, usePathname } from 'next/navigation'
55
import { InfluencerList, useInfluencers, SORT_OPTIONS } from '@/features/influencer'
66
import { useYoutubeCategories } from '@/entities/youtubeCategory'
77
import type { SortCriteria, SortOrder } from '@/entities/influencer'
88
import { InfluencerFilter } from '@/widgets/influencer'
99

10+
const BookmarkedInfluencerListSectionDynamic = dynamic(
11+
() => Promise.resolve(BookmarkedInfluencerListSection),
12+
{ ssr: false }
13+
)
14+
1015
export function BookmarkedInfluencerPage() {
1116
const { data: categoriesData } = useYoutubeCategories()
1217
const categories = categoriesData?.youtubeCategories ?? []
@@ -15,9 +20,7 @@ export function BookmarkedInfluencerPage() {
1520
<div className='flex h-fit w-full flex-col gap-24 pb-[9.6rem]'>
1621
<InfluencerFilter categories={categories} />
1722
<div className='h-full'>
18-
<Suspense fallback={<></>}>
19-
<BookmarkedInfluencerListSection />
20-
</Suspense>
23+
<BookmarkedInfluencerListSectionDynamic />
2124
</div>
2225
</div>
2326
)

src/pages/influencer/ui/InfluencerPage.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { Suspense } from 'react'
3+
import dynamic from 'next/dynamic'
44
import { useSearchParams, useRouter, usePathname } from 'next/navigation'
55
import {
66
InfluencerList,
@@ -11,6 +11,11 @@ import { useYoutubeCategories } from '@/entities/youtubeCategory'
1111
import type { SortCriteria, SortOrder } from '@/entities/influencer'
1212
import { InfluencerFilter } from '@/widgets/influencer'
1313

14+
const InfluencerListSectionDynamic = dynamic(
15+
() => Promise.resolve(InfluencerListSection),
16+
{ ssr: false }
17+
)
18+
1419
export function InfluencerPage() {
1520
const { data: categoriesData } = useYoutubeCategories()
1621
const categories = categoriesData?.youtubeCategories ?? []
@@ -19,9 +24,7 @@ export function InfluencerPage() {
1924
<div className='flex h-fit w-full flex-col gap-24 pb-[9.6rem]'>
2025
<InfluencerFilter categories={categories} />
2126
<div className='h-full'>
22-
<Suspense fallback={<></>}>
23-
<InfluencerListSection />
24-
</Suspense>
27+
<InfluencerListSectionDynamic />
2528
</div>
2629
</div>
2730
)

src/pages/videos/ui/VideosPage.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
'use client'
22

3-
import { Suspense, useState } from 'react'
3+
import { useState } from 'react'
4+
import dynamic from 'next/dynamic'
45
import { useSearchParams } from 'next/navigation'
56
import { useAuth } from '@/features/auth'
67
import { useVideos, VideoList, VALID_FORMAT } from '@/features/videos'
78
import type { VideoFilterParams, VideoSort } from '@/features/videos'
89
import { InfiniteScrollList } from '@/shared/ui/infinite-scroll-list/InfiniteScrollList'
910
import { SearchAndFilter } from '@/widgets/videos'
1011

12+
const VideoListSectionDynamic = dynamic(
13+
() => Promise.resolve(VideoListSection),
14+
{ ssr: false }
15+
)
16+
1117
export function VideosPage() {
1218
return (
1319
<>
1420
<SearchAndFilter />
1521
<div className='h-full'>
16-
<Suspense fallback={<></>}>
17-
<VideoListSection />
18-
</Suspense>
22+
<VideoListSectionDynamic />
1923
</div>
2024
</>
2125
)

src/widgets/influencer/ui/InfluencerFilter.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use client'
22

3-
import { useState, useEffect, useRef, useCallback, Suspense } from 'react'
3+
import { useState, useEffect, useRef, useCallback } from 'react'
44
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
5+
import dynamic from 'next/dynamic'
56

67
import { SearchBar } from '@/shared/ui/search-bar'
78
import { Button } from '@/shared/ui/button'
@@ -75,13 +76,10 @@ type InfluencerFilterProps = {
7576
categories: YoutubeCategory[]
7677
}
7778

78-
export function InfluencerFilter({ categories }: InfluencerFilterProps) {
79-
return (
80-
<Suspense fallback={<div className='h-full' />}>
81-
<InfluencerFilterInner categories={categories} />
82-
</Suspense>
83-
)
84-
}
79+
export const InfluencerFilter = dynamic(
80+
() => Promise.resolve(InfluencerFilterInner),
81+
{ ssr: false }
82+
)
8583

8684
function InfluencerFilterInner({ categories }: InfluencerFilterProps) {
8785
const router = useRouter()
@@ -158,6 +156,7 @@ function InfluencerFilterInner({ categories }: InfluencerFilterProps) {
158156
<div className='flex w-full items-center gap-24'>
159157
{/* 검색바 */}
160158
<SearchBar
159+
className='w-[50rem]'
161160
placeholder='채널명 또는 키워드 검색'
162161
value={query}
163162
onChange={(e) => setQuery(e.target.value)}

src/widgets/videos/ui/SearchAndFilter.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
'use client'
22

3-
import { Suspense, useState, useEffect, useRef, useCallback } from 'react'
3+
import { useState, useEffect, useRef, useCallback } from 'react'
44
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
5+
import dynamic from 'next/dynamic'
56
import { SearchBar } from '@/shared/ui/search-bar'
67
import { Toggle } from '@/shared/ui/toggle'
78
import { CalendarFilter } from './CalendarFilter'
89

9-
export function SearchAndFilter() {
10-
return (
11-
<Suspense fallback={<></>}>
12-
<SearchAndFilterInner />
13-
</Suspense>
14-
)
15-
}
10+
export const SearchAndFilter = dynamic(
11+
() => Promise.resolve(SearchAndFilterInner),
12+
{ ssr: false }
13+
)
1614

1715
/* 필터를 쿼리 파라미터에 반영 */
1816
function SearchAndFilterInner() {

0 commit comments

Comments
 (0)