[LIKELION] React Router + REST API

Lellow_Mellow·2023년 6월 8일
2
post-thumbnail

해당 글은 인하대학교 멋쟁이사자처럼 11기 FE를 위한 교육 자료로 작성되었습니다.


여러분, 드디어 대망의 마지막 이론 세션입니다.

이번 세션에서 여러분은 react-router-domaxios에 대해 학습하게 됩니다. 여러 페이지들을 컴포넌트 단위로 개발하기 위한 라우팅 기능과 백엔드에서 개발한 API를 연동하는 것과 관련된 내용이니 꼭!! 복습하시기를 바랍니다.

이번 세션의 목표는 아래와 같습니다.


React Router + react-router-dom

Router? Routing? 이 단어들은 어떤 것을 의미할까요?

왜 이러한 기능이 필요할까요?


1. 라우팅이란?

라우팅웹에서 사용자가 요청한 URL에 따라 알맞은 페이지를 보여주는 것을 의미합니다. 우리가 일반적으로 아는 보통의 웹페이지들은 하나의 페이지로 끝나지 않습니다. 메인 페이지, 로그인 페이지, 회원가입 페이지, 마이 페이지, 설정 페이지 등등 다양한 페이지로 이루어져 있습니다.

이렇게 여러 페이지로 구성된 웹 애플리케이션을 만들 때, 페이지 단위로 컴포넌트들을 분리해가면서 프로젝트를 관리하기 위해 필요한 것routing system입니다. react에서 routing system을 구축하기 위한 방법은 크게 2가지가 있습니다.

[ React Router ]

  • react의 routing 관련 라이브러리들 중에서 가장 오래되었고, 가장 많이 사용되고 있습니다. component 기반으로 routing system을 설정할 수 있습니다.

[ Next.js ]

  • react 프로젝트의 framework로, 다양한 기능을 지원합니다. Next.js의 routing system은 파일 경로 기반으로 작동하며, React Router의 대안으로 사용되고 있습니다.

우리는 라우팅 기능만을 집중한 라이브러리이기도 하며, 편리하고 다양한 라우팅 기능을 제공하고 안정적인 React Router를 사용할 예정입니다. 이러한 React Router를 사용하면 손쉽게 single page application을 만들 수 있습니다.


2. Single Page Application?

[ single page application ]

한 개의 페이지로 이루어진 어플리케이션이라는 의미입니다. 위에서는 여러 페이지로 구성된 프로젝트라고 했는데 왜 single page application일까요?

multi page application은 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고, 페이지를 로딩할 때마다 서버에서 css, js, 이미지 파일 등의 리소스를 전달받아 브라우저 화면에서 보여주게 됩니다.

하지만 사용자 인터랙션이 많은 동적인 페이지들을 이러한 방식으로 구성한다면, 새로운 페이지를 보여줄 때마다 서버에서 매번 리소스를 받아와야하며, 이는 비효율적일 것입니다.

반대로 single page applicationhtml을 한 번만 받아와서 웹 어플리케이션을 실행시킨 후에, 이후에는 필요한 데이터만 받아와서 화면에 업데이트해주기 때문에 single page application이라 불립니다.

즉, 기술적으로는 하나의 페이지만 존재하지만, 사용자가 경험하기에는 여러 페이지가 존재하는 것처럼 느껴지는 것입니다.

[ SPA의 장단점 ]

  • 클라이언트가 모든 페이지를 가지고 있으므로 앱과 같은 자연스러운 사용자 경험을 제공합니다. 다만, 처음 접속시에 사이트 구성과 관련된 모든 리소스를 한 번에 받기 때문에 초기 구동 속도가 느릴 수 있습니다.

  • 모듈화와 컴포넌트별 개발이 용이해집니다. 또한 페이지에서 일부분만 교체 (header와 footer 등을 제외한 나머지 부분만 교체될 수 있음) 하므로 효율성이 증가합니다. 다만, 검색엔진 최적화 (SEO)가 어렵습니다.


3. React Router Dom

react router dom은 라이브러리이기 때문에 install이 필요합니다. 하단 코드를 터미널에 입력하여 라이브러리를 설치합니다.

npm i react-router-dom

라우터 기능은 아래와 같이 사용할 수 있습니다.

import { BrowserRouter, Routes, Route } from "react-router-dom";

const App = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<h1>Home Page</h1>} />
        <Route path="/menu" element={<h1>Home Page</h1>} />
        <Route path="/setting/:userId" element={<h1> Page</h1>} />
        <Route path="*" element={<h1>Not Found Page</h1>} />
      </Routes>
    </BrowserRouter>
  );
};

export default App;

react-router-dom에 내장된 BrowserRouter 컴포넌트 내부에 Route를 사용하여 라우팅을 할 수 있습니다. Route들은 Routes 컴포넌트로 감싸줘야 하며, Routepathelement 로 경로와 보여줄 컴포넌트를 지정할 수 있습니다.

path는 도메인 주소 뒤에 붙는 주소를 기준으로 작성하며, /는 루트 주소가 됩니다. 4번째 Routepath="*"는 아무 텍스트나 매칭한다는 의미를 가집니다. 이는 다시 말하자면 위의 Route와 일치하지 않는 경우를 처리하는 것으로, 정상적인 주소로 접근하지 않는 경우에 올바르지 않은 주소와 관련된 페이지로 연결해주는 역할을 담당합니다.

페이지에서 페이지로 이동하는 방법에는 크게 2가지가 존재합니다. LinkuseNavigate로, 이에 대한 자세한 사용법과 차이에 대해 알아보겠습니다.


react-router-dom의 내장 컴포넌트로, 아래와 같이 사용합니다.

return (
    <>
      <h1>Home Page</h1>
      <Link to="/menu">메뉴 페이지로 이동</Link>
    </>
  );

Route와 동일하게 to에 이동하고자 하는 주소를 작성합니다. Link 태그 내부에는 버튼과 같은 클릭할 태그 혹은 텍스트를 작성합니다.

Link는 상품 리스트에서 상세 페이지로 이동하는 등, 클릭 시 바로 이동하는 로직 구현 시에 사용되며 개발자 도구에서는 <a> 태그로 표시됩니다.

[ useNavigate ]

react-router-dom에 내장되어 있으며, 주소를 변경할 수 있는 함수를 return 합니다. 이를 이용하여 아래와 같이 다른 페이지로 이동할 수 있도록 코드를 작성할 수 있습니다.

const navigate = useNavigate();
  return (
    <>
      <h1>Menu Page</h1>
      <button onClick={() => navigate("/")}>홈으로 이동하기</button>
    </>
  );

return 되는 함수를 navigate에 저장한 이후, button과 같이 특정 이벤트가 발생했을 경우에 navigate를 사용하여 다른 페이지로 이동하도록 할 수 있습니다. navigate의 인자로는 Link, Route와 동일하게 이동하고자 하는 주소를 작성해줍니다.

useNavigate는 로그인 버튼 클릭 시에 회원가입 여부에 따라 다른 페이지로 이동하는 것과 같이, 페이지 전환 시에 추가로 처리해야 하는 로직이 있는 경우에 사용됩니다.

이에 대한 내용을 정리하면 아래와 같습니다.


5. URL 파라미터

URL 파라미터ID 또는 이름을 사용해 특정 데이터를 조회할 때, 이를 위해 유동적인 주소를 사용하는 경우에 사용합니다. Route의 주소를 정의할 때, 아래와 같이 정의하여 이를 사용할 수 있습니다.

<Route path="/setting/:userId" element={<Setting />} />

앞에서 봐온 주소와는 무언가 다르게 작성된 부분이 보이시죠? :userId 처럼 앞에 :을 작성하여 URL 파라미터를 사용할 수 있습니다. URL 파라미터/setting/:userId/:id 처럼 여러 개를 사용할 수 있습니다.

실제로 localhost:3000/setting/123 이라는 주소에 접근한다면, :userId 위치에 존재하는 123 이라는 값이 userId : 123의 형태로 객체에 저장되어 전달됩니다. 이러한 값은 react-router-dom에 내장된 useParams를 사용하여 가져올 수 있습니다. 아래와 같이 작성합니다.

const { userId } = useParams();
return <h1>Setting Page for {userId}</h1>;

useParams를 사용하여 URL 파라미터 객체를 가져올 수 있습니다. 이를 구조 분해 할당을 이용하여 userId라는 변수에 담아 사용합니다. params 라는 하나의 변수에 담아 (변수 이름은 자유) params.userId 처럼 객체의 값을 사용하듯이 접근하여 사용해도 무방합니다.

잘 이해가 가지 않는다면, 이 블로그를 참고해보세요.


REST API

API 라는 단어, 세션 초반부터 많이 들어보셨죠? 드디어 API와 친해져볼 시간이 왔습니다! 이번에는 API가 무엇이고, REST API가 무엇인지, axios는 어떻게 사용하는지에 대해 알아보겠습니다.


1. API란?

[ Appliation Programming Interface - API ]

소프트웨어간의 응답과 요청을 통한 데이터 통신을 위한 방법과 규칙입니다.정보들이 주고받아지는데 있어 개발자들 사이에서 널리 쓰이는 하나의 방식이라고도 할 수 있습니다.

우리가 어떤 기계를 만들면 사용자가 그 기능들을 사용할 수 있도록 제어 장치를 만들 필요가 있습니다. TV의 리모컨, 노트북의 키보드와 트랙패드와 같이 말이죠. 이러한 것들을 interface라고 부릅니다. 우리의 입력에 따른 결과를 보여주기 위하 TV와 노트북의 스크린 또한 interface라고 할 수 있습니다. 웹페이지에서는 버튼, 스크롤바, 브라우저 창 등을 UI(user interface)라고 부릅니다.

그럼 API는 어떤 인터페이스를 의미하는 것일까요? 예시를 하나 생각해보겠습니다.

스마트폰에도, PC에도 있는 날씨와 관련된 다양한 서비스들, 다들 사용해보셨죠? 이런 서비스들은 날씨와 관련된 정보를 어디서 받아올까요? 흔하게 생각해볼 수 있는 곳이라면 바로 기상청일 것입니다. 그런데, 기상청에게 이러한 정보를 요청하는 하나의 형식이 필요하지 않을까요?

언제, 어느 지역인지 등등 날씨 정보 요청과 관련된 정보들을 전달할 수 있는 하나의 메뉴얼이 있으면, 누구든지 이러한 메뉴얼을 바탕으로 정보들을 쉽게 가져올 수 있을 것입니다. 이렇듯이 어떤 소프트웨어가 다른 소프트웨어로부터 지정된 형식으로 요청과 명령을 받을 수 있는 수단을 API 라고 할 수 있습니다.

이제 API가 무엇인지 감이 오시나요? 그렇다면 REST API는 무엇일까요? 아래에서 알아봅시다.


2. REST API

[ Representational State Transfer - REST ]

우선 REST가 무엇인지부터 알아봅시다. RESTHTTP URI를 통해 자원을 명시하고, HTTP Method를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미합니다. 무슨 의미인지 도통 이해가 안갑니다. 하나씩 간단하게 살펴보겠습니다.

[ Unifron Resource Identifier ]

URI는 자원을 구분하고 접근하기 위해 사용하는 유일한 식별자입니다. 예시를 함께 살펴봅시다. 만약 멋쟁이사자처럼 인하대학교 11기의 인원을 조회하려고 합니다. 그 중에서도 프론트엔드 인원들만 알고 싶다면 다음과 같이 접속할 것입니다.

https://(도메인)/front-end

그렇다면, 백엔드 인원 중에서 2번째 인원의 정보만 알고 싶다면 어떤 주소로 접근할까요?

https://(도메인)/back-end/2

이처럼 자원들이 어떠한 구조로 저장되었는지를 쉽게 판단할 수 있는 것이 URI입니다. 근데 우리는 자원을 조회만 하지는 않겠죠? 수정하기도 하고, 추가하거나 삭제하기도 해야합니다. 이럴 때 필요한 것이 바로 CRUD Operation입니다.

[ CRUD ]

CRUD는 각각 Create, Read, Update, Delete 4가지를 의미합니다. 이러한 4가지 기능들로 특정 주소를 통해 새롭게 생성하고, 정보를 읽어오거나 업데이트하고, 삭제하는 명령을 하게 됩니다. 이러한 명령에는 HTTP Method가 사용됩니다.

[ HTTP Method ]

HTTP Method는 클라이언트와 서버 사이에 이루어지는 요청과 응답에 대한 데이터를 전송하는 방식입니다. 다시 말해 API로 요청을 보낼 때, HTTP라는 규약에 따라 신호를 전송하게 되는데, 이때 사용되는 메서드입니다.

이러한 HTTP Method는 여러 개가 존재하지만, REST API에서는 4개에서 5개를 위주로 사용합니다. 이는 아래와 같습니다.

즉 정리하자면, REST API웹페이지나 앱 서비스에서 널리 사용되며, 소프트웨어간 HTTP로 정보를 주고받는 부분이 있다면 활용이 가능합니다.

각 요청이 어떤 동작이나 정보를 위한 것인지를 그 요청의 모습 자체로 쉽게 추론이 가능하며, 이러한 규칙들을 만족하는 API를 우리는 RESTful한 API 라고 부릅니다.

잘 이해가 가지 않는다면 이 영상이 블로그를 참고해보세요.


3. Axios

앞서 학습한 REST API를 활용하기 위해 우리는 Axios라는 라이브러리를 사용합니다.

Axios는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리로, 쉽게 이해하자면 벡엔드와 프론트엔드 사이에서 통신을 쉽게 하기 위한 라이브러리입니다.

우선 아래와 같은 명령어로 라이브러리를 설치합니다.

npm i axios

axios의 다양한 메서드 중에서 getpost를 사용하는 방법에 대해 간단하게 알아보겠습니다. 아래는 단순히 예시이며, 주어진 REST API의 문서에 따라 어떠한 메서드로 어떠한 값을 담아 요청하고, return 받는 값의 형태가 어떠한지를 확인하시어 코드를 작성하시면 됩니다.

[ axios.get ]

일반적으로 get은 정보를 읽어올 때 사용합니다. 아래 예시를 살펴보겠습니다.

useEffect(() => {
    axios
      .get(`https://reqres.in/api/users/${1}`)
      .then((res) => {
        setUserInfo(res.data.data);
      })
      .catch((e) => {
        console.log(e);
      });
  }, []);

일반적으로 정보를 가져오는 시점은 특정 페이지를 접근한 시점이므로, 해당 페이지 컴포넌트가 render 되는 시점에 1번만 실행되도록 useEffect를 사용하였습니다.

axios는 사용하고자 하는 메서드의 인자로 해당 API의 주소를 작성하여 사용하며, 아래의 thenAPI 요청을 성공한 경우에 실행될 코드를, catchAPI 요청에 실패한 경우에 실행될 코드를 각각 작성합니다.

[ axios.post ]

post는 새로운 정보를 생성할 때 사용합니다. 정보를 API에게 전달해야하기 때문에 아래와 같이 정보를 담아 전달하게 됩니다.

axios.post(`https://reqres.in/api/users`, {
    avatar: "",
    email: "",
    first_name: "",
    last_name: "",
}).then((res) => {
    console.log(res);
});

즉, post의 첫 번째 인자는 주소를, 두 번째 인자는 전달하고자 하는 정보를 담아 요청합니다. 이때, 담는 정보의 형식은 API 문서를 참고해 작성하며, 일반적으로 객체의 형태로 전달합니다. 위 코드를 더 간단하게 작성할 수 있는 방법도 있습니다.

[ 단축 프로퍼티 ]

단축 프로퍼티는 객체 프로퍼티 값을 기존 변수에서 받아와 사용하는 방법입니다. 아래 코드를 살펴보겠습니다.

let a = 1, b = 2
console.log({a, b});
// { a : 1, b : 2 }

위와 같이 변수를 바로 객체에 넣어 변수 이름을 key로, 변수의 값을 value로 하여 코드를 작성할 수 있습니다. post와 관련된 코드에서 이미 각각 avatar, email, first_name, last_name이라는 변수가 존재할 경우, 아래와 같이 작성이 가능합니다.

axios.post(`https://reqres.in/api/users`, {
    avatar,
    email,
    first_name,
    last_name,
}).then((res) => {
    console.log(res);
});

4. HTTP Status Code

API 요청을 하여 그 결과를 console에 출력하면 Status Code에 따라 다른 결과가 나오는 것을 확인할 수 있습니다. 각각의 Status Code는 의미를 가지고 있으며, 이를 간단히 정리하자면 위와 같습니다.


profile
festina lenta

0개의 댓글