티스토리 뷰
하나씩 비교하면서 정리해 보겠다..
먼저 tanstack-query에 대해 알아보아야 하지 않겠는가?
1. Tanstack-query 란?
주로 서버 상태를 관리하기 위한 도구로 사용된다.
- 서버에서 데이터를 가져올때
- 데이터를 업데이트할 때
- 데이터를 동기화할 때
발생하는 복잡성을 줄여준다!
이는 API호출을 통해 데이터를 가져오고, 그데이터를 UI에 표기하고자 할 때 매우 유용하다.
2. Tanstack-query 사용하는 이유 !
💡 자동캐싱 :
데이터를 자동으로 캐시하고, 캐시된 데이터를 재사용함으로써 네트워크 사용을 최적화 하고 사용자 경험 개선
- 설명 : 성공적으로 패치된 데이터를 자동으로 캐시하고, 이를 통해 동일한 쿼리에 대한 중복 요청 방지
- 사용 방법: 지정된 쿼리 키(queryKey) 에 대한 데이터 패칭 요청이 자동으로 캐시
이후, 같은 쿼리키를 useQuery 호출은 캐시된 데이터를 반환
- 주의사항: 캐시된 데이터는 시간이 지남에 따라 만료될 수 있으며 React Query 설정을 통해 조절 가능
💡 백그라운드 데이터 동기화 :
애플리케이션 포커스를 받을 때 자동으로 데이터를 새로고침해 항상 최신의 상태 유지
애플리케이션이 포커스를 받을 때 자동으로 데이터를 새로 고침하는 기능을 제공한다.
즉, 애플리케이션의 사용자 인터페이스(UI)와 백엔드 서버간의 데이터를 최신 상태로 유지하면서,
사용자의 작업 흐름을 방해하지 않는 과정을 말한다.
네트워크상태 변화, 애플리케이션의 생명 주기 이벤트 등에 반응하여 데이터를 자동으로 업데이트
⭐매서드 및 매서드 사용방법 및 주의사항▼ ⭐
useQuery / useInfiniteQuery:
- 설명: 데이터를 패칭하고 캐싱하는 데 사용되는 훅
- useInfiniteQuery는 무한 스크롤 목록을 구현할 때 사용.
- 사용 방법: 쿼리 키, 패칭 함수 등을 인자로 전달하여 사용
- 주의사항: 적절한 쿼리 키를 선택해 데이터가 올바르게 캐시되고 재사용되도록 해야한다.
useMutation:
- 설명: 데이터를 생성, 업데이트, 삭제하는 비동기 로직을 실행하는 데 사용.
- 사용 방법: 뮤테이션 실행 함수를 인자로 전달하여 사용.
- 주의사항: useMutation후에 관련 쿼리를 무효화하거나 업데이트하여 최신 상태를 반영해야 한다.
queryClient.prefetchQuery:
- 설명: 특정 쿼리에 대한 데이터를 미리 패칭하고 캐싱하는 데 사용.
- 사용 방법: 쿼리 키와 패칭 함수를 인자로 전달하여 사용.
- 주의사항: 네트워크 요청이 많아지지 않도록 필요한 시점에만 사용해야 한다.
- 사용시점: 사용자가 애플리케이션을 다시 활성화할 때, 중요한 데이터를 미리 로드할 수 있다!
queryClient.invalidateQueries:
- 설명: 특정 쿼리의 캐시된 데이터를 무효화하고, 필요한 경우 자동으로 데이터를 다시 패칭하는 데 사용.
- 사용 방법: 무효화하고자 하는 쿼리 키를 인자로 전달하여 사용.
- 주의사항: 무효화 과정에서 네트워크 요청이 발생할 수 있으므로, 사용자 경험에 영향을 주지 않도록 주의해야 한다.
- 사용시점 1: 네트워크 상태 변경 감지 시_ 온라인 상태로 전환될 때, 백그라운드에서 데이터를 자동으로 업데이트
- 사용시점 2: 데이터 업데이트 후_ 사용자가 데이터 생성, 수정, 삭제 후 관련 쿼리를 무효화 후 최신 데이터로 업데이트
🔥주의사항🔥
- 데이터 동기화는 네트워크 요청을 발생시키기 때문에,
사용자의 데이터 사용량 및 베러티소모에 영향을 줄 수 있다. 때문에 필요한 시점에 한하여 신중하게 사용해야 한다.
- 대용량 데이터 동기화는 Wi-Fi연결 시에만 수행되도록 설정하는 것이 좋다.
💡 로딩 상태 및 에러 핸들링 :
데이터를 로딩하는 동안의 상태와 에러를 쉽게 관리할 수 있다.
isLoading , isError, error 상태로 반환.
이를 통해 데이터 패칭 중인지, 에러가 발생했는지 등의 상태를 쉽게 파악하고, 이에 따른 UI 조정 가능!!!
💡 데이터 패칭 및 업데이트를 위한 훅스 :
useQuery, useMutation 같은 훅스를 제공해 데이터 패칭 및 업데이트 로직을 쉽게 구현할 수 있다.
useQuery 훅
서버로부터 데이터를 읽어오는데 사용된다.
데이터를 비동기적으로 패치하고, 캐싱, 재사용, 자동 업데이트를 관리한다.
리펙토링하기
const [channelData, setChannelData] = useState([]);
const [originalData, setOriginalData] = useState([]);
const [sortBy, setSortBy] = useState('subscriberCount');
const { keyword } = useParams();
useEffect(() => {
const fetchData = async () => {
const searchKeyword = keyword;
const data = await readSearchKeyWord(searchKeyword);
// 중복 제거 후 정렬된 데이터로 업데이트
const uniqueSortedData = sortAndRemoveDuplicates(data, sortBy);
setChannelData(uniqueSortedData);
setOriginalData(uniqueSortedData);
};
fetchData();
}, [keyword, sortBy]);
// 정렬 옵션 변경 핸들러
const handleSortChange = (e) => {
setSortBy(e.target.value);
const sortedData = sortAndRemoveDuplicates(originalData, e.target.value);
setChannelData(sortedData);
};
// 중복 제거 및 정렬 함수
const sortAndRemoveDuplicates = (data, sortBy) => {
const uniqueData = Array.from(new Set(data.map((item) => item.channelTitle))).map((channelTitle) =>
data.find((item) => item.channelTitle === channelTitle)
);
const sortedData = uniqueData.sort((a, b) => parseInt(b[sortBy], 10) - parseInt(a[sortBy], 10));
return sortedData;
};
비동기적으로 사용하기 위해 useEffect을 이용
async, await을 사용하기 위해 const를 이용해 서버에서 데이터를 받아온다.
그리고 특정 값이 변할 때 마다 재요청을 하기 위해 정렬 함수도 함께 useEffect안에 선언
↓
const { data, isLoading, error } = useQuery({
queryKey: ['keyword', keyword, sortBy],
queryFn: () => readSearchKeyWord(keyword),
keepPreviousData: true
});
// 중복 제거 및 정렬된 데이터
useEffect(() => {
if (!data) return;
const uniqueChannelTitles = Array.from(new Set(data.map((item) => item.channelTitle)));
const uniqueData = uniqueChannelTitles.map((channelTitle) =>
data.find((item) => item.channelTitle === channelTitle)
);
const sortedData = uniqueData.sort((a, b) => parseInt(b[sortBy], 10) - parseInt(a[sortBy], 10));
setSortedAndUniqueData(sortedData);
}, [data, sortBy]);
// 정렬 옵션 변경 핸들러
const handleSortChange = (e) => {
setSortBy(e.target.value);
};
useQuery를 이용해 data, isLoading, error 매서드를 이용해
통신, 로딩, 에러처리 까지 한번에 할 수 있도록 사용.
- queryKey : 쿼리의 고유 식별자.
캐싱과 데이터 재패칭에 사용
[
"keyWord" : queryKey의 고정된 값으로 어떤 유형의 데이터를 다루는지 명시적으로 보여줄 수있다.
keyWord : queryKey의 동적인 부분으로 실행 시점에 결정되는 값. 이 값에 따라 결과값이 변한다.
sortBy : queryKey의 동적인 부분으로 실행 시점에 결정되는 값. 이 값에 따라 결과값이 변한다.
]
리펙토링 하기전 useEffect를 보면 keyWord와 sortBy 에 따라 리렌더링이 된다.
즉 리렌더링이 필요한 값을 동적으로 실행될 수 있는 자리에 넣어주면 된다!
- queryfn: 데이터 패칭 함수를 정의
인스턴스에 정의된 필요한 api 경로를 담고있는 함수를 정의
() => readSearchKeyWord(keyword)
api 통신을 하는 경로에 keyword를 추가해야 값을 받아 올 수 있다.
때문에 keyword를 인자값으로 전달해 주기 위해 () => readSearchKeyWord(keyword) 형태로 작성
**만약 인자로 전달할 값이 없다면 queryfn: readSearchKeyWord 이렇게만 작성해 주면 된다!
- keepPreviousData: true
새 데이터 패칭 중에도 이전 데이터를 보여준다. 사용자 경험 향상!!
페이지네이션, 정렬 시 새로운 값으로 받아오기 전까지 이전 화면을 그대로 보여줄 수있도록 하기 위해 사용했다.
이렇게 되면 새로운 값을 받아올 때까지 loading창이 아닌 이전 화면의 값을 그대로 보고 있기 때문에
사용자 경험이 향상된다!
고유한 배열 만들기!
if (!data) return [];
data가 없으면 빈배열로 보여줘!
↓ channelTitle 을 이용한 중복된 값 제거 후 새로운 배열 생성
const uniqueChannelTitles = Array.from(new Set(data.map((item) => item.channelTitle)));
위 코드는 뒤에서부터 봐보자.
(data.map((item) => item.channelTitle))
data 배열의 각항목(item)에서 item.channelTitle 속성을 추출한 값을
new Set
중복값을 제거한 고유 값들을 Set에 담는다!
Array.from
중복된 값을 제외한 모든 channelTitle 을 담고있는 Set을 배열로 만들어 준다
**Array.from은 새로운 배열 생성, new는 새로운 배열임을 명시, Set은 중복값 제거
const uniqueData = uniqueChannelTitles.map((channelTitle) =>
data.find((item) => item.channelTitle === channelTitle)
);
channelTitle 을 담고있는 배열을 .map을 이용해
const uniqueData = uniqueChannelTitles.map((channelTitle) => data.find((item)
channelTitle 을 담고 있는 새로운 배열과 원본배열을 가지고 처음 일치되는 값만을 추출하기위해서
item.channelTitle === channelTitle
channelTitle을 비교하여 가정 처음 값이 일치된다면
원본배열에서 해당값을 배열 안의 객체로 놓고 새로운 배열에 있던 일치된 channelTitle은 사라짐.
이렇게 해서 channelTitle이 가장 처음 일치하는 원본배열 값만을 추출!
즉, 중복이 없는 고유 channelTitle 배열과
원본 배열이 가지고 있던 channelTitle을 비교해
가장 처음 일치되는 값이 있다면 해당 값만 추출.
일치되는 값을 찾게 되면 다음 channelTitle과 원본배열에 있는 item.channelTitl 이 일치되는 값을 찾아 또 배열에 추가
const sortedData = uniqueData.sort((a, b) => parseInt(b[sortBy], 10) - parseInt(a[sortBy], 10));
uniqueData에서 받은 값을 정렬하기 위해서
parseInt를 이용해 10진법으로 정수로 변환
**sortBy에는 구독자수(subscriberCount), 영상조회수(averageViewCount) 총 2개의 값이 전달된다!
객체에서 subscriberCount를 찾거나, averageViewCount를 찾아서 재정렬을 해준다.
const handleSortChange = (e) => {
setSortBy(e.target.value);
};
때문에 핸들러에서는 value만 setSortBy에 전달하면 된다!
'TIL' 카테고리의 다른 글
CSS :hover :active :focus 차이 (0) | 2024.03.03 |
---|---|
loadingbar 만들기! (0) | 2024.02.29 |
Outsourcing-Project 시작! (Figma 활용) (0) | 2024.02.23 |
Input Custom Hook 만들어보기 (0) | 2024.02.20 |
.env.local 환경변수 사용하기 (0) | 2024.02.20 |
- Total
- Today
- Yesterday
- styled component 조건부 사용방법
- axiosinstance 사용 시 토큰 사용 법
- 별점 색채우기
- Fetch와 Axios 의 장단점
- 유효성검사 css
- simple Icon 사용방법
- styled component 사용방법
- readme 이미지 추가 방법
- 유효성검사
- readme 작성 방법
- styled component GlobalStyle 사용방법
- axios instance 작성하기
- axios 사용하기
- Warning: Each child in a list should have a unique "key" prop.
- styled component 설치방법
- 영화별점만들기
- readme 작성해야 하는 이유
- readme 역할
- Warning: validateDOMNesting(...): <li> cannot appear as a descendant of <li>
- readme작성해보기
- 에러모음집
- 별점만들기
- git cache
- axios CRUD
- Warning: A component is changing an uncontrolled input to be controlled.
- axios 설치하기
- nextjs 토큰 만료처리하기
- 영화 별점
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |