leehyeon-dv 님의 블로그
TailwindCSS설치방법 , React Router 본문
1. Tailwind CSS설치
pnpm install tailwindcss @tailwindcss/vite
2.Vite plugin구성
vite.config.ts파일 아래 파일을 추가한다
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
tailwindcss(),
],
})
3.index.css에 최상단에 아래 코드 추가
@import "tailwindcss";
React Router
사용자가 웹 브라우저의 주소창에 URL을 입력하면 해당 URL에 맞는 데이터를 서버로 부터 받아와 사용자에게 제공하는 과정
CSR은 페이지는 유지하되, 부분적으로 내가 원하는 부분만 경로에 해당하는 컴포넌트를 보여줬다, 숨겼다 할 수 있는 방법
SPA를 유지하면서, 멀티 페이지 형태의 장점을 그대로 사용할 수 있다
장점
1. URL 경로 활용
URL 경로가 달라지므로, 브라우저의 Web History API를 이용할 수 있다
2. 주소 복사 및 공유 가능
사용자가 특정 페이지에 머무르고 있을때, 해당 URL을 복사하여 다른 사람이 방문해도 동일한 화면을 볼 수 있다
SPA에서는 보통 초기화면으로 리디렉트 되는 문제가 있지만, React Router를 활용하면 원하는 위치로 바로 이동할 수 있다
3. 성능 최적화
전체 페이지를 새로고침하지 않고 필요한 부분만 변경하므로 성능이 향상되고 사용자 경험이 개선된다
4. 네비게이션이 부드러움
서버 렌더링 방식과 달리 새로운 페이지를 로드하지 않고 빠르게 전환이 가능하다
동작원리
1. 사용자가 특정 URL을 입력하거나 클릭하여 새로운 페이지를 요청한다
2. 요청된 URL에 해당하는 데이터를 서버에서 찾아 응답한다
3. 서버는 해당 URL에 맞는 HTML, CSS, JavaScript 등의 리소스를 클라이언트에게 전달한다
4. 브라우저는 서버로부터 받은 데이터를 렌더링해 새로운 페이지를 표시한다
5. 이 과정에서 전체 페이지가 새로고침되며, 새로운 html이 로드된다
Routing의 예시
사용자가 https://umc.com/home을 입력하면 서버는 umc.html을 반환해 해당 페이지를 표시한다
사용자가 https://umc.com/about을 입력하면 about.html을 받아와 페이지가 로드된다
Client Side Rendering(CSR)
클라이언트 사이드 라우팅
- SPA에서 주로 사용되며 페이지 전체를 새로고침하지 않고 필요한 데이터만 갱신한다
- 새로운 링크를 클릭하면 URL은 업데이트 되지만 전체 페이지가 새로고침되지 않는다
- React, Vue.js 같은 프레임 워크에서 주로 사용된다
(새로운 경로를 입력했을때 서버에서 새로운 페이지를 요청하는 것이 아닌, 앱 안에서 필요한 부분만 업데이트 하는 것이 Routing과의 차이다 )
React Router 실습
pnpm i react-router-dom
App.tsx에 아래와 같이 코드를 입력해준다
import './App.css'
// 1. import를 해줍니다.
import {createBrowserRouter, RouterProvider} from "react-router-dom";
const router = createBrowserRouter([
{
path: '/',
element: <h1>홈 페이지입니다.</h1>
},
{
path: '/movies',
element: <h1>영화 페이지 입니다.</h1>
}
])
function App() {
return <RouterProvider router={router}/>
}
export default App
1. createBrowerRouter를 활용하여 원하는 path경로를 통해 해당 경로에 접근하면 어떤 element를 보여주게 될 지 정의해준다
2. path: '/'라는 것은 현재 vite로 프로젝트를 세팅했을 경우 localhost:5173을 의미한다. 즉 처음 실행했을때 페이지이다
3. path: 'movies' 라는 것은 현재 vite로 프로젝트를 세팅했을 경우 localhost:5173/movies경로를 의미한다. 즉, 유저가 movies라는 경로로 이동 했을때, 영화 페이지 입니다.라는 텍스트가 나오게 된다
4. createBrowerRouter를 통해, 만든 router를 RouterProvider의 router에 전달해주면 된다 그러면 path로 접근했을때 element가 페이지에 보이게 됩니다.
React Router 지정하지 않은 경로 접근 처리
만약 사용자가 지정한 path가 아닌 localhost:5173/yaho와 같은 경로에 접근하면 404 Not Found라는 에러가 발생합니다
이것에 대한 접근 처리가 필요합니다
import './App.css'
import {createBrowserRouter, RouterProvider} from "react-router-dom";
const router = createBrowserRouter([
{
path: '/',
element: <h1>홈 페이지입니다.</h1>,
// 없는 경로에 들어온 처리를 해줍니다.
errorElement: <h1>너는 없는 경로에 들어왔다 ^ㅁ^ 야호~!</h1>
},
{
path: '/movies',
element: <h1>영화 페이지 입니다.</h1>
}
])
function App() {
return <RouterProvider router={router}/>
}
export default App
이렇게 하면 다음과 같은 에러 처리를 할 수 있습니다
React Router의 Outlet사용법 Link 태그를 활용한 페이지 이동
1. Outlet 적용전 세팅
3개의 페이지 (home.tsx, movies.tsx, not-found.tsx<에러페이지>)를 만든다
그리고 만든 페이지를 import 해줍니다
import './App.css'
import {createBrowserRouter, RouterProvider} from "react-router-dom";
//만든 페이지들을 import
import HomePage from "./pages/home.tsx";
import Movies from "./pages/movies.tsx";
import NotFound from "./pages/not-found.tsx";
const router = createBrowserRouter([
{
path: '/',
element: <HomePage/>,
errorElement: <NotFound/>
},
{
path: '/movies',
element: <Movies/>
}
])
function App() {
return <RouterProvider router={router}/>
}
export default App
이런식으로 나오면 성공입니다
2. Outlet 적용방법
먼저, '/' 경로에서만 공유하는 layout을 만들어보고자 합니다
'/' 경로에서 공유한다는 것은 '/movie', '/yaho'등 '/'로 시작하는 모든 루트 경로에서 해당 Outlet을 공유하는 것입니다
src/layout폴더를 만들어 root-layout.tsx파일을 만듭니다
import {Outlet} from "react-router-dom";
const RootLayout = () => {
return (
<>
<Outlet/>
</>
);
};
export default RootLayout;
다음과 같은 코드로 만들려고 하는 목표는 Outlet을 활용해 Single Page Application 장점을 살려 navbar라는 컴포넌트를 만든 후 navbar는 유지되고 아래에 있는 내용만 각 경로에 맞게 변경되도록 만드는 것입니다
import {Link} from "react-router-dom";
const Navbar = () => {
return (
<nav>
<Link to={'/'}>홈 페이지로 이동</Link>
<Link to='/movies'>영화 목록 페이지로 이동</Link>
</nav>
);
};
export default Navbar;
만든 navbar를 root-layout.tsx에 import를 시켜줍니다
import {Outlet} from "react-router-dom";
import Navbar from "../components/navbar.tsx";
const RootLayout = () => {
return (
<>
<Navbar/>
<Outlet/>
</>
);
};
export default RootLayout;
이제 이를 router에 연결해주도록 하겠습니다
import './App.css'
import {createBrowserRouter, RouterProvider} from "react-router-dom";
import HomePage from "./pages/home.tsx";
import NotFound from "./pages/not-found.tsx";
import Movies from "./pages/movies.tsx";
import RootLayout from "./layout/root-layout.tsx";
const router = createBrowserRouter([
{
path: '/',
// element: <HomePage/>,
element: <RootLayout/>,
errorElement: <NotFound/>
},
{
path: '/movies',
element: <Movies/>
}
])
function App() {
return <RouterProvider router={router}/>
}
export default App
하지만 이는 navbar를 통해 path에 맞는 element가 나오기를 기대하는데 그렇게 동작하지 않습니다
따라서 RootLayout안에있는 Outlet안에 보여주길 원하면, 경로에 해당하는 element들을 외부에 표기하는게 아니라
children이라는 속성안에 자식경로를 만들어 표기해줘야합니다
Dynamic Routing(동적라우팅)
보통 상세 상품 페이지는 진열된 상품 정보는 다르지만 전체적인 ui는 비슷합니다
이러한 페이지 같은 경우 Dynamic Routing을 활용해 구현을 많이 합니다
예를들어 umc.com/vp/products/뒤에 숫자만 다른경우 숫자를 활용해 페이지의 정보를 구분하는것을 말합니다
이를 React Router를 활용하여 쉽게 구현이 가능합니다
import './App.css'
import {createBrowserRouter, RouterProvider} from "react-router-dom";
import HomePage from "./pages/home.tsx";
import NotFound from "./pages/not-found.tsx";
import Movies from "./pages/movies.tsx";
import RootLayout from "./layout/root-layout.tsx";
const router = createBrowserRouter([
{
path: '/',
element: <RootLayout/>,
errorElement: <NotFound/>,
children: [
{
index: true,
element: <HomePage/>
},
{
// /:을 활용해서, 동적으로 바뀌는 부분의 이름을 정의해줍시다.
path: 'movies/:movieId',
element: <Movies/>
}
]
},
])
function App() {
return <RouterProvider router={router}/>
}
export default App
가장 중요한점은 /: 뒤에 설정한 이름으로 우리가 해당하는 params의 값을 받아올 수 있습니다
위와 같이 /movies/:movieId 경로를 설정하면 movieId 값을 가져와 서버에 데이터를 요청하여 응답 받은 해당 영화의 각기 다른 상세 정보를 표시할 수 있습니다
useParams를 활용해보자
import { useParams } from 'react-router-dom';
// movies.tsx
const MoviesPage = () => {
const params = useParams();
console.log(params);
return <h1>{params.movieId}번의 Movies Page 야호~!</h1>;
};
export default MoviesPage;
useParams를 활용하면 파라미터에 대해 받아볼 수 있습니다
이전에 createBrowserRouter에서 path로 :moveId 이렇게 작성했기 때문에
예를들어 :umc 이렇게 작성했으면, params.umc 로 접근할수있습니다
react-hook
리액트의 useEffect 훅은 컴포넌트의 생명주기와 관련된 부수효과를 처리시 사용됩니다
예를들어, API호출, 구독설정, 수동 DOM조작, 타이머 설정이 필요할때 useEffect를 활용할 수 있습니다
useEffect
Effect : 특정 상황에서 컴포넌트 내부에서 발생하는 행동
Side Effect : 데이터를 불러오거나, API를 호출하는 등의 작업을 추가로 하는것
React는 이런 Side Effect를 특정 조건에서만 실행하기 위해 useEffect 훅을 제공합니다
이 훅을 통해 컴포넌트가 마운트 될때, 특정값이 변경될때, 또는 언마운트 될때 원하는 작업을 수행할 수 있습니다
또한, 의존성 배열을 사용하면 Side Effect가 언제 실행될지 제어할 수 있습니다
import { useEffect } from 'react';
useEffect(() => {
// 실행할 부수 효과 (예: API 호출, 구독 설정 등)
}, []);
// 의존성 배열 (Dependency Array)
// [] 빈 배열이면 컴포넌트가 처음 마운트될 때만 실행됨.
useEffect의 두가지 인자
1. 첫번째 인자
부수효과를 실행하는 함수를 지정합니다
이 함수 안에서 API호출, 이벤트 리스너 설정, 타이머 설정 등의 작업을 수행할 수 있습니다
2. 두번째 인자
useEffect가 실행될 조건을 지정합니다
[ ] : 컴포넌트가 처음 마운트 될때만 실행됩니다
[state] : state값이 변경될 때마다 실행됩니다
의존성 배열을 생략하면 컴포넌트가 리렌더링될때마다 실행됩니다
'Front' 카테고리의 다른 글
npm에서 pnpm으로 마이그레이션 하기 (0) | 2025.05.10 |
---|