ํ๋ก์ ํธ ์์๋งํฌ ๐ผ
https://www.youtube.com/watch?v=v78D9IcYdU8
1. Styled Component ํ์ฉ
์ด์ ํ๋ก์ ํธ์ ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ Styled Component
๋ฅผ ํ์ฉํด ๋ณด์๋ค๋ ์ ์ด๋ค.
Styled Component
๋ฅผ ํ์ฉํ๋ฉด ์ฝ๋๊ฐ ๊น๋ํ๊ฒ ์ ๋ฆฌ๋๊ณ ์ฝ๋ ์คํฌ๋กค์ด ์ค์ด๋ ๋ค.
html/css
๊ฐ ์ฝ๋์ ๋ถ๋ฆฌ๋์ด jsx
ํ์ผ์๋ ์์ ํ ๊ธฐ๋ฅ์ ์ํ ์ฝ๋๋ง์ด ๋ถ๋ฆฌ๋์ด ๊ด๋ฆฌ๋๋ฏ๋ก
ํ์ธ์ด ํธ๋ฆฌํ๊ณ ๊ตฌ์กฐ ํ์ธ์ ์ฉ์ดํ๋ค. ๋ํ ํด๋์ค ๋ช
์ ๋ํ ๊ณ ๋ฏผ์ ์ค์ผ ์ ์์๊ณ ,
์ค์๋ก ์ค๋ณต๋ ํด๋์ค๋ช
์ ๊ฐ๊ฒ ๋๋ ๊ฒฝ์ฐ๊ฐ ์์ด ์๋ชป๋ css
๊ฐ ์ ์ฉ๋์ด ์ค์ผ๋๋ ๊ฒฝ์ฐ๊ฐ ์์๋ค.
2. EventCard Component
1. type
{type !== 'wishlist' ? (
''
) : (
<S.Check
src={
checkList.includes(event_id)
? '/images/common/check-true.png'
: '/images/common/check-false.png'
}
onClick={() => handleChecked(event_id)}
/>
)}
EventCard
์ปดํฌ๋ํธ๋ ํ๋์ ์ปดํฌ๋ํธ ์ด์ง๋ง, wishlist
์ ๊ทธ ์ธ ํ์ด์ง์์ ํ์ฉ๋๊ฐ ๋ค๋ฅด๋ค.
์๋ฅผ ๋ค์ด checklist
๊ธฐ๋ฅ์ wishlist
์๋ง ์๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ๋ค์ ์ฐจ์ด๋ฅผ ๋ฐ๋ก ๊ด๋ฆฌํ ์ ์๋๋ก
๊ฐ ํ์ด์ง์์ EventCard
์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ฌ ๋ type
์ ๋ถ์ฌํ๋ค.
์ด type
์ด wishlist
์ธ์ง, ๊ทธ ์ธ์ธ์ง๋ฅผ ๊ตฌ๋ถํ์ฌ ๊ฐ๊ฐ ๋ค๋ฅด๊ฒ ๋ ๋๋งํ ์ ์๋๋ก ์์
ํ์๋ค.
์์ ์ ํ์ญ์ ๋ฅผ ์ํ ์ฒดํฌ๋ฆฌ์คํธ ๋ฟ๋ง ์๋๋ผ UX์ ์ธ ๊ด์ ์์๋,
๋ค๋ฅธ ํ์ด์ง์์๋ ์ด๋ฒคํธ ์์ฒด์ ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ ๋ฐ ์ฃผ๋ ฅํ๊ณ
wishlist
ํ์ด์ง์์๋ ์ด๋ฏธ user
๊ฐ ์ด๋ฒคํธ์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ํฅ๋ฏธ๋ฅผ ๊ฐ์ง ์ํ์ด๋ฏ๋ก
'์
์ฐฐ ๋ง๊ฐ ๋จ์ ์๊ฐ'๊ณผ '๋จ์ ํฐ์ผ ์'๋ฅผ ํ๊ธฐํ๋๋ก ํ์ฌ ๊ตฌ๋งค ์๊ตฌ๋ฅผ ์ฆ๋ํ ์ ์๊ฒ ๊ณ ์ํ์๋ค.
2. fetchLiked
๋ชจ๋ ํ์ด์ง์์ ๋ ๋๋ง ๋ eventCard
์ wishlist
ํฌํจ ์ฌ๋ถ์ ์ํ๋ฅผ ํ๋ฒ์ ๊ด๋ฆฌํ ์ ์๋๋ก
๊ธฐ๋ฅ์ ๋ฐ๋ก fetchLiked
ํจ์๋ก ๋ง๋ค์ด ๊ด๋ฆฌํ์๋ค.
์ด ํจ์๋ฅผ ๋ง๋ค ๋
recoil
์ฌ์ฉ๊ณผ ๊ณ ๋ฏผ์ ํด๋ณด๊ฒ ๋์๋ค.
ํ์ง๋ง ๋จ์ํ ํ๋ก ํธ ๋จ์์ ์ ์ฅ๊ณผ์ ์์ด ์ฌ์ฉํ ๋ฐ์ดํฐ๊ฐ ์๋๊ณ ,
์๋ก๊ณ ์นจ์ด๋ ์์์น ๋ชปํ ํ์ด์ง์ ๋ซํ ๋ฑ์ด ์๊ฒผ์ ๋์๋ ์ ์ง๊ฐ ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์
๋ฐฑ ๋จ๊ณผ ๋ฐ๋ก ๋ฐ๋ก ํต์ ํ๋ฉด์user data
์์์ ๊ด๋ฆฌ๋์ด์ผ ํ๋ค๊ณ ์๊ฐํ์๋ค.
๊ทธ๋์ user
๊ฐ liked(heart)
๋ฅผ ๋๋ฅผ ๋ ๋ง๋ค ํต์ ์ด ์ผ์ด๋ ์ ์์ด์ผ ํ๊ณ
๋ก๊ทธ์ธ ๋ user
๋ง ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฅ, ์ฆ TOKEN
์ ๋ถ์ฌ ๋ฐ์ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋ค์๋ค.
TOKEN
, url
, wishlist(data)
, event_id
๋ฅผ ์ฃผ์๋ก ์ ๋ฌ๋ฐ๋๋ก ํ๊ณ
const isExistData =
wishlist &&
wishlist.filter(el => el.event_id === Number(event_id)).length > 0;
wishlist data
์ ๋ค์ด์๋ event_id
์ data
์์ ๋ฐ์ event_id
๋ฅผ filter
๋ก ๋น๊ตํ์ฌ 1๊ฐ๋ผ๋ wishlist
์ data
๊ฐ ์กด์ฌํ๋ฉด DELETE
ํต์ ์ ์งํํ๊ณ ์กด์ฌํ์ง ์์ผ๋ฉด event_id
๋ฅผ ๊ธฐ์ค์ผ๋ก POST
ํต์ ์ ์งํํ๋ค.
์ด ํต์ ๊ณผ ํจ๊ป eventCard Component
๋ด๋ถ์์๋ wishlist ID
์ฌ๋ถ๋ฅผ includes
๋ก ์ฒดํฌํ์ฌ ์ปดํฌ๋ํธ ๋ด๋ถ์ heart
๋ฅผ ์ํ ๋ณํํ๋ค.
3. fetchLiked
ํ์ฉ๋ชจ๋ ํ์ด์ง์์ fetchLiked๋ฅผ ํธ์ถํ์ฌ EventCard
๊ฐ ๋ ๋๋ง ๋ ๋ ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ค.
const setId = (data, event_id) => {
fetchLiked(TOKEN, APIS.wishlist, data, event_id, setWishlist, getWishList);
};
์ฌ๊ธฐ์ getWishlist
๋ wishlist
๋ฅผ ๋ถ๋ฌ์ค๋ ํต์ ์ผ๋ก ๋ฐ๋ก ์ ์ธ๋ ๋ณ์์ ๋ด์๋๊ณ ์คํํ๋๋ก ํ๋ค.
3. Wishlist
ย ๐ wishlist
ํต์ ์ ํญ์ TOKEN
๊ฐ์ ๊ธฐ๋ณธ์ผ๋ก ๊ฐ๋๋ก ํ์ฌ ํ์ ๊ฐ๊ฐ์ wishlist
๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๊ด๋ฆฌํ ์ ์๋๋ก ํ๋ค.
1. emptyBox
UX์ ์ธ ๊ด์ ์์ wishlist
๊ฐ ๋น์ด์๋ค๊ณ ์๋ฌด๊ฒ๋ ๋
ธ์ถ๋์ง ์์ผ๋ฉด ์ฌ์ฉ์๋ ์์ง ๋ ๋๋ง์ด ์งํ ์ค์ธ์ง, wishlist
๊ฐ ๋น์ด์๋์ง ํ์
ํ๊ธฐ๊ฐ ์ด๋ ต๋ค. ๊ทธ๋์ ํ ๋์ ์ ์ ์๋๋ก wishlist.length
๋ฅผ ํ์ฉํ์ฌ 0
์ด๋ผ๋ฉด ๋ฏธ๋ฆฌ ์ง์ ํด๋ ๋ฌธ๊ตฌ (์ด๋ฒคํธ ์นด๋๋ฅผ ๋ด์์ฃผ์ธ์!) ๋ฅผ ๋ ๋๋ง ํ ์ ์๋๋ก ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฌ์ฉํ์๋ค.
2. handleChecked
const handleChecked = event_id => {
if (checkList.includes(event_id)) {
setCheckList(checkList.filter(el => el !== event_id));
} else {
setCheckList([...checkList, event_id]);
}
};
wishlist
์์๋ง ๋ ๋๋ง ๋๋ check icon
์ ํด๋ฆดํ ๋๋ง๋ค handleChecked
๊ฐ ์คํ๋๋ค.
checklist
๊ฐ ์ด๋ฏธ ํด๋น event_id
๋ฅผ ํฌํจํ๊ณ ์์ ๊ฒฝ์ฐ ๋ฐฐ์ด ๋ด์์ ์ญ์ ํ๊ณ , ํฌํจ๋์ง ์์์ ๊ฒฝ์ฐ ์ถ๊ฐํ๋ค.
3. handleDeleteChecked
const handleDeleteChecked = id => {
if (checkList !== []) {
let copy = [...wishlist];
setWishlist(copy.filter(el => !checkList.includes(el.id)));
setType('checked');
}
const url = `${APIS.wishlist}`;
const deleteCards = checkList.join(',');
fetch(`${url}/${deleteCards}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json;charset=urf-8',
Authorization: TOKEN,
},
}).then(response => {
if (response.ok) {
getWishList();
}
});
};
์์ handleChecked
๋ก ๋ง๋ checklist
๋ฐฐ์ด์ด ๋น๋ฐฐ์ด์ด ์๋ ๊ฒฝ์ฐ setWishlist
๋ฅผ ํ์ฉํ์ฌ wishlist
์์ checklist
( ์ญ์ ๋ฅผ ์ํด ์ ํ๋ ์ด๋ฒคํธ ๋ค์ id
๊ฐ ํฌํจ๋ ๋ฐฐ์ด ) ์ ํฌํจ๋ id
๋ฐฐ์ด์ join
ํ์ฌ endpoint
์ ๋ด์ ๋ณด๋์ผ๋ก์จ ์ ํ๋ event๋ฅผ wishlist
์์ ์ญ์ ํ๋ค.
์ด ๋ type
์ checked
๋ก ์ง์ ํจ์ผ๋ก์จ ์ญ์ ๋ชจ๋ฌ์ด ๋ด์ ๋ ์ ํ ์ญ์ ๋ฅผ ์งํํ ์ง ์ ์ฒด ์ญ์ ๋ฅผ ์งํํ ์ง ์ ๋ฌํ๋ค.
4. handleDeleteAll
wishlist
๋ฐฐ์ด ๋ด ๋ชจ๋ ๊ฐ์ฒด๋ฅผ join
ํด์ endpoint
์ ๋ด์ ๋ณด๋์ผ๋ก์จ ๋ชจ๋ wishlist
๋ฅผ ์ญ์ ํ๋ค.
5. ๋ฌดํ๋ ๋๋ง (๋๋ณด๊ธฐ)
let limit = searchParams.get('limit');
const handleMoreEvent = () => {
searchParams.set('limit', Number(limit) + 6);
setSearchParams(searchParams);
};
limit
์ ๋ฐฑ์๋์์ ๊ธฐ๋ณธ๊ฐ 6์ผ๋ก ์ ๋ฌ๋ฐ๊ณ ์๋ค. ๊ทธ๋์ ๋จผ์ limit
์ searchParams.get()
์ผ๋ก ๋ฐ์์ค๋๋ก ํ๋ค. ๊ทธ๋ฐ ๋ค์ ํ๋ฉด ํ๋จ์ ๋๋ณด๊ธฐ
๋ฒํผ์ ํด๋ฆญํ ๋ ๋ง๋ค limit
์ 6์ ๊ณ์ํด์ ๋ํ ์ ์๋๋ก ์์
ํ์๋ค.
EventList
1. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ฉ (
calendar/
range filter )
1. calendar
React-calendar
ํ์ฉ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ ๊ฒ์ ์ฒ์์ด๋ผ ์ฒ์ ์์
ํ ๋๋ ๋งค์ฐ ์์ ๊ฑฐ ๋ถํฐ ๋ง์ด ํค๋งธ๋ค. ์๋ก์ด ํ์ผ์ ์ถ๊ฐํด์ CSS
๋ฅผ ์ ์ฉํด ์ปค์คํฐ๋ง์ด์ง์ ํ ํ์ ๊ธฐ๋ฅ ์์
์ ๋ค์ด๊ฐ๋๋ฐ, ์ฒ์์ onClick
์์ฒด๊ฐ ๋์์ ํ์ง ์์ ๋๋ฌด ๋นํฉ์ค๋ฌ์ ๋ค. ๊ทธ๋์ ๊ทธ ๋ค์์ onChange
๋ฅผ ์ ์ฉํด ๋ณด๋ ์๋์ ์ ๋๋ก ํ์ง๋ง, ํ ํ
ํฌ ๋๋ฆฌ๊ฒ ์๋ํ๋ ๊ฒ์ด ๋ง์์ ๋ค์ง ์์๋ค.
๋ค์ ๊ณต์ ๋ฌธ์๋ฅผ ๊ผผ๊ผผํ ์ดํด๋ณด๋ onClickDay
๋ผ๋ ๋ฉ์๋๊ฐ ๋ฐ๋ก ์ ๋ฆฌ ๋์ด ์์๋ค. ์ด๊ฑธ ํ์ฉํ๋ ์ ์์ ์ผ๋ก ์ํ๋ ๋๋ก ์๋ํ๋ค. ์ด๋ ๊ฒ ์ถ๋ ฅํ userDate
๋ฅผ
const dateFormat = userDate => {
const year = userDate.getFullYear();
const month = String(userDate.getMonth() + 1).padStart(2, '0');
const date = String(userDate.getDate()).padStart(2, '0');
return `${year}-${month}-${date}`;
};
๋ฐฑ์๋์์ ํต์ ์ ์๋ง๋ ํํ๋ก ๋ง๋ค๋๋ก ํ๋ค. ์ฒ์์ ํ ์๋ฆฌ ์๋ง ์์ 0์ ๋ํด์ฃผ๋ ๊ฒ์ ๋ํด ์กฐ๊ธ ํค๋งธ๋๋ฐ padStart
๋ฅผ ํ์ฉํด์ ํด๊ฒฐํ๋ค.
padStart(size, '๋น์๋ฆฌ๋ฅผ ์ฑ์ธ string')
๊ทธ๋ฆฌ๊ณ ๋ค์ ์ด fomattedDate
๋ฅผ searchParams
์ ํ์ฉํ์ฌ ํด๋น ๋ ์ง์ ํด๋นํ๋ ์ด๋ฒคํธ๋ง ์ถ๋ ฅํ ์ ์๋๋ก ํ์๋ค.
2. Range Filter
material-ui (MUI)
ํ์ฉmin
๊ฐ๊ณผ max
๊ฐ์ value
๋ก ์ ๋ฌ๋ฐ์ query
์ ํ์ฉํ ์ ์๋๋ก ํ์๊ณ ,
๊ณต์ ๋ฌธ์๋ฅผ ํตํด step
์ ์ด์ฉํด ํ์ํ ๊ฐ๊ฒฉ(10๋จ์)์ผ๋ก๋ง ์ด๋ํ ์ ์๋๋ก ์ง์ ํ์๋ค.
์ด๋ค ํน์ ๊ฐ์ด ์ถ๊ฐ๋์ด ํํฐ๋ง ๋๋ ๊ฒ์ด ์๋๋ผ ํน์ ๊ฐ ๋ด์ ๋ฒ์๊ฐ ๊ณ์ ๋
ธ์ถ๋ ์ ์๋๋ก ํด์ผํ๊ธฐ ๋๋ฌธ์
min
๊ฐ๊ณผ max
๊ฐ์ url
์ minPrice
, maxPrice
๋ก ๊ธฐ๋ณธ์ผ๋ก ์ ๋ฌ๋๋๋ก ํ๋ค.
2. Category Component
- data ๊ตฌ์กฐ
{ "id": 1, "mainCategory": "์นดํ ๊ณ ๋ฆฌ", "subCategory": ["ํ์คํฐ๋ฒ", "์ฝ์ํธ", "ํผํฌ๋จผ์ค", "ํด๋์"], "key": "categoryId" }, { "id": 2, "mainCategory": "๋์ด", "subCategory": ["์ ์ฒด", "์ฑ์ธ"], "key": "ageRange" }, { "id": 3, "mainCategory": "๊ตญ๊ฐ", "subCategory": ["๊ตญ๋ด", "๋ฏธ๊ตญ", "ํธ์ฃผ", "์ผ๋ณธ"], "key": "countryId" }, { "id": 4, "mainCategory": "์ ์ฐฐ๊ฐ", "subCategory": "" }
๋ฉ์ธ ์นดํ
๊ณ ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ธ๋ถ ์นดํ
๊ณ ๋ฆฌ๊ฐ ๋๋์ด ์ง๋ ํํ์๋๋ฐ, ์ ์ฒด ์นดํ
๊ณ ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ํ์ผ๋ก ๋ง๋๋ ๊ฒ ์ข์ง ์์๊น? ๋ผ๊ณ ์๊ฐํด์ data
๊ตฌ์กฐ๋ฅผ ์์ ๊ฐ์ด ๋ง๋ค์๋ค. ์ฌ๊ธฐ์ key
๋ query
๋ฅผ ๋ฃ์ด์ฃผ์๋ค. ๊ทธ๋ฆฌ๊ณ mainCategory
๋ฅผ ๊ธฐ์ค์ผ๋ก component
ํ ํด์ map()
๋ฉ์๋๋ฅผ ํ์ฉํด์ ๊ตฌํํ์๋ค.
๋จผ์ subCategory๊ฐ array
๊ฐ ์๋ ๊ฒฝ์ฐ๋ฅผ ๋นผ๊ธฐ ์ํด Array.isArray(subCategory)
๋ฅผ ํ์ฉํ์๋ค.
* Array.isArray(subCategory ) - subCategory๊ฐ array ์ธ์ง ํ์ธ ํ ์๋๋ฉด subCategory๋ฅผ ๊ทธ๋๋ก ์ถ๋ ฅ - Array ์ผ ๊ฒฝ์ฐ : key ๊ฐ์ผ๋ก subcategory ๋ถ์ฌ (subcategory = ์ธ์ === subCategory ๋ฐฐ์ด ๋ด ๋ฌธ์ ๊ทธ์์ฒด) -> query๋ฅผ ์ํจ
<S.SubCategories key={subcategory} onClick={() => { handleCheckedCategory(String(idx + 1)); handleCategoryState(subcategory, data.key); }}
์ฌ๊ธฐ์ idx
์ +1 ์ ํ๋ ์ด์ ๋ ๋ฐฐ์ด์ idx
๊ฐ 0 ๋ถํฐ ์์ํ๊ณ ,
์ด idx
๋ฅผ ์ดํ data์ id
๊ฐ๊ณผ ๋น๊ตํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค !
3. DropBox Component
- data ๊ตฌ์กฐ
export const DROP_MENU = [ { id: 0, name: '๋ ์ง์', key: 'dateAsc' }, { id: 1, name: '๊ฐ๊ฒฉ ๋ฎ์ ์', key: 'priceAsc' }, { id: 2, name: '๊ฐ๊ฒฉ ๋์ ์', key: 'priceDesc' }, ];
์์ ์นดํ
๊ณ ๋ฆฌ data ๊ตฌ์กฐ์ ๋์ผํ๊ฒ id
๋ฅผ index
๋ก ํ์ฉํ์ฌ key
๊ฐ์ searchParams
๋ฅผ ํ์ฉํด orderBy
์ ์ ๋ฌํ ์ ์๋๋ก ํ๋ค.
4. handleCategoryState
const handleCategoryState = (category, key, categoryData) => {
const categoryIndex = categoryData.subCategory.indexOf(category) + 1;
const categoryIdArr = searchParams.getAll(key);
if (categoryIdArr.includes(String(categoryIndex))) {
const newArr = categoryIdArr.filter(el => el != categoryIndex);
searchParams.delete(key);
newArr.forEach(el => {
searchParams.append(key, el);
});
} else {
searchParams.append(key, categoryIndex);
}
setSearchParams(searchParams);
};
๋ฐฐ์ด์ index๊ฐ 0๋ถํฐ ์์ํ๋ฏ๋ก id ์ ๋ง์ถ๊ธฐ ์ํด +1์ ํด์ค๋ค.
categoryIdArr
๋ searchParams.getAll(key)
๋ฅผ ํตํด key
์ ์ผ์นํ๋ ํ๋ผ๋ฏธํฐ๋ฅผ array
๋ก ๊ฐ์ ธ์จ๋ค. ๊ทธ ๋ค includes
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ categoryIdArr
์ categoryIndex
๊ฐ ์ด๋ฏธ ํฌํจ๋์ด ์๋ ์ง ํ์ธํ๊ณ ์๋ค๋ฉด ํด๋น ์นดํ
๊ณ ๋ฆฌ ์ธ๋ฑ์ค๋ฅผ ์ ์ธํ ์๋ก์ด ๋ฐฐ์ด (newArr
)๋ฅผ ๋ง๋ค๊ณ ๊ธฐ์กด ์ฟผ๋ฆฌ๋ฅผ ์ง์ฐ๊ณ ๋ค์ append
ํ์ฌ ์ค๋ณต๋ ์นดํ
๊ณ ๋ฆฌ๋ฅผ ์ญ์ ํ๋ค.
๋ง์ฝ ์ค๋ณต๋ ์ธ๋ฑ์ค๊ฐ ์๋ค๋ฉด append
ํ๋ค.
๋ ๋ง์ง๋ง ์ค์ setSearchParams(searchParams)
๋ฅผ ํตํด ์๋ก๊ณ ์นจ ์์๋ ์ฟผ๋ฆฌ๊ฐ ์ ์ง๋ ์ ์๋๋ก ๊ตฌํํ์๋ค.
* value(min/max), limit, location.search, checkLiked ์์กด์ฑ ๋ฐฐ์ด
5. API fetch
useEffect(() => {
const url = `${APIS.events}${location.search}&minPrice=${value[0]}&maxPrice=${value[1]}`;
fetch(url)
.then(response => response.json())
.then(result => {
setCardData(result.data);
});
}, [value, limit, location.search, checkLiked]);
fetch
์ ์์กด์ฑ ๋ฐฐ์ด์๋ value
(mixPrice / maxPrice), location.search
(์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ), checkLiked
(๊ฐ๋ณ ์ข์์ ํต์ ) ๋ฅผ ๊ฐ๋๋ค.
5. goToTop Component
์๋จ ์ด๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋์๋ UX/UI ๋ถ๋ถ์์ ๊ณ ๋ฏผ์ ์ข ํด๋ณด์๋ค.
ํ๋ฉด์ ํํ๊ฐ ์ข/์ฐ๋ก ๋ช
ํํ๊ฒ ๋๋์ด์ ธ ์๊ณ , ์ข์ธก ์นดํ
๊ณ ๋ฆฌ ์ฒดํฌํ๋ ๋ถ๋ถ์ ๋ง์ฐ์ค๊ฐ ์์ฃผ ์ด๋ํ ์ ์๋ค๋ ์ ์
๊ฐ์ํ์ฌ ๋ค๋ฅธ ํ์ด์ง๋ ์ฐ์ธก ํ๋จ์๋ง ์๋ ์๋จ ์ด๋ ์ปดํฌ๋ํธ๋ฅผ ์ข์ธก ํ๋จ์๋ ํด๋น ๋ถ๋ถ์ ๋ง๊ฒ ๋์์ธ์ ์์ ํ์ฌ ๊ตฌํํ๋ค. ์ด ๊ฒ๋ ์์ Eventcard component
๊ฐ wishlist
์์๋ง ๋ค๋ฅด๊ฒ ๋ํ๋ ์ ์๋๋ก ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํ๋ ๊ฒ ์ฒ๋ผ type
์ ๋ถ์ฌํด์ ํ์ด์ง๋ฅผ ๊ตฌ๋ถํ์ฌ ํ์ด์ง์ ๋ง๋ ๋ค๋ฅธ ๋์์ธ์ด ๋์ฌ ์ ์๋๋ก ๊ตฌํํ์๋ค.