코딩공부/T.I.L

2022-02-07 컴포넌트 내에서 AJAX 요청

지구야 사랑해 2022. 2. 7. 12:01

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를 호출함.

 

예제2

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