25회차 React & Redux

정상희·2025년 4월 9일

코딩공부

목록 보기
34/60
post-thumbnail

현재 오즈코딩스쿨 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.

1. React 조건부 렌더링

React에서는 조건에 따라 특정 컴포넌트를 화면에 보이게 하거나 숨기는 것을 조건부 렌더링이라 부른다.

1) if 문을 사용하는 방식

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;

  if (isLoggedIn) {
    return <h1>다시 오신 것을 환영하오이다</h1>;
  }
  return <h1>회원가입 해주시기 바라오이다</h1>;
}

가장 기본적인 조건 분기 방식이다.


2) && 연산자를 사용하는 방식

function Notification(props) {
  const hasNewMessage = props.hasNewMessage;

  return (
    <div>
      <h1>마이 페이지이다</h1>
      {hasNewMessage && <p>새로운 메시지가 있소이다</p>}
    </div>
  );
}

조건이 참일 때만 뒤의 JSX가 렌더링된다.


3) 삼항 연산자 ? :를 사용하는 방식

function UserStatus(props) {
  return (
    <div>
      {props.isOnline ? <p>접속 중이다</p> : <p>접속 종료 상태이다</p>}
    </div>
  );
}

조건에 따라 두 가지 경우 중 하나를 선택하여 출력할 수 있다.


4) 조건이 거짓이면 아무것도 출력하지 않는 방식

function WarningBanner(props) {
  if (!props.warn) {
    return null; // 아무것도 렌더링하지 않는다
  }

  return <div className="warning">경고 메시지이다</div>;
}

null을 반환하면 아무것도 그려지지 않는다.



2. React Router

React Router는 React에서 페이지 전환을 구현할 수 있게 도와주는 라이브러리이다.
Single Page Application(SPA) 구조에서도 주소(URL)를 바꾸면 다른 컴포넌트를 보여줄 수 있도록 한다.

설치

npm install react-router-dom
npm i react-router-dom

1) 주요 컴포넌트

a. BrowserRouter

React Router를 사용하고 싶은 곳을 <BrowserRouter> 컴포넌트로 감싼다.
<App /> 컴포넌트를 감싸버리면 어디서든 사용 가능하다.

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

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

이것은 앱 내에서 라우팅을 사용할 수 있도록 만들어주는 최상위 설정이다.


<Link> 컴포넌트와 to속성을 사용해서 이동하고 싶은 주소로 이동할 수 있다.
이때 <Link>컴퍼넌트는 <a>요소로 표시되지만 새로고침은 발생하지 않고 주소만 변경된다!

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

function NavBar() {
  return (
    <nav>
      <Link to="/main">메인</Link>
      <Link to="/mypage">마이페이지</Link>
      <Link to="/test">테스트</Link>
    </nav>
  );
}

c. Routes와 Route 컴포넌트

  • <Routes>컴포넌트는 <Route>컴포넌트들을 묶어주는 역할
  • <Route>컴포넌트는 특정 주소에서 어떤 컴포넌트를 보여줄지 정해주는 역할
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';

function App() {
  return (
    <Routes>
      <Route path="/main" element={<Main />} />
      <Route path="/mypage" element={<MyPage />} />
      <Route path="/test" element={<Test />} />
    </Routes>
  );
}

Route는 URL 경로와 그에 해당하는 컴포넌트를 연결해주는 역할을 한다.


2) 주요 함수

a. useNavigate()

특정 주소로 이동할 수 있게 해주는 함수를 생성

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

function MyComponent() {
  const navigate = useNavigate();

  const goToAbout = () => {
    navigate('/about');
  };

  return (
    <button onClick={goToAbout}>
      소개 페이지로 이동
    </button>
  );
}

navigate('/경로') 형태로 원하는 경로로 이동할 수 있다.


b. useLocation()

현재 페이지의 위치 정보를 담고있는 객체를 생성

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

const location = useLocation();

객체구성

{
  pathname: "/about",        // 현재 경로
  search: "?mode=dark",      // 쿼리 스트링
  hash: "#section1",         // 해시값
  state: { from: "/login" }, // navigate 시 넘긴 state
  key: "abc123"              // 고유 키값
}
  • navigate로 넘긴 데이터를 useLocation으로 받을 수 있다.
  • 보통 로그인 성공 후, 또는 등록 완료 후 정보 전달용으로 많이 쓰인다.

c. useParams()

주소의 쿼리 파라미터 값을 담은 객체 생성

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

function App() {
  return (
    <Routes>
      <Route path="/user/:id" element={<UserPage />} />
    </Routes>
  );
}

useParams()는 URL에서 설정한 :id 값을 객체 형태로 반환한다.


d. useSearchParams()

주소의 쿼리 스트링 값을 가져올 수 있는 객체와 쿼리 스트링을 수정할 수 있는 함수 생성

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

function ProductList() {
  const [searchParams, setSearchParams] = useSearchParams();

  const category = searchParams.get('category');
  const page = searchParams.get('page');

  return (
    <div>
      <h1>카테고리: {category}이다</h1>
      <p>{page} 페이지이다</p>
    </div>
  );
}

searchParams.get('key') 형태로 값을 가져올 수 있다.



3. React Router 실습

1) 메인 페이지에서 동물 목록 화면에 표시하기

a. React Router를 사용한 페이지 별 라우팅 과정

BrouserRouter

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

ReactDOM.createRoot(document.getElementById("root")).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

Routes와 Route

<Routes>
 <Route path='/' element={<Main /> }></Route>
 <Route path='/detail/:id' element={<Detail />}></Route>
 <Route path='/search' element={<Search />}></Route>
</Routes>
<Link to={`/detail/${el.id}`}>
 <img src={el.img} />
 <div>{el.name}</div>
</Link>

b. data.js 파일 내 데이터를 메인 페이지에 렌더링하는 방법

먼저 동물 데이터를 따로 저장할 data.js 파일을 만든다.
아래와 같이 객체 배열 형태로 정의하면 된다.

data.js 구성

import images from "./images"

export const data = [
    {
        id:0,
        name:'고양이',
        img: images.cat,
        description: '나만 고양이 없어..'
    },
    {
        id:1,
        name:'소',
        img: images.cow,
        description: '어린 송아지가 부뚜막에 앉아 울고 있어요'
    },
    {
        id:2,
        name:'강아지',
        img: images.dog,
        description: '강아지 귀여워'
    },
    {
        id:3,
        name:'오리',
        img: images.duck,
        description: '오리는 뒤집어지면 혼자 일어나지 못한다'
    },
    {
        id:4,
        name:'여우',
        img: images.fox,
        description: 'What Does the Fox Say?'
    },
    {
        id:5,
        name:'개구리',
        img: images.frog,
        description: '콩쥐야... 망했어...'
    },
    {
        id:6,
        name:'기린',
        img: images.giraffe,
        description: '기린은 하루에 10분에서 2시간만 잔다.'
    },
    {
        id:7,
        name:'사자',
        img: images.lion,
        description: '카카오의 라이언은 탈모 사자다.'
    },
    {
        id:8,
        name:'판다',
        img: images.panda,
        description: '판다는 유전학적으로 육식동물에 가깝다.'
    },
    {
        id:9,
        name:'펭귄',
        img: images.penguin,
        description: '펭귄은 사실 롱다리다.'
    },
    {
        id:10,
        name:'돼지',
        img: images.pig,
        description: '돼지는 배가 부르면 그 이상 먹지 않습니다.'
    },
    {
        id:11,
        name:'토끼',
        img: images.rabbit,
        description: '암컷 토끼는 싸울 때 수컷의 얼굴을 초당 5회까지 때릴 수 있습니다.'
    },
    {
        id:12,
        name:'양',
        img: images.sheep,
        description: '잠이 안올 때 양을 세는 이유는 sleep과 sheep의 발음이 비슷해서다.'
    },
    {
        id:13,
        name:'호랑이',
        img: images.tiger,
        description: '호랑이 털의 무늬는 지문 같은 역할을 한다.'
    },
]
  • 동물 정보는 id, name, img, description 속성으로 구성된 객체 배열이다.
  • imagescat, dog, fox 등 각각의 이미지를 key로 가지는 객체이며, 이로써 각 동물의 이미지를 코드에서 바로 참조할 수 있다.
  • 이 데이터는 export 되었기 때문에 다른 컴포넌트에서 import 하여 사용할 수 있다.

Main.jsx에서 데이터를 렌더링하는 방법이다

import { Link } from "react-router-dom";
import { data } from "../assets/data/data"

function Main() {
    return (
        <ul>
            {data.map(el => (
                <li key={el.id}>
                    <Link to={`/detail/${el.id}`}>
                        <img src={el.img} />
                        <div>{el.name}</div>
                    </Link>
                </li>
            ))}
        </ul>
    );
}

export default Main;
  • datamap()으로 순회하면서 각 동물 항목을 리스트로 렌더링하는 구조이다.
  • 각 항목은 li로 감싸져 있으며, 내부에 Link 컴포넌트를 사용하여 상세 페이지로 이동할 수 있도록 되어 있다.
  • Linkto 속성은 /detail/{id} 경로로 이동하도록 설정되어 있다.
  • img 태그의 srcel.img, altel.name으로 설정하여 이미지 접근성과 명확성을 높이고 있다.

c. 동물 카드 클릭 시 상세 페이지로 경로 이동 설정

동물 카드에 Link를 설정하는 방법이다(Main.jsx)

import { Link } from "react-router-dom";
import { data } from "../assets/data/data"

function Main() {
    return (
        <ul>
            {data.map(el => (
                <li key={el.id}>
                    <Link to={`/detail/${el.id}`}>
                        <img src={el.img} />
                        <div>{el.name}</div>
                    </Link>
                </li>
            ))}
        </ul>
    );
}

export default Main;
  • react-router-domLink 컴포넌트를 사용하여 경로 이동을 처리하는 방식이다.

  • el.id는 각 동물 객체의 고유한 id 값이며, 이를 포함한 주소(/detail/1, /detail/5 등)로 연결되는 것이다.

라우터에서 상세 페이지 경로를 설정하는 방법(App.jsx)

import { useState } from "react";
import "./App.css";
import { Route, Routes, useNavigate } from "react-router-dom";
import Main from "./page/Main";
import Detail from "./page/Detail";
import Search from "./page/Search";


function App() {
  const [inputValue, setInputValue] = useState('')
  const navigate = useNavigate()

  return (
    <>
      <header>
        <h1>💚 동물 조아 💚</h1>
        <input value={inputValue} onChange={(event) =>
          setInputValue(event.target.value)} />
        <button onClick={() => navigate(`/search?animal=${inputValue}`)}>
          검색
        </button>
      </header>
      <Routes>
        <Route path='/' element={<Main /> }></Route>
        <Route path='/detail/:id' element={<Detail />}></Route>
        <Route path='/search' element={<Search />}></Route>
      </Routes>
      <footer>all rights reserved to OZ</footer>
    </>
  );
}

export default App;
  • <Route path="/detail/:id">는 동적 라우팅이다.
  • 이때 :id는 경로의 일부분이며, 사용자가 실제로 클릭한 동물의 id 값으로 대체되는 것이다.

상세 페이지에서 id 값으로 데이터 찾는 방법(Detail.jsx)

import { useParams } from "react-router-dom";
import { data } from "../assets/data/data";

function Detail() {
    const params = useParams();
    const animalData = data.find((el) => el.id === Number(params.id));

    return (
        <section className="detail">
            <img src={animalData.img} />
            <h2>{animalData.name}</h2>
            <div>{animalData.description}</div>
        </section>
    );
}

export default Detail
  • useParams() 훅은 경로에서 :id 부분의 값을 추출하는 역할을 한다.
  • params.id는 문자열(string)이므로, 비교를 위해 Number()를 사용해 숫자로 변환하는 것이 일반적이다.
  • data.find()를 통해 해당 id를 가진 동물 객체를 찾아 화면에 표시하는 구조이다.

2) 동물 상세 정보 페이지 만들기

a. 상세 페이지로 이동 시 특정 id값에 대한 데이터를 받아오는 방법

import { useParams } from "react-router-dom";
import { data } from "../assets/data/data";

function Detail() {
  const params = useParams();  // URL 경로에 포함된 id 값을 가져온다. 예: { id: "3" }

  // data 배열에서 id 값이 일치하는 동물 데이터를 찾아낸다
  const animalData = data.find((el) => el.id === Number(params.id));

  return (
    <section className="detail">
      <img src={animalData.img} alt={animalData.name} />
      <h2>{animalData.name}</h2>
      <div>{animalData.description}</div>
    </section>
  );
}

export default Detail;
  • 경로 설정도 함께 필요하다(App.jsx)
    여기서 /detail/:id는 동적 경로를 의미하며, 사용자가 /detail/5 같은 경로로 이동할 때, useParams()를 통해 해당 id 값이 컴포넌트로 전달되는 것이다.

3) 동물 이름으로 검색기능 만들기 & 검색 결과 페이지 생성하기

a. useSearchParmas를 사용하여 경로의 특정 값에 대한 데이터를 받아오는 방법

import { Link, useSearchParams } from "react-router-dom";
import { data } from "../assets/data/data";
import { getRegExp } from "korean-regexp";

function Search() {
    const [searchParams] = useSearchParams();
    const param = searchParams.get('animal');
    const reg = getRegExp(param);

    const filterdData = data.filter(el => el.name.match(reg));

    return (
        <ul>
            {filterdData.map(el => (
                <li key={el.id}>
                    <Link to={`/detail/${el.id}`}>
                        <img src={el.img} />
                        <div>{el.name}</div>
                    </Link>
                </li>
            ))}
        </ul>
    );
}

export default Search;
  • useSearchParams()?animal=고양이처럼 URL 쿼리스트링에 포함된 데이터를 읽어올 수 있게 해주는 훅이다.
  • searchParams.get("animal")로 해당 키의 값을 추출하는 방식이다.
  • 이 방식은 검색어를 페이지 주소에 노출시키면서, 페이지 리로드 없이 검색 결과를 보여줄 수 있는 방법이다.

b. useNavigate를 사용하여 경로를 이동하는 방법

import { useNavigate } from "react-router-dom";

function App() {
  const [inputValue, setInputValue] = useState('');
  const navigate = useNavigate();

  const handleSearch = () => {
    navigate(`/search?animal=${inputValue}`);
  };

  return (
    <>
      <input value={inputValue} onChange={(event) => setInputValue(e.target.value)} />
      <button onClick={handleSearch}>검색</button>
    </>
  );
}
  • useNavigate()는 프로그래밍적으로 페이지 경로를 변경할 수 있게 해주는 훅이다.
  • 버튼 클릭 시 navigate()를 사용하여 검색어를 쿼리로 포함한 경로로 이동시키는 것이다.
  • navigate("/search?animal=강아지")처럼 쓰면, Search.jsx 페이지가 렌더링되며 해당 데이터를 읽게 된다.

c. korean-regexp

korean-regexp는 한글 초성 검색이 가능하도록 도와주는 유틸리티 라이브러리이다.
https://www.npmjs.com/package/korean-regexp/v/1.0.7

  • 일반적인 문자열 .includes()는 초성 검색이 되지 않지만, 이 라이브러리를 사용하면 'ㄱㅇ' → '고양이' 매칭 가능하다.

설치

npm i korean-regexp

d. 전체 데이터 목록에서 검색어로 필터링 된 데이터를 받아오는 방법

필요한 모듈을 불러온다.

import { useSearchParams } from "react-router-dom";
import { data } from "../assets/data/data";
import { getRegExp } from "korean-regexp";
  • useSearchParams: URL에서 쿼리 문자열을 추출하기 위해 사용한다.
  • data: 전체 동물 데이터 목록이다.
  • getRegExp: 검색어를 정규표현식으로 변환해주는 함수로, 초성 검색을 가능하게 한다.

쿼리 문자열에서 검색어를 받아온다.

const [searchParams] = useSearchParams();
const param = searchParams.get('animal');

/search?animal=고양이처럼 입력되었을 때 "고양이"param으로 저장된다.

검색어를 기반으로 정규식 객체를 만든다.

const reg = getRegExp(param);
  • getRegExp("ㄱㅇ")/.*ㄱ.*ㅇ.*/ 와 같은 정규식이 만들어진다.
  • 이로 인해 초성 기준 검색이 가능해진다.

동물 이름(el.name)이 검색어 정규식과 매칭되는 항목만 추출한다.

const filteredData = data.filter(el => el.name.match(reg));
  • match(reg)를 통해 부분 일치 여부를 판단한다.
  • 조건에 해당하는 항목만 filteredData 배열에 담긴다.

실습 이미지

끝맺음.

머리가 멍~
라우트 어려워요..ㅠㅠ

profile
UI/UX디자이너의 코딩 공부

0개의 댓글