๐ Task TODOLIST
- [x] ์ด์ ๋ฉ์ธ์ง ๋๋ณด๊ธฐ ๊ธฐ๋ฅ
- [x] ๋๋ณด๊ธฐ ๋ฒํผ ๋ง๋ค๊ธฐ
- [x] ๊ฐ์ ธ์ฌ ๋ฉ์ธ์ง๊ฐ ๊ฐ์ ธ์ค๊ณ ์ถ์ ๋ฉ์ธ์ง์ ๊ฐฏ์๋ณด๋ค ์ ์ผ๋ฉด? ๋๋ณด๊ธฐ ๋ฒํผ ์๋ณด์ด๊ฒ
โจ๊ฐ๋ฐ ๋ด์ฉ
1. ์ด์ ๋ฉ์ธ์ง ๋๋ณด๊ธฐ ๊ธฐ๋ฅ
Why ?
์ฒ์๋ถํฐ ๋ชจ๋ ๋ฉ์ธ์ง๋ฅผ ๋ค ๋ถ๋ฌ์ค๋ฉด ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐ์ ๋ถ๋ฌ์์ผ ํด์ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ด ๊ธธ์ด์ง ๊ฑฐ๋ผ๊ณ ํ๋จ.
How ?
(1) ์์ ์ฒ์์๋ 11๊ฐ์ ๋ฉ์ธ์ง๋ง ์๋ฒ๋ก๋ถํฐ ๋ฐ์์ CSR ํ์ด์ง์์ hydrationํจ์ผ๋ก์จ ์ด๊ธฐ ๋ก๋ฉ ์๋ ์ค์ด๊ธฐ
(2) ๊ทธ ์ดํ ์ด์ ๋ฉ์ธ์ง๋ฅผ ๋ ๋ณด๊ณ ์ถ๋ค๋ฉด, ๋๋ณด๊ธฐ ๋ฒํผ ๋๋ฅด๊ธฐ -> ์ด์ 10๊ฐ์ ๋ฉ์ธ์ง ๋ถ๋ฌ์ค๊ธฐ
what ?
๋ถ๋ฌ์ฌ ๋ฉ์ธ์ง ์ ์์ํ
export const ITEM_INTERVAL = 10;
๋๋ณด๊ธฐ ํ์์ ๋ฐ๋ฅธ ๋ถ๋ฌ์ฌ ๋ฉ์ธ์ง์ range๋ฅผ ๋ฐํํ๋ utility ํจ์ getFromTo ์์ฑ
export const getFromTo = (loadCount: number, idx: number) => {
const from = loadCount * (idx + 1);
const to = from + idx;
return { from, to };
};
์ด๊ธฐ ์๋ฒ์ฌ์ด๋ ์ปดํฌ๋ํธ์ธ chat/page.tsx ์์ ๊ฐ์ฅ ์ต์ 10๊ฐ์ ๋ฉ์ธ์ง๋ง ์์ฒญํ์ฌ, InitChat.tsx ๋ผ๋ CSR ์ปดํฌ๋ํธ์ props๋ก ๋๊ฒจ์ค
const ChatPage = async ({ params }: { params: { chatroom_id: string } }) => {
const chatRoomId = params.chatroom_id;
const supabase = serverSupabase();
const {
data: { user }
} = await supabase.auth.getUser();
const { from, to } = getFromTo(0, ITEM_INTERVAL);
const { data: allMsgs } = await supabase
.from('messages')
.select('*')
.eq('chatting_room_id', chatRoomId)
.range(from, to)
.order('created_at', { ascending: false });
return (
<Suspense fallback={<ChatLoading />}>
<div className="relative flex flex-row">
<InitChat user={user} chatRoomId={chatRoomId} allMsgs={allMsgs ?? []} /> --> CSR ์ปดํฌ๋ํธ
InitChat.tsx ํ์ผ์์๋ ๊ฐ์ ธ์จ ๋ฉ์ธ์ง๋ค๋ก ์ด๊ธฐ ์ฟผ๋ฆฌ๋ฐ์ดํฐ๋ก setQueryData()
if (allMsgs) {
queryClient.setQueryData([MSGS_QUERY_KEY, chatRoomId], [...allMsgs].reverse());
}
2. ๋๋ณด๊ธฐ ๋ฒํผ ๋ง๋ค๊ธฐ + ๊ฐ์ ธ์ฌ ๋ฉ์ธ์ง๊ฐ ๊ฐ์ ธ์ค๊ณ ์ถ์ ๋ฉ์ธ์ง์ ๊ฐฏ์๋ณด๋ค ์ ์ผ๋ฉด? ๋๋ณด๊ธฐ ๋ฒํผ ์๋ณด์ด๊ฒ
why?
๊ฐ์ ธ์ฌ ๋ฉ์ธ์ง๊ฐ ๊ฐ์ ธ์ค๊ณ ์ถ์ ๋ฉ์ธ์ง ๊ฐฏ์๋ณด๋ค ๋ง์ผ๋ฉด ๋๋ณด๊ธฐ ๋ฒํผ ๋ณด์ฌ์ฃผ๊ณ , ์ ์ผ๋ฉด ์ ๋ณด์ฌ์ค์ผ ํ๋๊น
= ๋ณํ๋ ์ํ๊ตฌ๋ = state ๋ง๋ค๊ธฐ
์ฒ์์ ๊ฐ์ ธ์ค๋ ๋ฐ์ดํฐ๋ถํฐ ์ ์ฉ์ด ๋์ด์ผ ํ๋๊น ์ด๊ธฐ ๋ฉ์ธ์ง๋ฅผ setQueryData()๋ฅผ ์ฌ์ฉํ๋ InitChat.tsx์์๋ ์ฐ์ด๊ณ , ์ค์ ๋ก ๋๋ณด๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋๋ณด๊ธฐ๊ฐ ๋๋ LoadChatMore.tsx์์๋ ์ฐ์ด๋ ์ ์ญ์ ์ผ๋ก ๊ด๋ฆฌํ์.
=> zustand store ์ฌ์ฉ
export const chatStore = create<chatState>()((set) => ({
chatRoomId: null,
hasMore: false, ---> ์ด๊ฒ
chatState: true,
isRest: true,
searchMode: false,
imgs: [],
onlineUsers: [],
setChatRoomId: (chatRoomId) => set({ chatRoomId }),
setHasMore: (hasMore) => set({ hasMore }), ---> ๋๋ณด๊ธฐํ ์ง ๋ง์ง setStateํ๋ ํจ์
setChatState: (isActive) => set({ chatState: isActive }),
setisRest: (isRest) => set({ isRest }),
setSearchMode: () => set((state) => ({ searchMode: !state.searchMode })),
setImgs: (imgs) => set({ imgs }),
setOnlineUsers: (onlineUsers) => set({ onlineUsers })
}));
How?
- ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๊ธฐ์ ๋ฉ์ธ์ง๋ฅผ ๊ฐ์ ธ์๋๋ฐ ๋๋ณด๊ธฐ ํด์ ๊ฐ์ ธ์ฌ ๊ฐฏ์(11๊ฐ) ๋ณด๋ค ์ ์ผ๋ฉด ์ฒ์๋ถํฐ ๋๋ณด๊ธฐ ๋ฒํผ์ ์จ๊ฒจ์ผ ํจ
if (allMsgs) {
queryClient.setQueryData([MSGS_QUERY_KEY, chatRoomId], [...allMsgs].reverse());
setHasMore(allMsgs.length >= ITEM_INTERVAL + 1);
}
์ฒ์์ ๊ฐ์ ธ์จ ๋ฉ์ธ์ง(allMsgs)๊ฐ ๋ถ๋ฌ์ฌ ๋ฉ์ธ์ง(ITEM_INTERVAL + 1) ๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์์ผ๋ง ๋๋ณด๊ธฐ ๋ฒํผ์ด ๋ณด์ด์.
- ๋๋ณด๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ์๋ก์ด ๋ฉ์ธ์ง๋ค์ ๋ถ๋ฌ์์ผ ํ๊ณ , ๊ฐ์ ธ์จ ๋ฉ์ธ์ง๊ฐ ๋ถ๋ฌ์ค๊ณ ์ถ์๋ ๋ฉ์ธ์ง๋ณด๋ค ์ ์ผ๋ฉด setHasMore(false)๋ก!
if (newMsgs.length < ITEM_INTERVAL + 1) {
setHasMore(false);
}
๐จ TroubleShotting
1. ๊ทธ๋ฐ๋ฐ! ์ด๋ ๊ฒ ํ๋๋, ์ฒ์ ๋ ๋๋ง ์์๋ ์ต์ 10๊ฐ๊ฐ ์ ๋ ๋๋ง ๋์์ง๋ง ๊ทธ ๋ค์ ์ด๋๋ฅผ ๊ฐ๋ค ์ค๊ฑฐ๋ focus out ํ ๋ค์ ๋์์ค๋ ์ ์ฒด ๋ฉ์ธ์ง๊ฐ ์๋ค๋ค ๋ ๋๋ง๋๋ ๊ฒ!
why?
์ด๊ธฐ์๋ setQueryData()๋ฅผ ํ์ง๋ง useSuspenseQuery๋ฅผ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ focus out ํ ๋์์ค๋ฉด useSuspenseQuery๊ฐ ์คํ๋๋ฉด์ ์ ์ฒด ๋ฉ์ธ์ง๋ฅผ ๋ค์ fetch.
What?
export const useMsgsQuery = (chatRoomId: string) => {
const { data } = useSuspenseQuery({
queryKey: [MSGS_QUERY_KEY, chatRoomId],
queryFn: () => fetchMsgs(chatRoomId),
refetchOnMount: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false
});
return data;
};
=> ์ง์ ๋๋ณด๊ธฐ or invalidate ํด์ผ๋ง ์ด์ ๋ฉ์ธ์ง๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋๋ก ์๋ refetch๋๋ ์ต์ ๋ชจ๋ false
๐ ๋ ํผ๋ฐ์ค
setQueryData()
https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata