본문 바로가기

react

[코드잇] 리액트로 웹 사이트 만들기

- 리액트에서는 웹사이트도 컴포넌트로 만들 수 있음

- 리액트 라우터(React Router) 사용

 

1. 리액트 라우터 v6 소개 

 

리액트 라우터 

- 리액트 컴포넌트로 페이지를 나누고 이동하게 해주는 라이브러리 

- 페이지 나누기 

- 페이지 이동

- 핵심 컴포넌트 

 -> 라우터(Router), 라우츠(Routes), 라우트(Route), 링크 (link)

 

라우터 (Rounter)

- 리액트 라우터에서 사용하는 데이터들을 모두 갖고 있음

- 현재 주소, 페이지 기록같은 데이터를 가지고 있음

- Router 컴포넌트도 내부적으로는 context provider임 

 

라우츠(Routes), 라우트(Route)

- Routes 컴포넌트 안에서 Route 컴포넌트로 페이지의 경로랑 보여줄 컴포넌트를 지정

 

링크(link)

- 리액트 라우터에서 a 태그 대신에 사용하는 것

 

2. 리액트 라우터 설치하기 

 

1) 패키지 

 

- Node.js를 설치하면 npm(노드 패키지 매니저)라는 프로그램도 함께 설치

- npm은 패키지를 설치하거나 삭제하는 것처럼 패키지를 관리하는 프로그램

 

2) 패키지 설치하기 

 

- 패키지를 설치하려면 package.json이 있는 폴더에서 터미널을 열고 npm install <패키지 이름>이라는 명령어를 실행 

- npm install react-router-dom@6

 

3) 라우터 컴포넌트 감싸기 

 

- 프로젝트의 최상위 컴포넌트인 Main.js 파일에 가서 라우터 컴포넌트 적용 

- BrowserRouter라는 컴포넌트를 불러와서 컴포넌트 전체를 감싸줌

import { BrowserRouter } from 'react-router-dom';
import App from './components/App';
import HomePage from './pages/HomePage';

function Main() {
  return (
    <BrowserRouter>
      <App>
        <HomePage />
      </App>
    </BrowserRouter>
  );
}

export default Main;

 

3. Routes로 페이지 나누기 

 

- Routes 컴포넌트는 여러 개의 Route를 포함

- Routes를 렌더링할 때 리액트 라우터는 Routes 안에 잇는 Route를 차례대로 검사하면서 현재경로가 path와 일치하는지 하나씩 검사 

- 일치하는 경로를 찾으면 element프롭으로 지정한 컴포넌트를 렌더링 해줌

-  Route 컴포넌트의 path 프롭으로 경로를 지정하고 element 프롭으로 보여줄 컴포넌트를 지정

- element 프롭은 컴포넌트 함수가 아니라 jsx를 넘겨줌 

 

Main.js

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './components/App';
import HomePage from './pages/HomePage';
import CoursePage from './pages/CoursePage';
import CourseListPage from './pages/CourseListPage';
import WishlistPage from './pages/WishlistPage';

function Main() {
  return (
    <BrowserRouter>
      <App>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="courses" element={<CourseListPage />} />
          <Route
            path="courses/react-frontend-development"
            element={<CoursePage />}
          />
          <Route path="wishlist" element={<WishlistPage />} />
        </Routes>
      </App>
    </BrowserRouter>
  );
}

export default Main;

 

4. Link로 이동하기 

 

- Link 컴포넌트에서는 to라는 프롭을 사용하여 이동할 경로를 지정

- '/'를 맨 앞에다가 붙이는 건 절대 경로라는 의미 

 

Nav.js

import Container from './Container';
import UserMenu from './UserMenu';
import logoImg from '../assets/logo.svg';
import styles from './Nav.module.css';

function Nav() {
  return (
    <div className={styles.nav}>
      <Container className={styles.container}>
        <Link to="/">
          <img src={logoImg} alt="Codethat Logo" />
        </Link>
        <ul className={styles.menu}>
          <li><Link to="/courses">카탈로그</Link></li>
          <li><Link to="/questions">커뮤니티</Link></li>
          <li>
            <UserMenu />
          </li>
        </ul>
      </Container>
    </div>
  );
}

export default Nav;

 

5. NavLink로 네비게이션 구현하기 

 

- 내브링크(NavLink)라는 컴포넌트를 사용해서 선택된 메뉴 강조 밑줄 기능 구현

- NavLink는 스타일(style)이라는 프롭으로 함수 지정 가능

- 현재 페이지의 경로가 내비게이션의 링크에 해당하면 isActive값이 참이 됨

 

Nav.js

import { Link, NavLink } from 'react-router-dom';
import Container from './Container';
import UserMenu from './UserMenu';
import logoImg from '../assets/logo.svg';
import styles from './Nav.module.css';

function getLinkStyle({ isActive }) {
  return {
    textDecoration: isActive ? 'underline' : '',
  };
}

function Nav() {
  return (
    <div className={styles.nav}>
      <Container className={styles.container}>
        <Link to="/">
          <img src={logoImg} alt="Codethat Logo" />
        </Link>
        <ul className={styles.menu}>
          <li>
            <NavLink style={getLinkStyle} to="/courses">
              카탈로그
            </NavLink>
          </li>
          <li>
            <NavLink style={getLinkStyle} to="/questions">
              커뮤니티
            </NavLink>
          </li>
          <li>
            <UserMenu />
          </li>
        </ul>
      </Container>
    </div>
  );
}

export default Nav;

 

6. 하위 페이지 나누기 

 

- 코스 목록 페이지랑 코스 페이지를 하위 Route로 만들기 

- 리액트 라우터는 Route를 중첩해서 사용할 수 있게 해줌

- 하위 경로에서 index에 해당하는 Route에서는 path 대신에 index라는 프롭을 사용 

- App 컴포넌트는 공통 레이아웃을 렌더링하는 컴포넌트 

- 하위 Route 여러 개에서 공통된 디자인을 보여주고 싶을 때는 element 프롭을 지정하고 지정된 컴포넌트에서는 Outlet 컴포넌트를 사용하면 됨 

  -> Routes 컴포넌트 안에선느 반드시 Route만 사용해야 하기 때문

 

Main.js

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './components/App';
import HomePage from './pages/HomePage';
import CoursePage from './pages/CoursePage';
import CourseListPage from './pages/CourseListPage';
import QuestionPage from './pages/QuestionPage';
import QuestionListPage from './pages/QuestionListPage';
import WishlistPage from './pages/WishlistPage';

function Main() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />}>
          <Route index element={<HomePage />} />
          <Route path="courses">
            <Route index element={<CourseListPage />} />
            <Route path="react-frontend-development" element={<CoursePage />} />
          </Route>
          <Route path="questions" element={<QuestionListPage />} />
          <Route path="questions/616825" element={<QuestionPage />} />
          <Route path="wishlist" element={<WishlistPage />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default Main;

App.js

import { Outlet } from 'react-router-dom';
import Nav from '../components/Nav';
import Footer from '../components/Footer';
import styles from './App.module.css';
import './App.font.css';

function App() {
  return (
    <>
      <Nav className={styles.nav} />
      <div className={styles.body}><Outlet /></div>
      <Footer className={styles.footer} />
    </>
  );
}

export default App;

 

7. useParams로 동적인 경로 만들기 

 

- 코스 상세 페이지를 동적인 경로로 바꾸기 

- 동적인 경로를 지정하려면 경로에 ':'으로 시작하는 단어를 사용하면 됨

- courseSlug라는 변수로 페이지의 경로 받아오기

- 경로에서 사용하는 동적인 값을 파라미터라고 부름

- 이러한 파라미터를 모아 놓은 것을 params라고 부름

- useParams라는 리액트 라우터에서 제공하는 커스텀 훅을 사용 

- useParams가 리턴하는 객체에는 현재 경로의 파라미터들이 저장되어 있음

  -> 이 객체에 우리가 정의한 courseSlug라는 값도 저장되어 있음

 

Main.js

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './components/App';
import HomePage from './pages/HomePage';
import CoursePage from './pages/CoursePage';
import CourseListPage from './pages/CourseListPage';
import QuestionPage from './pages/QuestionPage';
import QuestionListPage from './pages/QuestionListPage';
import WishlistPage from './pages/WishlistPage';

function Main() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />}>
          <Route index element={<HomePage />} />
          <Route path="courses">
            <Route index element={<CourseListPage />} />
            <Route path=":courseSlug" element={<CoursePage />} />
          </Route>
          <Route path="questions">
            <Route index element={<QuestionListPage />} />
            <Route path="616825" element={<QuestionPage />} />
          </Route>
          <Route path="wishlist" element={<WishlistPage />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default Main;

 

CoursePage.js

import Button from '../components/Button';
import { useParams } from 'react-router-dom';
import { addWishlist, getCourseBySlug } from '../api';
import Container from '../components/Container';
import Card from '../components/Card';
import CourseIcon from '../components/CourseIcon';
import getCourseColor from '../utils/getCourseColor';
import styles from './CoursePage.module.css';

function CoursePage() {
  const { courseSlug } = useParams();
  const course = getCourseBySlug(courseSlug);
  const courseColor = getCourseColor(course?.code);

  const headerStyle = {
    borderTopColor: courseColor,
  };

  const handleAddWishlistClick = () => {
    addWishlist(course?.slug);
  };

  return (
    <>
      <div className={styles.header} style={headerStyle}>
        <Container className={styles.content}>
          <CourseIcon photoUrl={course.photoUrl} />
          <h1 className={styles.title}>{course.title}</h1>
          <Button variant="round" onClick={handleAddWishlistClick}>
            + 코스 담기
          </Button>
          <p className={styles.summary}>{course.summary}</p>
        </Container>
      </div>
      <Container className={styles.topics}>
        {course.topics.map(({ topic }) => (
          <Card className={styles.topic} key={topic.slug}>
            <h3 className={styles.title}>{topic.title}</h3>
            <p className={styles.summary}>{topic.summary}</p>
          </Card>
        ))}
      </Container>
    </>
  );
}

export default CoursePage;

 

8. 없는 페이지 처리하기 

 

- 웹 서핑을 하다보면 페이지가 없어졌거나 주소를 잘못 쳐서 없는 주소로 들어가는 경우 

- 경로를 찾을 수 없을 때 보여줄 페이지 지정

- Routes 안에서 차례대로 Route를 검사하다가 일치하는 path가 없으니까 빈화면 보여주게됨

 -> 모든 경로를 포함하는 Route를 추가 

- 잘못된 경로로 접속하면 일치하는 Route가 없을 테니까 차례대로 검사하다가 맨 마지막에 있는 Route에서 NotFoundPage를 보여줌 

 

Main.js

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './components/App';
import HomePage from './pages/HomePage';
import CoursePage from './pages/CoursePage';
import CourseListPage from './pages/CourseListPage';
import QuestionPage from './pages/QuestionPage';
import QuestionListPage from './pages/QuestionListPage';
import WishlistPage from './pages/WishlistPage';
import NotFoundPage from './pages/NotFoundPage';

function Main() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />}>
          <Route index element={<HomePage />} />
          <Route path="courses">
            <Route index element={<CourseListPage />} />
            <Route path=":courseSlug" element={<CoursePage />} />
          </Route>
          <Route path="questions">
            <Route index element={<QuestionListPage />} />
            <Route path=":questionId" element={<QuestionPage />} />
          </Route>
          <Route path="wishlist" element={<WishlistPage />} />
          <Route path="*" element={<NotFoundPage />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default Main;

 

NotFoundPage.js

import { Link } from 'react-router-dom';
import Button from '../components/Button';
import Container from '../components/Container';
import Warn from '../components/Warn';
import styles from './NotFoundPage.module.css';

function NotFoundPage() {
  return (
    <Container className={styles.container}>
      <Warn
        variant="big"
        title="존재하지 않는 페이지에요."
        description="올바른 주소가 맞는지 다시 한 번 확인해 주세요."
      />
      <div className={styles.link}>
        <Link to="/">
          <Button as="div">홈으로 가기</Button>
        </Link>
      </div>
    </Container>
  );
}

export default NotFoundPage;

 

9. Navigate로 리다이렉트 하기 

 

리다이렉트 (Redirect)

-  페이지에 접속했을 떄 어떤 이유 때문에 다른 페이지로 이동

- 코스 목록 페이지로 리다이렉트 

- CoursePage를 렌더링할 때 course의 값이 없으면 Navigate라는 컴포넌트르 리턴 

 -> 렌더링하면 to 프롭에 지정된 경로로 이동시켜 줌 

 

CoursePage.js

...
function CoursePage() {
  const { courseSlug } = useParams();
  const course = getCourseBySlug(courseSlug);
  const courseColor = getCourseColor(course?.code);

  if (!course) {
    return <Navigate to="/courses" />;
  }
...

 

10. useSearchParams로 쿼리 사용하기

 

- 쿼리 스트링을 받아서 검색어 기능 만들기 

- 검색어를 입력하고 엔터를 입력하거나 검색 버튼을 누르면 페이지 주소 뒤에 "?keyword=검색어"를 붙여서 이동하고 

 페이지에서는 검색된 결과를 보여줌 

 

쿼리 스트링(Query String)

 - 주소에서 추가적인 조건을 넣을 때 사용 

 

- form 태그의 기본동작은 엔터나 submit 버튼을 누르면 쿼리와 함께 페이지를 이동

- input 태그에는 name값을 "keyword"라고 지정 

- handleKeywordChange라는 함수가 있어서 값을 입력할 때마다 keyword  State값이 함께 변경됨

 <form className={searchBarStyles.form} onSubmit={handleSubmit}>
        <input
          name="keyword"
          value={keyword}
          onChange={handleKeywordChange}
          placeholder="검색으로 코스 찾기"
        ></input>
        <button type="submit">
          <img src={searchIcon} alt="검색" />
        </button>
      </form>

- 리액트 라우터에서는 쿼리 파라미터값을 가져오고 싶을 때 useSearchParms라는 훅을 사용

- useSearchParms는 serachParams와 setter 함수를 배열형으로 리턴 

- searchParams에서는 get()이라는 함수로 값을 가져올 수 있음 

- setter 함수인 setSearchParams()에 값을 지정하려면, 객체를 넘겨주면 됨

- keyword state 값은 인풋에 value로 내려주기 때문에 initKeyword 값이 없는 경우에는 빈문자열로 지정

 

- handleSubmit() 함수 구현 

 -> 폼 태그의 기본 동작을 막은 다음에, setSearchParams()라는 setter함수를 이용해서 쿼리 값을 변경 

 

CourseListPage.js

import { useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import ListPage from '../components/ListPage';
import Warn from '../components/Warn';
import CourseItem from '../components/CourseItem';
import { getCourses } from '../api';
import styles from './CourseListPage.module.css';
import searchBarStyles from '../components/SearchBar.module.css';
import searchIcon from '../assets/search.svg';

function CourseListPage() {
  const [searchParam, setSearchParam] = useSearchParams();
  const initKeyword = searchParam.get('keyword');
  const [keyword, setKeyword] = useState(initKeyword || '');
  const courses = getCourses(initKeyword);

  const handleKeywordChange = (e) => setKeyword(e.target.value);

  const handleSubmit = (e) => {
    e.preventDefault();
    setSearchParam(keyword ? { keyword } : {});
  };

  return (
    <ListPage
      variant="catalog"
      title="모든 코스"
      description="자체 제작된 코스들로 기초를 쌓으세요."
    >
      <form className={searchBarStyles.form} onSubmit={handleSubmit}>
        <input
          name="keyword"
          value={keyword}
          onChange={handleKeywordChange}
          placeholder="검색으로 코스 찾기"
        ></input>
        <button type="submit">
          <img src={searchIcon} alt="검색" />
        </button>
      </form>

      <p className={styles.count}>총 {courses.length}개 코스</p>

      {initKeyword && courses.length === 0 ? (
        <Warn
          className={styles.emptyList}
          title="조건에 맞는 코스가 없어요."
          description="올바른 검색어가 맞는지 다시 한 번 확인해 주세요."
        />
      ) : (
        <div className={styles.courseList}>
          {courses.map((course) => (
            <CourseItem key={course.id} course={course} />
          ))}
        </div>
      )}
    </ListPage>
  );
}

 

11. useNavigate로 페이지 이동하기 

 

- 코드를 통해 페이지를 이동 

- 코스 담기 버튼을 눌렀을 때 실행할 함수 

 -> useNavigate라는 커스텀 훅을 사용 

 

CoursePage.js

const handleAddWishlistClick = () => {
    addWishlist(course?.slug);
    navigate('/wishlist');
  };

 

12. 리액트 라우터 정리 

 

1) 리액트 라우터란?

 - 리액트에서 경로에 따라 페이지를 나누도록 해주는 라이브러리 

 - 컴포넌트를 사용해서 페이지를 나눔

 

2) 라우터 

 - 리액트 라우터를 사용하려면 반드시 라우터라는 컴포넌트가 필요 

 - BrowserRouter를 사용 

  ->이 컴포넌트를 최상위 컴포넌트에서 감싸주면 모든것에서 사용할 수 있음 

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

function App() {
  return <BrowserRouter> ... </BrowserRouter>;
}

 

3) 페이지를 나누는 방법 

 

- Routes 컴포넌트 안에다가 Route 컴포넌트를 배치해서 각 페이지를 나눠줄 수 있음 

- 이때 Routes 안에서는 위에서부터 차례대로 Route를 검사 

- 현재 경로와 path prop이 일치하는 Route를 찾음 

<Routes>
    <Route path="/" element={<HomePage />} />
    <Route path="posts" element={<PostListPage /> />
    <Route path="posts/1" element={<PostPage/>} />
</Routes>

 

4) 링크 

 

- 리액트 라우터에서는 <a> 태그 대신에 Link 컴포넌트를 사용 

- to 라는 prop으로 이동할 경로를 정해주면 됨 

<Link to="/posts">블로그</Link>

 

5) 하위 페이지 나누기 

 

- Route 컴포넌트에다가 Route 컴포넌트를 배치하면 됨 

- 이때 하위 페이지에서 최상위 경로에 해당하는 경로는 path prop이 아니라 index라는 prop을 사용하면 됨 

<Routes>
  <Route path="/"><HomePage /></Route>
  <Route path="posts" element={<PostLayout />} >
    <Route index element={<PostListPage />}  />
    <Route path="1" element={<PostPage />}  />
  </Route>
</Routes>

- 부모 Route 컴포넌트에 element를 지정하고, Outlet 이라는 컴포넌트를 활용하면 공통된 레이아웃을 지정해 줄 수 있음

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

function PostLayout() {
  return (
    <div>
      <h1>블로그</h1>
      <hr />
      <Outlet />
    </div>
  );
}

export default PostLayout;

 

6) 동적인 경로 다루기 

 

- 콜론(:)으로 시작하는 문자열을 사용하면 경로에 파라미터를 지정할 수 있음 

 

ex) 

/posts/:postId라는 경로는 /posts/123 이라던지 /posts/abc라는 주소로 접속하면 123이나 abc 라는 값을 postId라는 파라미터로 받음 

<Routes>
  <Route path="/"><HomePage /></Route>
  <Route path="posts" element={<PostLayout />} >
    <Route index element={<PostListPage />}  />
    <Route path=":postId" element={<PostPage />}  />
  </Route>
</Routes>

 

- 경로 파라미터를 사용하려면 useParams 라는 훅을 사용하면 됨 

function PostPage() {
  const { postId } = useParams();
  // ...
}

 

7) 쿼리 사용하기 

 

- useSearchParams라는 Custom hook으로 SearchParams 객체를 받아올 수 있음

 -> SearchParms 객체와 Setter 함수를 배열형으로 리턴 

 -> 이때 쿼리 값은 SearchParams의 get 함수로 가져옴 

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

function PostListPage() {
  const [searchParams, setSearchParams] = useSearchParams();
  const filterQuery = searchParams.get('filter');

  // ...
}

- 쿼리 값을 변경하고 주소를 이동하고 싶다면 Setter 함수에 객체를 넘겨주면 됨 

- 이때 객체의 프로퍼티로 쿼리 값을 지정할 수 있음 

 ex) ?filter=react라는 쿼리로 이동

setSearchParams({
  filter: 'react',
});

 

8) 페이지 이동하기 

 

Navigate 컴포넌트 

 - 리턴 값으로 Navigate 컴포넌트를 리턴하면 to prop으로 지정한 경로로 이동 

function PostPage() {
  // ...

  const post = getPost(postId);

  // post가 없는 경우 /posts 페이지로 이동
  if (!post) {
    return <Navigate to="/posts" />;
  }

  // ...
}

 

useNavigate Hook

- useNavigate 라는 hook으로 navigate 함수를 가져오면 이 함수를 통해 페이지를 이동할 수 있음

const navigate = useNavigate();

const handleClick = () => {
  // ... 어떤 작업을 한 다음에 페이지를 이동
  navigate('/wishlist');
}

 

9) Link, Navigate, useNavigate를 사용하는 예시 상황 

 

Link 

- 사용자가 클릭해서 페이지를 이동하도록 할 때 사용 

- 하이퍼링크 텍스트나 페이지를 이동하는 버튼, 이미지 등에 사용 

 

Navigate

- 특정 경로에서 렌더링 시점에 다른 페이지로 이동시키고 싶을 때 사용 

ex) 

  - 쇼핑몰의 회원 전용 페이지에 로그인 없이 들어와서 로그인 페이지로 리다이렉트 하는 경우 

  - 쇼핑몰의 상품 상세 페이지에서 제품이 품절되었거나 삭제되어서 다른 페이지로 이동시키는 경우 

 

useNavigate

 - 특정한 코드의 실행이 끝나고 나서 페이지를 이동시키고 싶을 때 사용 

 ex)

   - 쇼핑몰에서 장바구니에 담기를 눌렀을 때 리퀘스트를 보내고 장바구니 페이지로 이동시키는 경우 

   - 쇼핑몰에서 결제하기 버튼을 누르고 나서 모든 결제가 완료된 후에 페이지를 이동시키는 경우 

   - 리다이렉트된 로그인 페이지에서 로그인을 완료한 후에 처음 진입했던 페이지로 돌아가는 경우 

 

 

13. 싱글 페이지 애플리케이션(SPA) 이해하기 

 

클라이언트사이드 렌더링(Clinet- side Rendering)

- 클라이언트 = 웹 브라우저 

- 렌더링 = HTML 페이지를 만드는 것

- 웹 브라우저에서 자바스크립트로 HTML 페이지를 만듬

 

싱글 페이지 애플리케이션 (single Page Application)

- 싱글 페이지 = 하나의 HTML문서 

- 애플리케이션  = 마치 앱처럼 여러 페이지를 돌아다니는 사이트 

- 여러 경로의 HTML 문서를 돌아다니는 게 아니라 하나의 HTML 문서 안에서 자바스크립트로 여러 페이지를 보여줌 

 

-  root div에다가 클라이언트사이드 렌더링을 하는데 리액트 라우터가 주소창에 적힌 경로를 읽어서 경로에 일치하는 컴포넌트르 렌더링하는 방식 

 

 

14. 리액트를 렌더링하는 방식 

 

1) 대표적인 렌더링의 종류 

 

클라이언트사이드 렌더링(Client-side Rendering)

 

 - 리액트로 할 수 있는 가장 기본적인 방식의 렌더링

 - 리액트로 작성한 코드는 자바스크립트로 변환 가능 

 - 자바스크립트로 변환된 리액트 코드를 웹 브라우저에서 실행해서 HTML을 만드는 것

 

서버사이드 렌더링(Server-side Rendering)

 

- 서버에서 HTML을 만들고 리스폰스로 보내주는 것 

- 백엔드 서버에서 리퀘스트를 받으면 상황에 맞는 HTML을 만들어서 리스폰스로 보내주는 방식 

- 이미 렌더링된 것이 웹 브라우저에 도착하니까 훨씬 빨리 화면을 띄어줄 수 있고, 검색 엔진에서 좋은 점수를 받아서 검색했을 때 사이트가 잘 노출될 수 있음

 

정적 사이트 생성 (Static Site Generation)

 

- 미리 HTML 파일을 만들어서 서버를 배포한느 것 

 

2) 렌더링을 활용한 리액트 기술 

 

Next.js

 

- 리액트 서버사이드 렌더링을 편하게 

- 리액트 라우터랑은 다르게 HTML 파일을 나누듯이 자바스크립트 파일을 나눠 놓으면 곧바로 페이지로 사용할 수 있는 장점

 

Gatsby

 

- 리액트로 정적 사이트 만들기 

- 리액트 코드를 미리 렌더링 해서 프로젝트를 빌드할 때 HTML 파일로 만듬 

- 리액트로 만든사이트를 빌드해서 손쉽게 HTML 파일로 만들 수 있음 

 

React Native

 

- 모바일 앱의 화면도 리액트로 

- 리액트로 작성한 코드를 모바일 앱으로 만들 수 있게 해줌 

- 리액트 코드로 개발하면 웹과 안드로이드와 iOS앱에서 사용하는 공통적인 코들르 한 번에 개발할 수 있음