Data Fetching: 필터링 예제 다시 보기
목록 내 필터링을 구현하기 위해서는 다음과 같은 두 가지 접근이 있을 수 있음.
1. 컴포넌트 내에서 필터링: 전체 목록 데이터를 불러오고, 목록을 검색어로 filter 하는 방법
2. 컴포넌트 외부에서 필터링: 컴포넌트 외부로 API 요청을 할 때, 필터링 한 결과를 받아오는 방법 ( 보통, 서버에 매번 검색어와 함께 요청하는 경우)
1. 컴포넌트 내에서 필터링
처음 단 한 번, 외부 API로부터 명언 목록을 받아오고, filter 함수를 이용함.
import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
const [proverbs, setProverbs] = useState([]);
const [filter, setFilter] = useState("");
useEffect(() => {
console.log("언제 effect 함수가 불릴까요?");
const result = getProverbs();
setProverbs(result);
}, []);
const handleChange = (e) => {
setFilter(e.target.value);
};
return (
<div className="App">
필터
<input type="text" value={filter} onChange={handleChange} />
<ul>
{proverbs
.filter((prvb) => {
return prvb.toLowerCase().includes(filter.toLowerCase());
})
.map((prvb, i) => (
<Proverb saying={prvb} key={i} />
))}
</ul>
</div>
);
}
function Proverb({ saying }) {
return <li>{saying}</li>;
}
2. 컴포넌트 외부에서 필터링
검색어가 바뀔 때마다, 외부 API를 호출함.
import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
const [proverbs, setProverbs] = useState([]);
const [filter, setFilter] = useState("");
const [count, setCount] = useState(0); // 다름
useEffect(() => {
console.log("언제 effect 함수가 불릴까요?");
const result = getProverbs(filter); // 다름
setProverbs(result);
}, [filter]); //다름
const handleChange = (e) => {
setFilter(e.target.value);
};
const handleCounterClick = () => {
setCount(count + 1); // 함수가 다름
};
return (
<div className="App">
필터
<input type="text" value={filter} onChange={handleChange} />
<ul>
{proverbs.map((prvb, i) => ( // 다름
<Proverb saying={prvb} key={i} />
))}
</ul>
<button onClick={handleCounterClick}>카운터 값: {count}</button> //다름
</div>
);
}
function Proverb({ saying }) {
return <li>{saying}</li>;
}
두 방식의 차이점
만약 서버에서 수십만 개의 명언을 제공한다고 가정하자. 이때
장점 | 단점 | |
컴포넌트 내부에서 처리 | HTTP 요청의 빈도를 줄일 수 있다 | 브라우저(클라이언트)의 메모리 상에 많은 데이터를 갖게 되므로, 클라이언트의 부담이 늘어난다 |
컴포넌트 외부에서 처리 | 클라이언트가 필터링 구현을 생각하지 않아도 된다 | 빈번한 HTTP 요청이 일어나게 되며, 서버가 필터링을 처리하므로 서버가 부담을 가져간다 |
Ex1) AJAX 요청을 보냅시다!
useEffect(() => {
fetch(`http://서버주소/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
});
}, [filter]);
AJAX 요청이 매우 느릴경우
외부 API 접속이 느릴 경우를 고려하여, 로딩 화면의 구현(Loading indicator)은 필수적 !
- 기본적으로, Loading indicator의 구현 역시 상태 처리가 필요함!
const [isLoading, setIsLoading] = useState(true);
// 생략, LoadingIndicator 컴포넌트는 별도로 구현했음을 가정합니다
return {isLoading ? <LoadingIndicator /> : <div>로딩 완료 화면</div>}
- fetch 요청의 전후로 setIsLoading을 설정해 주어 보다 나은 UX를 구현할 수 있음.
useEffect(() => {
setIsLoading(true);
fetch(`http://서버주소/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
setIsLoading(false);
});
}, [filter]);
Self Guided Lessons
실무에서는, 서버의 부담과 클라이언트의 부담이 적절하게 분배된 애플리케이션 구조를 가지게 됩니다. 이러한 내용에 대해 궁금하다면, 다음 내용을 공부해 보는 것도 좋습니다.
클라이언트가 서버에 요청을 덜 보내는 방법
서버가 클라이언트에게 돌려줄 응답을 캐싱하는 방법
HTTP 및 서버 구현에 대한 이해가 필요합니다.
'코딩공부 > T.I.L' 카테고리의 다른 글
2022-02-09 CORS 리뷰 및 적용 (0) | 2022.02.09 |
---|---|
2022-02-09 Web Server 기초 성취목표 (0) | 2022.02.09 |
2022-02-07 Effect Hook(2) - 조건부 실행 (0) | 2022.02.07 |
2022-02-07 Effect Hook (1) - 기본 (0) | 2022.02.07 |
2022-02-07 Side Effect (0) | 2022.02.07 |