ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] fetch( ) 메서드를 사용하여 API 호출하기
    Develope/React 2020. 5. 23. 14:09

    react.logo

    1. fetch란

    ◎ fetch API를 이용하면 RequestResponse와 같은 HTTP의 파이프라인을 구성하는 요소를 조작하는 것이 가능하다.

    또한 fetch() 메서드를 이용하는 것으로 비동기 네트워크 통신을 알기 쉽게 기술할 수 있다.

    2. 특징

    • fetch( )로 부터 반환되는 HTTP Status Code가 404나 500을 반환하더라도 Promise 객체는 HTTP error 상태를 reject하지 않는다. 대신 ok 상태가 fasle인 resolve가 반환되며, 네트워크 장애나 요청이 완료되지 못한 상태에는 reject가 반환된다.

    • 보통 fetch는 쿠키를 보내거나 받지 않는다. 사이트에서 사용자 세션을 유지 관리해야 하는 경우 인증되지 않는 요청이 발생한다. 쿠키를 전송하기 위해서는 자격증명 옵션을 반드시 설정해야 한다.

    3. 문법

    ◎ fetch( )의 기본 문법은 다음과 같다.

    fetch("API 주소", {
     method: "GET" // or "POST"
     headers: {
      "Content-Type": "application/json",
     },
     bodys: JSON.stringfy({
       key: value,
     })
    })
    .then(response => response.json())
    .then(response => console.log(response)).catch(err => console.log(err));
    • fetch( ) 메서드에 첫 번째 파라미터는 API 주소, 두 번째 파라미터에는 request의 옵션을 적용한다.

    • method의 종류는 기본적으로 GET, POST가 있는데 GET조회할 때 사용하며, POST생성할 때 사용한다.

    • headers에는 메타정보들이 들어간다.

    • bodys에는 body에 담아서 보내고 싶은 내용을 보여준다. 바디는 객체로 이루어져있어야 하며, 객체에서 키값은 내가 정하는 게 아니고 백엔드에서 요구하는 키값으로 정해서 보내줘야 한다. js 파일로 작업을 했기 때문에 JSON.stringfy() 방식을 사용하여 해당 내용을 JSON으로 바꿔준다.

    • response.json( )은 받아온 data는 json타입인데 자바스크립트에서 사용하기 위해 js형식으로 바꿔주는 역할을 한다.

    • catch는 요청에 대한 에러를 받는다.

    4. 사용 예시

    ◎ 오픈 API를 호출하여 GET방식을 이용하여 해당 데이터(mosters)를 화면에 나타내게 하는 예시를 해보았다.

    해당 데이터가 화면에 나타내고 input에 monster의 name을 검색하면 해당 monster가 나타나게 해주는 것도 구현해보았다.

    ※ fetch( ) 메서드를 사용하고 filter함수를 사용한 코드이다.

    class App extends Component {
      state = {
        monsters: [],
        userInput: "",
      };
    
      // 데이터 로딩
      componentDidMount = () => {
        fetch("https://jsonplaceholder.typicode.com/users")
          .then(res => res.json())
          .then(res => this.setState({
            monsters : res
          }), () => console.log(this.state.monsters)).catch(err => console.log(err));
      };
    
      // SearchBox에 props로 넘겨줄 handleChange 메소드 정의
      handleChange = (e) => {
        this.setState({
          userInput : e.target.value
        });
      };
    
      render() {
        // 필터링 로직
        const { monsters, userInput } = this.state;
        const filtered = monsters.filter(monster => {
            // 검색했을 때 monster.name과 일치하는 것만 filter시키자.
            return monster.name.toLowerCase().includes(userInput);
        });
        console.log(filtered);
        return (
          <div className="App">
            <h1>컴포넌트 재사용 Monster Card</h1>
              <SearchBox handleChange={this.handleChange}/> 
              <CardList monsters={filtered} />
          </div>
        );
      }
    }
    
    export default App;

     

    react에서 GET방식으로 API를 요청할 때는 componentDidMount() 라이플 사이클에 적용하는 게 좋다.

    react flow에 따르면 constructor( ) -> render( ) -> return ( ) -> componentDidMount( )이기 때문에 전체적인 코드를 렌더 하고 나서 componentDidMount( ) 안에 fetch 메서드를 사용하여 데이터를 로딩한다.

    GET방식을 사용할 때는 methods: GET을 따로 설정을 생략해도 되며, 상황에 따라 headers와 bodys를 생략할 수 있다.

    ※ 상황에 따라 headers와 bodys를 사용해야 하는 경우가 있다. 필수적으로 생략할 수 없는 건 아니다. methods 정의는 해주면 더 직관적이기 때문에 좋다.

    요청 응답은 res로 받아오고 this.setState( )에 mosters에 받아온 res를 값으로 설정해주면 된다.

    consoled을 확인해 보면 받아온 데이터를 확인할 수 있다.

     

    이제 monster의 name으로 input value와 비교하면 되니까 filter함수를 사용하여 해당 monster가 필더링 되게 하면 된다.

    const filtered = monsters.filter(monster => {
      // 검색했을 때 monster.name과 일치하는 것만 filter시키자.
      return monster.name.toLowerCase().includes(userInput);
    });

    mosters의 name을 소문자로 변환하여 input에 소문자로 입력해도 필터링 되게 구현하였다.

    최종 코드는 includes함수를 사용하였지만, 처음 구현할 때는 indexOf()를 사용하여 구현했다.

    const filtered = monsters.filter(monster => {
      // 검색했을 때 monster.name과 일치하는 것만 filter시키자.
      return monster.name.toLowerCase().indexOf(userInput) !== -1;
    });

    하지만 더 직관적이고 가독성 좋은 코드를 위해서 includes함수를 바꿔서 사용하였다.

    class CardList extends Component {
      render() {
        const { monsters } = this.props;
        
        return (
          <div className="card-list">
            {
              monsters.map(monster => {
                return (
                  <Card 
                    key={monster.id}
                    id={monster.id}
                    name={monster.name}
                    email={monster.email}
                  />
                );
              })
            }
          </div>
          );
      }
    }
    
    export default CardList;

    CardList component에서 map 함수를 사용하여 props에서 받아온 mosters를 map 함수를 사용하여 Card component에 필요한 정보를 넘겨서 화면에 나타나게 하였다.

    5. 최종 결과

    6. 느낀 점

    ◎ API 정보를 fetch 메서드를 사용하여 처음 다뤄봤는데, 처음에는 어떤 상황일 때, 어떤 메서드를 사용하고 header, bodys를 언제 사용할지 헷갈렸는데, 하다 보니까 익숙해졌고, 직접 데이터를 다루니까 재미있었다.

    앞으로 프로젝트할 때도 fetch 메서드를 사용하여 백엔드와 소통해야 되는데 꾸준히 코딩하여 완벽하게 사용하고 싶다.

    ※ 참조

    https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Fetch%EC%9D%98_%EC%82%AC%EC%9A%A9%EB%B2%95

     

    Using Fetch

    Fetch API를 이용하면 Request나 Response와 같은 HTTP의 파이프라인을 구성하는 요소를 조작하는것이 가능합니다. 또한 fetch() 메서드를 이용하는 것으로 비동기 네트워크 통신을 알기쉽게 기술할 수 있

    developer.mozilla.org

     

Designed by Tistory.