-
Notifications
You must be signed in to change notification settings - Fork 2
๐ ์น์์ผ์ ์ฑํ ๋ฐ์ดํฐ์ REST API์ ์ฑํ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๊ด๋ฆฌํ๊ธฐ
๋ถ์ผ | ์์ฑ์ | ์์ฑ์ผ |
---|---|---|
FE | ์กฐ๋ฐฐ๊ฒฝ | 24๋ 12์ 04์ผ |
์ฐ๋ฆฌ ์๋น์ค์ ์ฑํ ์, ์น์์ผ์ผ๋ก๋ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ก์์ ํ๊ณ rest api๋ก๋ ์ด์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
๊ฐ๊ฐ ๋ฐ๋ ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ๊ด๋ฆฌํ๊ณ ์ ์ฑํ
๋ฐ์ดํฐ์ ์ํ๋ฅผ chatData
์ ์ ์ฅํ๋ค.
์ด chatData
์๋ ์น์์ผ์ด ์ ๊ณตํ๋ ์ต์ ์ฑํ
20๊ฐ์, ๋ฌดํ์คํฌ๋กคํด์ ๊ฐ์ ธ์ค๋ rest api์ ์ฑํ
๋ฐ์ดํฐ๋ฅผ ๋์ ํ์ฌ ์ ์ฅํ๋ค.
์ด๋, ์น์์ผ์ ๊ณ์ํด์ ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์ต์ ๋ฐ์ดํฐ 20๊ฐ๋ฅผ ์ ์งํ๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ก์์ ํ ๋๋ง๋ค rest api๋ ์น์์ผ์ด ๊ฐ๊ณ ์๋ ๋ฐ์ดํฐ ์ค ๊ฐ์ฅ ๋ง์ง๋ง์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ์ตํ๊ณ , ์ด๋ฅผ ๊ฐ์ ธ์์ผํ๋ค.
์ฆ ์น์์ผ ๋ฐ์ดํฐ๋ฅผ ์๋ก ๋ฐ์์ฌ ๋๋ง๋ค latestChatId๋ฅผ ์ ๋ฐ์ดํธํ์ฌ, ํด๋น ์ง์ ๋ถํฐ rest api๋ก ๋ค์ ๊ฐ์ ธ์จ๋ค.
๋จ์ํ ์ฑํ ์ก์์ , ๋ฌดํ์คํฌ๋กค, ์ข์์ ๊ธฐ๋ฅ๋ง ์์ ๋์๋ ์ด ๋ฐฉ๋ฒ์ด ๊ฐ๋ฅํ๋ค.
ํ์ง๋ง ์ฑํ ์ ์ข์์์์ผ๋ก ์ ๋ ฌํ๋ api๋ฅผ ์ถ๊ฐํด๋ณธ๋ค๋ฉด ์ด๋จ๊น?
chatData๊ฐ ๋ชจ๋ ์ ๋ ฌ์ด ์ ์ฉ๋ผ์ผ ํ๋ฏ๋ก, chatData์ ์ํ ์น์์ผ์ผ๋ก ๋ฐ์์จ ๋ฐ์ดํฐ๋ ์ ๋ ฌ์ด ๋์ด์ผ ํ๋ค.
ํ์ฌ ๊ตฌ์กฐ๋ก๋ ์ฃผ์ด์ง api๋ api๋ก ๋ฐ์์จ ๋ฐ์ดํฐ์ ํํด์๋ง ์ ๋ ฌ์ด ๋ ๊ฒ์ด๋ค.
chatData์ ์์ 20๊ฐ๋ ํญ์ ์น์์ผ์ด๊ธฐ ๋๋ฌธ์, ์ด ๋ฐฉ์๋๋ก๋ผ๋ฉด ์น์์ผ ๋ฐ์ดํฐ๋ ์ ๋ ฌ์ด ๋์ง ์์ ๊ธฐ๋์๋ ๋ค๋ฅธ ํ๋ฉด์ด ๋์ฌ ๊ฒ์ด๋ค.
ํ ์ํฉ์ผ๋ก ๊ฐ ๋ฐ์ดํฐ์ ์ญํ ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์น์์ผ ๋ฐ์ดํฐ: ์์ 20๊ฐ ๋ฐ์ดํฐ ๋ชฉ๋ก + ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ ์ก์์
- rest api์ ๋ฐ์ดํฐ: ๋ฌดํ์คํฌ๋กค๋ก ๋ฐ๋ ์ด์ ์ฑํ ๋ฐ์ดํฐ ๋ชฉ๋ก
๋ฐ์ดํฐ ๋ชฉ๋ก์ ์น์์ผ๊ณผ rest api ๋ชจ๋ ๋ฐ๊ณ ์๋๋ฐ, rest api์๋ง ์ฑ ์์ ๋ถ์ฌํ์.
๊ทธ๋ ๊ฒ ํด์ ๋ค์ ์๊ฐํ ์ญํ ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์น์์ผ ๋ฐ์ดํฐ: ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ ์ก์์ (1๊ฐ์ฉ ๋ฐ๊ฒ๋จ)
- rest api์ ๋ฐ์ดํฐ: ์ค์๊ฐ์ ์ ์ธํ ๋ชจ๋ ์ฑํ ๋ฐ์ดํฐ ๋ชฉ๋ก
์ด๋ ๊ฒ ์ญํ ์ ๋๋๋ฉด, ์ข์์์์ผ๋ก ๋ค์ ์ ๋ ฌ ์์ฒญ์ ํ๋ค๋ฉด ๋ชจ๋ ๋ฐ์ดํฐ์ ๋ฐ์๋ ๊ฒ์ด๋ค.
๊ธฐ์กด์๋, useInfiniteQuery
๋ฅผ ์ฌ์ฉํ๋ ์ชฝ์์ ์ปค์คํ
ํ์ฌ latestChatId๋ฅผ ๋ณด๋ด์คฌ๋๋ฐ, useInfiniteQuery
์ ๊ธฐ๋ฅ์ ํ์ฉํด์ ๋ฐ๊ฟ๋ณด์.
๋ฐ์์์ผํ๋ ์ฑํ ๋ชฉ๋ก ์ค ๊ฐ์ฅ ์ต์ ์ ์ฑํ ์ id๋ฅผ page ์ฒ๋ผ ์ฐ๊ณ ์์ผ๋, ์ด๋ฅผ ๋ น์ฌ๋ด์.
export const useGetChatList = ({
stockId,
latestChatId,
pageSize,
order,
}: GetChatListRequest) => {
return useInfiniteQuery({
queryKey: ['chatList', stockId, order],
queryFn: ({ pageParam }) =>
getChatList({
stockId,
latestChatId: pageParam?.latestChatId,
pageSize,
order,
}),
// lastestChatId๋ฅผ nextPageParam์ผ๋ก์จ ๋๊ธฐ๊ณ ์ ํจ
getNextPageParam: (lastPage) =>
lastPage.hasMore
? {
latestChatId: lastPage.chats[lastPage.chats.length - 1].id,
}
: undefined,
// initialPageParam ์ง์
initialPageParam: { latestChatId },
// select ์ต์
์ ํตํด ํ์ํ ๋ฐ์ดํฐ๋ง ๋ฝ์์ ์ฌ์ฉ
select: (data) => ({
pages: [...data.pages].flatMap((page) => page.chats),
pageParams: [...data.pageParams],
}),
});
};
์ปดํฌ๋ํธ์์๋ ์ด๋ป๊ฒ ์ฌ์ฉํ๋ฉด ๋ ๊น?
const { fetchNextPage, data, status, isFetching, hasNextPage } =
useGetChatList({
stockId,
order,
});
// IntersectionObserver์ ์ํด ๊ฐ์ง๋๋ฉด ์คํ
const fetchMoreChats = () => {
fetchNextPage(); // ๋ค์ ํ์ด์ง ์คํ
// ์๋ต์ด ์ฑ๊ณต์ ์ด๋ฉด ๋ฐ์ดํฐ ์ ์ฅ
if (status === 'success') {
setChatData(data.pages);
}
};
const { ref } = useInfiniteScroll({
onIntersect: fetchMoreChats,
hasNextPage,
});
- useGetChatList๋ฅผ ๋ถ๋ฌ์จ๋ค.
- observer๋ฅผ ํตํด ํน์ ์์ญ์ ๋ฟ๋ ๊ฒ์ ๊ฐ์งํ๊ณ ๋ฐ์ดํฐ๋ฅผ ํจ์นญํ๋ค.
// ์ ๋ ฌ์ ํ์ฌ ๋ฐ์ดํฐ๊ฐ ๋ณํ๋ค๋ฉด ์๋กญ๊ฒ ์ ์ฅํด์ผํ๋ค.
useEffect(() => {
if (status === 'success') {
setChatData(data.pages.flat());
}
}, [data, status]);
- ๋ณดํต ๋ฌดํ์คํฌ๋กค์ observer๋ก ๊ฐ์ง๋๋ฉด fetchNextPage๋ฅผ ์คํํ๋๋ฐ, ์ ๋ ฌ๋ก ์ธํ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ๋ฐ๋ก ๊ฐ์งํ์ง ๋ชปํ๋ค.
- ๋ฐ๋ผ์ useEffect๋ก ๊ฐ์ธ์ ๋ฐ์ดํฐ๊ฐ ๋ณํํ๋ฉด ์๋ก ์ ์ฅํ๋ค.
const handleChat = useCallback((message: ChatDataResponse | ChatData) => {
// chats ๋ฐฐ์ด๋ก ์ค๋ ์๋ต์ return
if ('chats' in message) return;
// ์ค์๊ฐ์ผ๋ก ์๋ต์ค๋ ๋จ์ผ ๋ฉ์์ง๋ง chatData์ ์ ์ฅ
const validatedSingleChat = ChatDataSchema.parse(message);
if (validatedSingleChat) {
setChatData((prev) => [{ ...validatedSingleChat } as ChatData, ...prev]);
}
}, []);
- ์น์์ผ์์ ์ฑํ ๋ธ๋ก๋์บ์คํธ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์คํ๋๋ ํจ์์ด๋ค.
- ์์ 20๊ฐ ๋ชฉ๋ก์ chats ๋ฐฐ์ด๋ก ์ค๊ณ , ๋จ์ผ ๋ฉ์์ง ์ก์์ ์ ๋จ์ผ ๊ฐ์ฒด๋ก ์ค๊ธฐ ๋๋ฌธ์ ์ด ์ ์ ๊ฐ์ง๊ณ ๊ฒ์ฌ๋ฅผ ํ๋ค.
- ๐ฉ FE ๊ธฐ์ ์ ํ์ด์
- โจ ์ฐจํธ์ ๋ฐ์ํ ๊ตฌํ๊ณผ useRef ํ์ ๋ฌธ์
- ๐ฃ ๋ถ๋ชจ ์์์ ์ํ์ ๋ฐ๋ผ ์์ ์์๋ ์คํ์ผ ๋ณํ ๋ถ์ฌํ๊ธฐ
- ๐ zod ๋์ ํ๊ธฐ
- ๐ useInfiniteQuery๋ฅผ ์ฌ์ฉํ ๊ทธ๋ํ ๋ฌดํ์คํฌ๋กค ๊ตฌํ
- ๐ซ ์ฌ์ฉ์์ ์์ ๋ณํ ์๋ ๊ทธ๋ํ ์คํฌ๋กค ๊ตฌํํ๊ธฐ
- ๐งช ์๋ง์ ๊ทธ๋ํ ๋ฐ์ดํฐ ์์ฒญ์ ์ด๋ป๊ฒ ์ค์ผ๊น
- ๐ ๋คํฌ๋ชจ๋์์ ์๋ก๊ณ ์นจ ์ ๋ผ์ดํธ๋ชจ๋๊ฐ ์ ๊น ๋ณด์ด๋ ๋ฌธ์
- ๐ ์น์์ผ์ ์ฑํ ๋ฐ์ดํฐ์ REST API์ ์ฑํ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๊ด๋ฆฌํ๊ธฐ
- ๐ก BE ๊ธฐ์ ์ ํ ์ด์
- โ๏ธ Node WebSocket ํ๊ณ ๋ค๊ธฐ
- โ๏ธ TypeORM Datasource mock ๋ง๋ค๊ธฐ
- โ๏ธ oauth ID range ๋ฌธ์
- ๐ custom pipe์์ Nan์ด ๋ฐ์์ง๋ ๋ฌธ์
- ๐ช nest Websocket์ ์ธ์ ์ด ์๋๋ค๊ณ ?
- ๐ด nginx websocket ์ฐ๊ฒฐ ์ ๋ฌธ์ ๋ฐ์
- ๐ WebPush ๊ตฌํ
- ๐ง ์ฐ์ ์์ ํ๋ก ์์ฒญ ์ ์ดํ๊ธฐ
- ๐ websocket์ด ๋ฆ๊ฒ ํ ๋น๋์ด ๋ฐ์๋๋ ๋ฌธ์
- ๐ฅณ typeorm์ ์ด์ฉํ FCM ์๋ฆผ ์๋น์ค
- ๐ฆ ๋ค์ค ์ ์ ๋์์ฑ ์ ์ด โ ์ฑ๊ธํค, ๋ฎคํ ์ค
- ๐ ๊ทธ๋ํ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ ๊ณตํ๊ธฐ์ํ ์ ๋ต
- ๐ ๏ธ ์ธํ๋ผ ๊ธฐ์ ์คํ ์ ํ ์ด์
- ๐ Ncloud ์ค์ ๊ณผ์
- ๐ ORM ๊ธฐ์ ์คํ ๋น๊ต
- ๐ค RabbitMQ๋ก ๋ถ์ฐ ์๋ฒ์๊ฒ ๋ฉ์์ง๋ฅผ ๋ถ๋ฐฐํ๊ธฐ
- ๐ข private DB ์๋ฒ์ ์ ์ํ์ง ๋ชปํ๋ ํ์
- ๐ 1์ฃผ์ฐจ ๋ฐํ
- ๐ 2์ฃผ์ฐจ ๋ฐํ
- ๐ 3์ฃผ์ฐจ ๋ฐํ
- ๐ 4์ฃผ์ฐจ ๋ฐํ
- ๐ 5์ฃผ์ฐจ ๋ฐํ
- ๐ ์ต์ข ๋ฐํ