#1. Single Page Application

1. Single Page Application의 개념

1) Single Page Application이란?

  • 하나의 HTML 페이지로 다수의 페이지 효과를 내는 구현 방식을 말한다.
  • js 파일로 웹 페이지 화면을 변경하는 형태로 구현된다.
  • Single Page Application을 줄여서 SPA 라고 부르기도 한다.
  • Router를 활용해서 페이지를 구현한다.

※ Router

  • 분배하는 기능을 수행하는 소프트웨어나 하드웨어를 말한다. (대표적인 하드웨어로는 공유기가 있다)
  • 리액트에서 Router는 URL에 의해 컴포넌트를 분배하는 기능을 말한다.
  • HTML에서 자바스크립트에 추가된 기능 중 history 객체를 통해 URL을 변조하는 기능이 있다.
  • 리액트의 Router는 이 기능을 활용하여 현재 페이지의 URL을 다양하게 변조하여 각각의 컴포넌트를 분배한다.

 

2) 장점

  • 페이지 이동 없이 JS에 의해 화면이 갱신되므로 실제로 네트워크 통신이 발생하지 않아 실행 속도가 빠르다.
  • 웹 어플리케이션에 필요한 모든 정적 리소스를 최조에 한번만 다운로드 한다.
    • 이후 새로운 페이지 요청 시, 페이지 갱신에 필요한 데이터만 받기 때문에 전체적인 트래픽 감소

 

3) 단점

  • 서버가 해야할 일을 자바스크립트가 대신 하다보니 JS코드가 비대해 질 수 있다. (코드 스플리팅 기법으로 해결 가능, 코드 분할 작성)
  • 하나의 HTML이므로 SEO(Search Engin Optimization)에 취약하다. (서버사이드 렌더링으로 해결 가능)

※ 검색엔진 최적화(SEO)

  • 검색엔진이 이해하기 쉽도록 홈페이지의 구조와 페이지를 개발해 검색 결과를 상위에 노출될 수 있도록 하는 작업이다.
  • 기본적인 작업 방식은 특정 검색어를 웹페이지에 적절하게 배치하고 다른 웹페이지에서 링크가 많이 연결되도록 하는 것이다.

 

2. Router 사용하기

create-react-app을 진행했다는 가정하에 추가진행.

1) 추가 패키지 설치하기

  • 터미널에서 프로젝트를 진행할 React 폴더 주소로 이동한다.
  • 해당 주소에서 아래 명령어를 수행해서 react-router-dom 패키지를 설치한다.
yarn add react-router-dom

※ react-router-dom

  • SPA 앱을 만들 때 사용한다.
  • URL에 따라 실행한 자바스크립트를 분기해준다.
  • 세가지 비슷한 패키지가 존재하며, 각각 용도가 다르다. 
    • react-router : 웹 & 앱
    • react-router-dom : 웹
    • react-router-native : 앱

 

2) Router 적용하기

※ 구문추가

-1. index.js

  • 상단에 아래 import 구문을 추가한다.
import { BrowserRouter } from "react-router-dom";
  • .render 구문에 <BrowserRouter> 태그를 추가한다.
    • history API를 사용해 URL과 UI를 동기화 하는 라우터.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
  
    <BrowserRouter>     // BrowserRouter 태그 추가
      <App />
    </BrowserRouter>
    
  </React.StrictMode>
);

 

-2. App.js

  • 상단에 아래 import 구문을 추가한다.
import { Link, Routes, Route } from "react-router-dom";
  • Link : "a" 태그와 비슷하지만, a태그는 클릭시 페이지를 새로 불러오기 때문에 사용하지 않는다.
    • to 속성에 설정된 링크로 이동하고, 기록이 history 스택에 저장된다.
  • Routes : 컴포넌트는 여러 Route를 감싸서 그 중 규칙이 일치하는 라우트 하나만을 렌더링 시켜주는 역할을 한다.
  • Route : 컴포넌트의 속성에 설정된 URL과 현재 경로가 일치하면 해당하는 컴포넌트, 함수를 렌더링한다.
    • path 속성에 경로, element 속성에는 컴포넌트를 넣어준다. 여러 라우팅을 매칭하고 싶은 경우 URL 뒤에 " /* "을 사용한다.

 

3) Router를 활용해서 페이지 만들기

  • 리액트는 단 한개의 파일로 만들어지지 않는다.
    • 여러 파일을 참조하는 구조로 페이지를 구성한다.
    • index.js 파일과 App.js 파일은 공통적으로 사용되고, 나머지는 개발자 재량 (App.js에 참조한다)

 

- index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

import { BrowserRouter } from "react-router-dom";  // 추가

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>  // 추가
      <App />
    </BrowserRouter>
  </React.StrictMode>
);
  • 위에서 설명했듯이 BrowserRouter를 import하고, 태그를 추가한다.

 

- App.js

import React from "react";
import { Link, Routes, Route } from "react-router-dom";  // 추가

import Home from "./pages/Home"    // Home.js 참조
import About from "./pages/About"  // About.js 참조
import Main from "./pages/Main";   // Main.js 참조

function App() {
  return (
    <div>
      <h1>SPA Example</h1>
      <hr />

      {/* === 링크 구성 부분 === */}
      <nav>
        <Link to="/">[ Home ]</Link>
        <Link to="/about">[ About ]</Link>
        <Link to="/main">[ Main ]</Link>
      </nav>

      {/* === 페이지 역할을 할 컴포넌트를 명시하기 === */}
      <Routes>
      
        {/* 첫 페이지로 사용되는 컴포넌트의 경우 exact={true}를 명시해야 한다. */}
        {/* 첫 페이지로 사용되는 컴포넌트는 path에 "/"를 권장 */}
        <Route path="/" element={<Home />} exact={true}></Route>
        <Route path="/about" element={<About />}></Route>
        <Route path="/main" element={<Main />}></Route>

      </Routes>
    </div>
  );
}

export default App;
  • { Link, Routes, Route } 를 import 한다.
  • Link는 <Link to="경로">링크명</Link> 형식으로 사용한다.
  • Route는 <Route path="경로" element={컴포넌트} /> 형식으로 사용한다. 

 

- Home.js (예시)

import React from "react";

const Home = () => {
  return (
    <div>
      <h2>여기는 Home.js 파일 입니다.</h2>
    </div>
  );
};

export default Home;

 

- About.js (예시)

import React from "react";

const About = () => {
  return (
    <div>
      <h2>여기는 About.js 파일 입니다.</h2>
    </div>
  );
};

export default About;

 

- Main.js (예시)

import React from "react";

const Main = () => {
  return (
    <div>
      <h2>여기는 Main.js 파일 입니다.</h2>
    </div>
  );
};

export default Main;

 

※ 실행결과

페이지 이동 없이 링크를 클릭할 때 마다 바뀌는걸 볼 수 있다.

 

4) 서브라우팅 사용하기

- MainSub1.js (예시)

import React from "react";

const MainSub1 = () => {
  return (
    <div>
      <h3>여기는 Main의 서브 페이지인 MainSub1.js 입니다.</h3>
    </div>
  );
};

export default MainSub1;
  • 서브라우팅으로 사용할 js파일 작성.

 

- Main.js (예시)

import React from "react";

// Main에서 서브라우팅을 사용하기 위해 다시 호출
import { Link, Routes, Route } from "react-router-dom";

import MainSub1 from "./MainSub1";  // MainSub1을 참조

const Main = () => {
  return (
    <div>
      <h2>여기는 Main.js 파일 입니다.</h2>

      {/* === 링크 구성 부분 === */}
      <nav>
        <Link to="sub1">[서브페이지]</Link>
      </nav>

      {/* === 페이지 역할을 할 컴포넌트를 명시하기 === */}
      <Routes>
        <Route path="sub1" element={<MainSub1 />} />
      </Routes>
    </div>
  );
};

export default Main;
  • Main.js 파일에서 서브라우팅을 구성하기 때문에 App.js 파일과 같은 구조로 작성한다.

 

- App.js

{/* 서브라우팅 사용 */}
{/* 하위의 모든 값을 허용할 때는 "/*"를 뒤에 붙인다 " */}
<Route path="/main/*" element={<Main />}></Route>
  • App.js의 Route의 path 경로를 하위 모든 값을 허용하게 해준다.
  • /main 경로 뒤에 " /* " 사용

 

※ 실행결과

  • Main 링크를 누르면 서브페이지 링크가 생기고, 서브페이지 링크를 누르면 해당 내용이 출력된다.

 

5) 지정되지 않은 요청에 대한 반응

- Error404.js (예시)

import React from "react";

const Error404 = () => {
  return (
    <div>
      <h2>요청하신 페이지는 존재하지 않습니다.</h2>
    </div>
  );
};

export default Error404;
  • 지정되지 않은 주소를 요청시 에러 메세지를 띄운다.

 

- App.js

import Error404 from "./pages/Error404";

{/* path 속성 없이 Route 지정 -> 지정되지 않은 모든 요청에 반응. 
단, Routes블록의 맨 마지막에 배치해야 한다. */}
<Route path="/*" element={<Error404 />} />
  • 지정되지 않은 주소에 대한 반응은 <Routes> 태그 맨 마지막에 배치해야한다.
  • path 경로는 모든 주소를 허용하는 " /* " 형태로 지정한다.

 

※ 실행결과

 

6) useParams

  • useParams는 리액트에서 Router 사용 시 파라미터 정보를 가져와 활용할 수 있게 해준다.
  • 즉, 동적라우팅이 필요할 때 사용하면 좋은 방법이다.

 

- WeatherData.js (예시)

const WeatherData = {
  "mon": ["맑음", "맑음"],
  "tue": ["비", "맑음"],
  "wed": ["맑음", "흐림"],
  "thu": ["맑음", "흐림"],
  "fri": ["흐림", "흐림"],
  "sat": ["비", "맑음"],
  "sun": ["맑음", "맑음"],
};

export default WeatherData;
  • 먼저 날씨정보에 대한 내용을 JSON 형태로 작성한다.
    • 보통은 이미 만들어진 데이터들을 가져오는 형식으로 사용한다.

 

- index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

import { BrowserRouter } from "react-router-dom";  // 라우터를 사용할 때 필수

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>       {/* <App />을 <BrowserRouter/>로 감싼다 */}
      <App />
    </BrowserRouter>
  </React.StrictMode>
);
  • BrowserRouter 를 import 시켜준다.
  • <App /> 을 <BrowserRouter />로 감싼다.

 

- App.js

import React from "react";
import { Link, Routes, Route } from "react-router-dom";
import Weatehr from './MyWeather';  // MyWeather.js 참조

function App() {
  return (
    <div>
      <h1>주간날씨</h1>
      <hr />

      <nav>
        <Link to="/weather/mon">월</Link> |&nbsp;
        <Link to="/weather/tue">화</Link> |&nbsp;
        <Link to="/weather/wed">수</Link> |&nbsp;
        <Link to="/weather/thu">목</Link> |&nbsp;
        <Link to="/weather/fri">금</Link> |&nbsp;
        <Link to="/weather/sat">토</Link> |&nbsp;
        <Link to="/weather/sun">일</Link>
      </nav>

      <Routes>
        <Route path="/weather/:day" exact={true} element={<Weatehr />} />  // id값 지정
      </Routes>
    </div>  
  );
}

export default App;
  • MyWeather.js를 import 시켜준다.
  • <Route>의 path경로에 id값을 지정해준다.
    • <Route path="/weather/:day" exact={true} element={<Weatehr />} />
    • 여기서는 /:day 가 id값 역할을 한다. (이 자리에 입력한 <Link> 태그의 /weateher 뒤 주소값을 가져온다)

 

- MyWeather.js (예시)

import React from 'react';
import { useParams } from "react-router-dom";  // useParmas hook 지정
import WeatherData from './WeatherData';  // 날씨정보 참조

const MyWeather = () => {

  const params = useParams();  // 컴포넌트 내에 useParams() 선언
  
  const {day} = params;  // 비구조문법으로 파라미터값 호출

  const [am, pm] = WeatherData[day];  // 파라미터 값에 따라 날씨정보 배열을 비구조문법으로 호출

  return (
    <div>

      <h2>오전</h2>
      <p>{am}</p>  // 호출한 배열 변수 사용
      <h2>오후</h2>
      <p>{pm}</p>
      
    </div>
  );
};

export default MyWeather;
  • react-router-dom의 useParams를 import 시켜준다.
    • import { useParams } from "react-router-dom";
  • 컴포넌트 내에 useParams( )를 선언하고, id값(파라미터)을 호출한다. (클릭하는 <Link> 경로의 파라미터값을 받아온다)
  • 호출한 id값을 날씨정보 데이터 객체에 매치 시켜(key) 배열을 비구조문법으로 변수에 호출하고(value) JSX에서 변수값을 사용한다.

요일을 클릭하면 해당 날씨정보가 호출된다.

'국비수업 > React' 카테고리의 다른 글

[React] CSS 사용하기  (0) 2022.04.26
[React] Props (Properties)  (0) 2022.04.25
[React] JSX (JavaScript eXtension)  (0) 2022.04.23
[React] React의 기본 구조  (0) 2022.04.21
[React] React의 개념 / 개발환경 구성하기  (0) 2022.04.21

+ Recent posts