Skip to content

Commit 73367e3

Browse files
committed
[refactor] 전역상태에서 필터링 삭제
1 parent 21a9de5 commit 73367e3

File tree

15 files changed

+201
-212
lines changed

15 files changed

+201
-212
lines changed

next.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import type { NextConfig } from 'next';
22

33
const nextConfig: NextConfig = {
4+
reactStrictMode: false,
45
experimental: {
56
scrollRestoration: false,
67
},
78
images: {
89
// 외부 이미지 최적화 완전 비활성화 (Vercel 유료 기능 회피)
9-
unoptimized: true,
10+
unoptimized: true,
1011
domains: [
1112
'team2-app-s3-bucket.s3.ap-northeast-2.amazonaws.com',
1213
'team2-app-s3-bucket.s3.amazonaws.com',
@@ -15,12 +16,14 @@ const nextConfig: NextConfig = {
1516
{
1617
protocol: 'https',
1718
hostname: 'www.thecocktaildb.com',
19+
pathname: '/images/**',
1820
},
1921
],
2022
},
2123
env: {
2224
NPUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
2325
},
26+
2427
// webpack 설정
2528
webpack: (config) => {
2629
// @ts-expect-error 타입 에러 무시

src/app/(with-layout)/mypage/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import MyNav from '@/domains/mypage/main/MyNav';
2-
import MyProfile from '@/domains/mypage/main/MyProfile';
1+
2+
import MyNav from '@/domains/mypage/components/main/MyNav';
3+
import MyProfile from '@/domains/mypage/components/main/MyProfile';
34
import SkeletonLayout from '@/domains/mypage/skeleton/main/SkeletonLayout';
45
import { Suspense } from 'react';
56

src/app/(with-layout)/mypage/my-setting/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import MySetting from '@/domains/mypage/main/MySetting';
21

2+
import MySetting from '@/domains/mypage/components/main/MySetting';
33
import { Metadata } from 'next';
44
export const metadata: Metadata = {
55
title: '마이페이지',

src/domains/mypage/components/main/SsuryImage.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import Image from 'next/image';
32
import useProfileSsury from '../../hook/useProfileSsury';
43

src/domains/recipe/api/fetchRecipe.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ interface PageParam {
2828
lastValue: number | string;
2929
}
3030

31+
32+
// 로그인 한 유저의 킵 칵테일을 Get으로 불러옴
3133
const fetchKeep = async (): Promise<Set<number>> => {
3234
const res = await fetch(`${getApi}/me/bar`, {
3335
method: 'GET',
@@ -41,6 +43,7 @@ const fetchKeep = async (): Promise<Set<number>> => {
4143
return new Set(myKeep.map((v: { cocktailId: number }) => v.cocktailId));
4244
};
4345

46+
// 비 로그인 유저도 볼 수 있는 칵테일 API fetch 각 종 정렬 파라미터를 문자열로 받아서 정렬함
4447
const fetchRecipe = async (
4548
pageParam: PageParam | null,
4649
size: number,
@@ -68,6 +71,7 @@ const fetchRecipe = async (
6871
return json.data ?? [];
6972
};
7073

74+
// 검색전용 API 여기서 필터링 토글도 받음
7175
const searchCocktails = async (filters: SearchFilters): Promise<Cocktail[]> => {
7276
const body = {
7377
keyword: filters.keyword?.trim() ?? '',
@@ -90,6 +94,7 @@ const searchCocktails = async (filters: SearchFilters): Promise<Cocktail[]> => {
9094
return json.data ?? [];
9195
};
9296

97+
// 적용된 필터
9398
const hasActiveFilters = (filters: SearchFilters): boolean => {
9499
return !!(
95100
filters.keyword?.trim() ||
@@ -99,10 +104,25 @@ const hasActiveFilters = (filters: SearchFilters): boolean => {
99104
);
100105
};
101106

107+
108+
export const useKeepQuery = () => {
109+
const user = useAuthStore((state) => state.user);
110+
111+
return useQuery({
112+
queryKey: ['keeps', user?.id],
113+
queryFn: fetchKeep,
114+
enabled: !!user,
115+
staleTime: 5 * 60 * 1000,
116+
gcTime: 10 * 60 * 1000,
117+
})
118+
};
119+
120+
// 무한스크롤 fetch
102121
export const useCocktailsInfiniteQuery = (size: number = 20, sortBy?: Sort) => {
103122
const user = useAuthStore((state) => state.user);
104123
const queryClient = useQueryClient();
105124
const prevSortBy = useRef(sortBy);
125+
const { data:keepIds } = useKeepQuery()
106126

107127
useEffect(() => {
108128
if (prevSortBy.current !== undefined && prevSortBy.current !== sortBy) {
@@ -118,12 +138,11 @@ export const useCocktailsInfiniteQuery = (size: number = 20, sortBy?: Sort) => {
118138
queryFn: async ({ pageParam }) => {
119139
const cocktails = await fetchRecipe(pageParam, size, sortBy);
120140

121-
if (user) {
122-
const keepId = await fetchKeep();
141+
if (user && keepIds) {
123142
return cocktails.map((item) => ({
124143
...item,
125-
isKeep: keepId.has(item.cocktailId),
126-
}));
144+
isKeep : keepIds.has(item.cocktailId)
145+
}))
127146
}
128147

129148
return cocktails;
@@ -159,31 +178,37 @@ export const useCocktailsInfiniteQuery = (size: number = 20, sortBy?: Sort) => {
159178
initialPageParam: null as PageParam | null,
160179
refetchOnMount: false,
161180
refetchOnWindowFocus: false,
181+
staleTime: 2 * 60 * 1000
162182
});
163183
};
164184

185+
// 검색용 fetch
165186
export const useCocktailsSearchQuery = (filters: SearchFilters) => {
166187
const user = useAuthStore((state) => state.user);
167188
const isActive = hasActiveFilters(filters);
189+
const {data: keepIds} = useKeepQuery()
168190

169191
return useQuery({
170192
queryKey: ['cocktails', 'search', filters, user?.id],
171193
queryFn: async () => {
172194
const cocktails = await searchCocktails(filters);
173-
if (user && cocktails.length > 0) {
174-
const keepId = await fetchKeep();
195+
if (user && cocktails.length > 0 && keepIds) {
196+
175197
return cocktails.map((item) => ({
176198
...item,
177-
isKeep: keepId.has(item.cocktailId),
199+
isKeep: keepIds.has(item.cocktailId),
178200
}));
179201
}
180202
return cocktails;
181203
},
182204
enabled: isActive,
183205
refetchOnMount: false,
206+
refetchOnWindowFocus: false,
207+
staleTime: 5 * 60 * 1000
184208
});
185209
};
186210

211+
// 검색모드를 전환하여 어떤 fetch를 하는지 결정
187212
export const useCocktails = (
188213
filters: CocktailFilter,
189214
infiniteScrollSize: number = 20,

src/domains/recipe/components/main/CocktailFilter.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import SelectBox from '@/shared/components/select-box/SelectBox';
2-
import { useRouter } from 'next/navigation';
2+
import { useRouter, useSearchParams } from 'next/navigation';
3+
4+
35

46
interface Props {
57
cocktailsEA: number;
@@ -12,18 +14,29 @@ function CocktailFilter({ cocktailsEA }: Props) {
1214
댓글순: 'comments',
1315
};
1416

17+
const searchParams = useSearchParams()
1518
const router = useRouter();
1619

20+
const getCurrentSort = () => {
21+
const sortBy = searchParams.get('sortBy') || 'recent'
22+
23+
const entry = Object.entries(sortMap).find(([_, value]) => value === sortBy)
24+
return entry ? entry[0] : '최신순'
25+
}
26+
1727
const handleChange = (selectTitle: string) => {
1828
const sortValue = sortMap[selectTitle as keyof typeof sortMap];
1929

30+
const params = new URLSearchParams(searchParams.toString())
31+
params.set('sortBy', sortValue)
32+
2033
router.push(`?sortBy=${sortValue}`);
2134
};
2235

2336
return (
2437
<div className="h-10 flex justify-between items-center mt-3 border-b-1 border-gray-light">
2538
<p>{cocktailsEA}개+</p>
26-
<SelectBox option={['최신순', '댓글순', '인기순']} title="최신순" onChange={handleChange} />
39+
<SelectBox option={['최신순', '댓글순', '인기순']} title="최신순" onChange={handleChange} value={ getCurrentSort()} />
2740
</div>
2841
);
2942
}

src/domains/recipe/components/main/Accordion.tsx renamed to src/domains/recipe/components/main/CocktailFilterRadios.tsx

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

33
import SelectBox from '@/shared/components/select-box/SelectBox';
4-
import { Dispatch, SetStateAction, useEffect } from 'react';
5-
import { useSearchParams, usePathname, useRouter } from 'next/navigation';
4+
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
5+
import { Dispatch, SetStateAction } from 'react';
66

77
interface Props {
88
setAlcoholBaseTypes: Dispatch<SetStateAction<string[]>>;
@@ -64,26 +64,17 @@ const SELECT_OPTIONS = [
6464
},
6565
];
6666

67-
function Accordion({ setAlcoholBaseTypes, setCocktailTypes, setAlcoholStrengths }: Props) {
67+
function CocktailFilterRadios({ setAlcoholBaseTypes, setAlcoholStrengths, setCocktailTypes } : Props) {
6868
const router = useRouter();
6969
const pathname = usePathname();
7070
const searchParams = useSearchParams();
7171

72-
// url 파라미터에서 값을 가져와 POST를 도와줌
73-
useEffect(() => {
74-
const abv = searchParams.get('abv');
75-
const base = searchParams.get('base');
76-
const glass = searchParams.get('glass');
77-
78-
setAlcoholStrengths(abv ? [abv] : []);
79-
setAlcoholBaseTypes(base ? [base] : []);
80-
setCocktailTypes(glass ? [glass] : []);
81-
}, [searchParams, setAlcoholStrengths, setAlcoholBaseTypes, setCocktailTypes]);
82-
8372
// 파라미터 값을 한글로 역 변환해주는 함수
8473
const getDisplayValue = (id: string, code: string | null): string => {
74+
// 파라미터에서 가져오는 값 없다면 전체로 표시 이 값을 전체가 아닌 타이틀이 나와야함
8575
if (!code) return '전체';
8676

77+
// 파라미터에서 가져오는 아이디가 선택한 아이디와 일치하는지
8778
const optionGroup = SELECT_OPTIONS.find((opt) => opt.id === id);
8879
if (!optionGroup) return '전체';
8980

@@ -147,9 +138,8 @@ function Accordion({ setAlcoholBaseTypes, setCocktailTypes, setAlcoholStrengths
147138
<SelectBox
148139
option={option}
149140
title={title}
150-
id={id}
151-
groupKey="filter"
152141
value={currentValue}
142+
align="left"
153143
onChange={(value) => handleSelect(id, value)}
154144
/>
155145
</li>
@@ -159,4 +149,4 @@ function Accordion({ setAlcoholBaseTypes, setCocktailTypes, setAlcoholStrengths
159149
);
160150
}
161151

162-
export default Accordion;
152+
export default CocktailFilterRadios;

src/domains/recipe/components/main/CocktailList.tsx

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import { Cocktail } from '../../types/types';
55
import CocktailCard from '@/domains/shared/components/cocktail-card/CocktailCard';
66
import { useSaveScroll } from '../../hook/useSaveScroll';
77

8+
9+
10+
811
interface Props {
912
cocktails: Cocktail[];
1013
}
1114

15+
16+
// Grid반응형 구조에서 virtual의 높이가 측정하기 힘든문제로 인해 virtual사용 포기
17+
1218
function CocktailList({ cocktails }: Props) {
1319
const { saveAndNavigate } = useSaveScroll({
1420
storageKey: 'cocktail_list_scroll',
@@ -20,36 +26,41 @@ function CocktailList({ cocktails }: Props) {
2026
saveAndNavigate(`/recipe/${cocktailId}`);
2127
};
2228

29+
30+
2331
return (
24-
<ul
25-
className="
26-
grid gap-8 lg:justify-between justify-center
27-
[grid-template-columns:repeat(1,minmax(0,250px))]
28-
sm:[grid-template-columns:repeat(2,minmax(0,250px))]
29-
md:[grid-template-columns:repeat(3,minmax(0,250px))]
30-
lg:[grid-template-columns:repeat(4,minmax(0,250px))]
31-
"
32+
<div
3233
>
33-
{cocktails.map(
34-
(
35-
{ cocktailImgUrl, cocktailId, cocktailName, cocktailNameKo, alcoholStrength, isKeep },
36-
i
37-
) => (
38-
<li key={`${cocktailId} - ${i}`} className="w-full">
39-
<Link href={`/recipe/${cocktailId}`} onClick={handleClick(cocktailId)}>
40-
<CocktailCard
41-
favor={isKeep}
42-
id={cocktailId}
43-
src={cocktailImgUrl}
44-
name={cocktailName}
45-
nameKo={cocktailNameKo}
46-
alcohol={alcoholStrength}
47-
/>
48-
</Link>
49-
</li>
50-
)
51-
)}
52-
</ul>
34+
<ul
35+
className="
36+
grid gap-8 lg:justify-between justify-center
37+
[grid-template-columns:repeat(1,minmax(0,250px))]
38+
sm:[grid-template-columns:repeat(2,minmax(0,250px))]
39+
md:[grid-template-columns:repeat(3,minmax(0,250px))]
40+
lg:[grid-template-columns:repeat(4,minmax(0,250px))]
41+
"
42+
>
43+
{cocktails.map(
44+
(
45+
{ cocktailImgUrl, cocktailId, cocktailName, cocktailNameKo, alcoholStrength, isKeep },
46+
i
47+
) => (
48+
<li key={`${cocktailId} - ${i}`} className="w-full">
49+
<Link href={`/recipe/${cocktailId}`} onClick={handleClick(cocktailId)}>
50+
<CocktailCard
51+
favor={isKeep}
52+
id={cocktailId}
53+
src={cocktailImgUrl}
54+
name={cocktailName}
55+
nameKo={cocktailNameKo}
56+
alcohol={alcoholStrength}
57+
/>
58+
</Link>
59+
</li>
60+
)
61+
)}
62+
</ul>
63+
</div>
5364
);
5465
}
5566
export default CocktailList;

0 commit comments

Comments
 (0)