본문 바로가기

WINK-(Web & App)/React.js 스터디

[2024 여름방학 React.js 스터디] 이종윤 #6주차

반응형

API

: API(application programing interface)는 소프트웨어 애플리케이션이 서로 통신하여 데이터, 특징 및 기능을 교환할 수 있도록 하는 일련의 규칙 또는 프로토콜이다.

$ npx create-react-app api-integrate

우선 이 코드로 React라는 JavaScript 라이브러리를 사용하여 새로운 웹 애플리케이션 프로젝트를 생성한다.

$ cd api-integrate
$ yarn add axios

그리고 그 만든 곳으로 이동하고 axios라이브러리를 설치한다.

axios를 사용해서 GET, PUT, POST, DELETE 등의 메서드로 API 요청을 할 수 있다.

 

<REST API>

  • GET: 데이터 조회
  • POST: 데이터 등록
  • PUT: 데이터 수정
  • DELETE: 데이터 제거
  • PATCH: 데이터 일부 수정
  • HEAD: 메타 데이터만 요청
import axios from 'axios';

axios.get('/users/1');

axios는 이렇게 사용하면 된다.

import axios를 해주고 axios.[명령어]('상대경로') 이렇게 써주면 된다!!!

그리고 axios.post() 로 데이터를 등록 할 때에는 두번째 파라미터에 등록하고자 하는 정보를 넣을 수 있다.

axios.post('/users', {
  username: 'blabla',
  name: 'blabla'
});

이렇게....

useState

useState는 React 함수형 컴포넌트에서 상태를 관리하는 데 사용되는 훅이다. 이 훅을 사용하면 컴포넌트가 재렌더링될 때도 유지되는 내부 상태를 정의할 수 있다.

useEffect

useEffect는 부수적인 효과를 처리하기 위해 사용된다. 여기서 부수적인 효과란, 컴포넌트가 렌더링될 때마다 발생해야 하는 작업을 의미한다. 예를 들어, 데이터 가져오기, DOM 조작, 구독(subscriptions), 타이머 설정 등이 포함된다.

 

요청에 대한 상태를 관리 할 때에는 위 두개를 사용하여 3가지 상태를 관리해주어야 한다.

1. 요청의 결과

2. 로딩 상태

3. 에러

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Users() {
  const [users, setUsers] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        // 요청이 시작될 때 error와 users를 초기화하고
        setError(null);
        setUsers(null);
        // loading 상태를 true로 바꿈
        setLoading(true);
        const response = await axios.get('https://jsonplaceholder.typicode.com/users');
        setUsers(response.data); // 데이터는 response.data 안에 있음
      } catch (e) {
        setError(e);
      }
      setLoading(false);
    };

    fetchUsers();
  }, []);

  if (loading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!users) return null;
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          {user.username} ({user.name})
        </li>
      ))}
    </ul>
  );
}

export default Users;

예제 코드를 보자

 

- 상태 관리하기

useState 훅을 사용하여 users, loading, error 세 가지 상태를 관리하고 있다.

users: API에서 받아온 사용자 데이터를 저장하는 상태이다. 초기값은 null이다.
loading: 데이터 요청 중인지 여부를 나타내는 상태이다. 초기값은 false이다.
error: 요청 중 발생한 오류를 저장하는 상태이다. 초기값은 null이다.
- useEffect로 데이터 요청하기
useEffect 훅을 사용하여 컴포넌트가 처음 렌더링될 때 API 요청을 실행하고 있다.
fetchUsers 함수는 비동기 함수로, API에서 데이터를 받아오는 역할을 한다.
요청을 시작할 때 오류와 사용자 데이터를 초기화하고, loading 상태를 true로 설정한다.
요청이 성공하면 response.data를 users 상태에 저장하고, 오류가 발생하면 error 상태에 오류 정보를 저장한다. 마지막으로 loading 상태를 false로 바꾼다.
- 조건부 렌더링
loading 상태가 true일 때는 "로딩중.." 메시지를, error 상태가 있으면 "에러가 발생했습니다" 메시지를, users가 null일 때는 아무것도 렌더링하지 않는다.
- 데이터 렌더링
users 배열에 있는 사용자 데이터를 map 함수를 통해 순회하면서 각 사용자의 username과 name을 <li> 요소로 출력하고 있다.

 

아까 구현했던 fetchUsers 함수를 바깥으로 꺼내주고, 버튼을 만들어서 해당 함수를 연결해주면 버튼을 눌러서 API를 재요청하는 기능을 구현 또한 가능하다.

 return (
    <>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            {user.username} ({user.name})
          </li>
        ))}
      </ul>
      <button onClick={fetchUsers}>다시 불러오기</button>
    </>
  );
}

라우팅(Routing)

: 웹 애플리케이션에서 라우팅이라는 개념은 사용자가 요청한 URL에 따라 알맞는 페이지를 보여주는 것을 의미한다.

-> 리액트에서 라우트 시스템을 구축하기위해 사용할 수 있는 선택지는 크게 두가지가 있다.

  • 리액트 라우터(React Router): 이 라이브러리는 리액트의 라우팅 관련 라이브러리들 중에서 가장 오래됐고, 가장 많이 사용되고 있다. 이 라이브러리는 컴포넌트 기반으로 라우팅 시스템을 설정할 수 있다.
  • Next.js: Next.js 는 리액트 프로젝트의 프레임워크이다. 이 프레임워크는 우리가 사용했던 Create React App처럼 리액트 프로젝트 설정을 하는 기능, 라우팅 시스템, 최적화, 다국어 시스템 지원, 서버 사이드 렌더링 등 다양한 기능들을 제공한다. 이 프레임워크의 라우팅 시스템은 파일 경로 기반으로 작동한다. 이 프레임워크는 리액트 라우터의 대안으로 많이 사용되고 있다.

싱글 페이지 어플리케이션

: html은 한번만 받아와서 웹 애플리케이션을 실행시킨 후에 그 이후에는 필요한 데이터만 받아와서 화면에 업데이트 해주는 것이다. 싱글 페이지 애플리케이션은 기술적으로는 한 페이지만 존재하는 것이지만, 사용자가 경험하기에는 여러 페이지가 존재하는 것 처럼 느낄 수 있는 것이다.

=> 리액트 라우터와 같은 라우팅 시스템은 사용자의 브라우저 주소창의 경로에 따라 알맞는 페이지를 보여주는데, 이후 링크를 눌러서 다른 페이지로 이동하게 될 때 서버에 다른 페이지의 html을 새로 요청하는 것이 아니라, 브라우저의 History API를 사용하여 브라우저의 주소창의 값만 변경하고 기존에 페이지에 띄웠던 웹 애플리케이션을 그대로 유지하면서 라우팅 설정에 따라 또 다른 페이지를 보여주게 된다.

리액트 라우터 사용하기

$ yarn create react-app router-tutorial

$ cd router-tutorial
$ yarn add react-router-dom

우선 리액트 라우터를 적용해 볼 리액트 프로젝트를 새로 생성하고 해당 프로젝트 디렉터리로 이동하여 리액트 라우터 라이브러리를 설치한다.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

프로젝트에 리액트 라우터를 적용할 때는 src/index.js 파일에서 react-router-dom에 내장되어 있는 BrowserRouter라는 컴포넌트를 사용하여 감싸면 된다.

이 컴포넌트는 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로 불러오지 않고도 주소를 변경하고 현재 주소의 경로에 관련된 정보를 리액트 컴포넌트에서 사용할 수 있도록 해준다.

 

페이지 컴퍼넌트

이제 리액트 라우터를 통해 여러 페이지로 구성된 웹 애플리케이션을 만들기 위하여 각 페이지에서 사용할 컴포넌트를 만들면 된다.

일단 사용자가 웹 사이트에 들어오게 됐을 때 가장 먼저 보여지게 될 Home 페이지 컴포넌트와 웹 사이트를 소개하는 About 페이지 컴포넌트를 만들면 된다.

const Home = () => {
  return (
    <div>
      <h1>아무거나 적으면 됩니다</h1>
      <p>가장 먼저 보여지는 페이지이고 about페이지도 똑같이 만들면 됩니다.</p>
    </div>
  );
};

export default Home;

Route 컴포넌트

: 사용자의 브라우저 주소 경로에 따라 우리가 원하는 컴포넌트를 보여주기 위해서 Route 라는 컴포넌트를 통해 라우트 설정을 해주어야 한다.

<Route path="주소규칙" element={보여 줄 컴포넌트 JSX} />
const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  );
};

이렇게 Route 컴포넌트는 Routes 컴포넌트 내부에서 사용되어야 한다.

Link 컴포넌트

: 원래 웹 페이지에서는 링크를 보여줄 때 a 태그를 사용하는, 리액트 라우터를 사용하는 프로젝트에서 a 태그를 바로 사용하면 안된다. 왜냐하면, a 태그를 클릭하여 페이지를 이동할 때 브라우저에서는 페이지를 새로 불러오게 되기 때문이다.

=> Link 컴포넌트 역시 a 태그를 사용하긴 하지만, 페이지를 새로 불러오는 것을 막고 History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있다.

<Link to="경로">링크 이름</Link>
const Home = () => {
  return (
    <div>
      <h1>홈</h1>
      <p>가장 먼저 보여지는 페이지입니다.</p>
      <Link to="/about">소개</Link>
    </div>
  );
};

이렇게 쓰면 된다.

URL 파라미터와 쿼리스트링

: URL 파라미터는 주소의 경로에 유동적인 값을 넣는 형태고, 쿼리 스트링은 주소의 뒷부분에 ? 문자열 이후에 key=value 로 값을 정의하며 & 로 구분을 하는 형태이다.

=> 주로 URL 파라미터는 ID 또는 이름을 사용하여 특정 데이터를 조회할 때 사용하고, 쿼리스트링(Querystring)은 키워드 검색, 페이지네이션, 정렬 방식 등 데이터 조회에 필요한 옵션을 전달할 때 사용한다.

URL 파라미터 예시: /profile/velopert
쿼리스트링 예시: /articles?**page=1&keyword=react

URL 파라미터 사용

import { Route, Routes } from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
    </Routes>
  );
};

URL파라미터는 /profiles/:username 과 같이 경로에 : 를 사용하여 설정한다.

만약 URL 파라미터가 여러개인 경우엔 /profiles/:username/:field 와 같은 형태로 설정할 수 있다.

쿼리스트링

import { useSearchParams } from 'react-router-dom';

const About = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  const detail = searchParams.get('detail');
  const mode = searchParams.get('mode');

  const onToggleDetail = () => {
    setSearchParams({ mode, detail: detail === 'true' ? false : true });
  };

  const onIncreaseMode = () => {
    const nextMode = mode === null ? 1 : parseInt(mode) + 1;
    setSearchParams({ mode: nextMode, detail });
  };

  return (
    <div>
      <h1>소개</h1>
      <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
      <p>detail: {detail}</p>
      <p>mode: {mode}</p>
      <button onClick={onToggleDetail}>Toggle detail</button>
      <button onClick={onIncreaseMode}>mode + 1</button>
    </div>
  );
};

export default About;

리엑트 라우터에서는 useSearchParams 라는 Hook을 통해서 쿼리스트링을다룰 수 있다.

useSearchParams 는 배열 타입의 값을 반환하며, 첫번째 원소는 쿼리파라미터를 조회하거나 수정하는 메서드들이 담긴 객체를 반환한다. get 메서드를 통해 특정 쿼리파라미터를 조회할 수 있고, set 메서드를 통해 특정 쿼리파라미터를 업데이트 할 수 있다. 만약 조회시에 쿼리파라미터가 존재하지 않는다면 null 로 조회된다. 두번째 원소는 쿼리파라미터를 객체형태로 업데이트할 수 있는 함수를 반환한다.

반응형