SPA란? (single page application)
하나의 페이지로 만들어진 어플리케이션을 의미합니다.
전통적 웹 어플리케이션 vs SPA
SPA는 html파일을 브라우저 측에서 로드하고, 필요한 데이터는 API와 ajax통신을 이용해서 처리합니다.
브라우저에서 사용자가 상호작용 하면 필요한 부분만 업데이트 해서 처리합니다.
멀티플랫폼 Android, IOS에 대응하여 웹뷰로 처리하는 목적으로도 사용됩니다.
SPA의 단점
- 앱의 규모가 커지면, JS파일도 너무 커져서 로딩이 오래걸리게 됩니다.
- 브라우저에서 렌더링이 완료되기 까지 비어있는 화면이 나오게 됩니다.
- 그래서 규모가 큰 어플리케이션은 SSR(서버사이드 렌더링) 방식으로 처리합니다. (웹팩 설정 필요)
라우팅이란?
- 브라우저의 주소상태에 따라 다양한 화면을 보여주도록 처리하는 것을 라우팅이라고 합니다.
사용이유
- create-react-app로 프로젝트를 생성하게 되면 기본적으로 SPA에 CSR(클라이언트 렌더링) 입니다.
- 하나의 페이지만 사용하게 되는 것입니다.
- SPA이지만 라우터를 활용해서 사용자로 하여금 여러 페이지가 존재하는 것처럼 느껴지게 할 수 있습니다.
라우터 설치하고 프로젝트 시작하기
1. 라우터를 적용할 프로젝트 생성
npm create react-app 프로젝트명
2. 라우터 설치
npm add react-router-dom
3. 프로젝트 시작
npm start
라우터 적용하기
- 라우터를 사용할때는 index.js에서 App컴포넌트를 <BrowserRouter>로 감싸줍니다.
- 페이지 컴포넌트 만들기
- App컴포넌트에서 <Routes>를 사용해서 분기하기
- 주소요청을 통해 확인하기
index.js
....
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
App.js
- /요청은 Home컴포넌트가 나타납니다
- /user요청은 User컴포넌트가 나타납니다.
- /info요청은 Info컴포넌트가 나타납니다.
function App() {
return (
<Routes>
<Route path='/' element={<Home/>}/>
<Route path='/user' element={<User/>}/>
<Route path='/info' element={<Info/>}/>
</Routes>
);
}
export default App;
Link를 이용해서 다른페이지로 이동하기
- link태그는 화면에서 a태그로 생성됩니다.
- to 속성에는 연결할 요청주소를 적습니다.
- 어느 컴포넌트든 사용할 수 있습니다.
/로 연결되는 Home
//.....
return (
<ul>
<li><Link to='/user'>회원페이지</Link></li>
</ul>
)
URL파라미터 or 쿼리스트링
같은 컴포넌트라도 전달되는 데이터에 따라서 다른 내용을 보여줘야 하는 경우가 있습니다.
EX) 글 상세
이 때 URL주소의 매개변수를 전달 할 수 있고, 컴포넌트는 그 값을 받아서 사용 할 수 있습니다.
1. 쿼리스트링
- 쿼리스트링은 주소의 ? 뒤에 키=값 의 형태로 넘어가는 매개값입니다.
- 별도의 라우터 설정은 하지 않아도 됩니다.
- 컴포넌트에서는 useLocation() 훅 or useSearchParams() 훅을 사용 해서 쿼리스트링을 받을 수 있습니다.
/경로?키=값&키=값
링크에서는...
//.....
return (
<ul>
<li><Link to='/user?id=aa123&key=1'>회원페이지(쿼리파람)</Link></li>
</ul>
)
컴포넌트에서는....
useLocation() 훅
const location = useLocation();
- 배열을 반환합니다.
- 첫 번째 요소는 쿼리파라미터를 조회하거나 수정하는 get, set이 담긴 객체
- 두 번째 요소는 쿼리파라미터를 객체로 업데이트 하는 함수 반환
const [객체, function] = useSearchParams()
const [obj, setObj] = useSearchParams();
let id = obj.get("id"); //request.getParameter("키")
let key = obj.get("key");
2. URL파라미터 👍
- URL파라미터는 주소 뒤에 /경로/값/값 의 형태로 넘어가는 매개값입니다.
- 라우터에 추가적인 설정이 필요합니다. ( /주소/:키 )
- 컴포넌트에서는 useParams() 훅을 사용하여 URL파라미터를 받을 수 있습니다.
라우터에서는...
function App() {
return (
<Routes>
.....
<Route path='/info/:num' element={<Info/>}/>
</Routes>
);
}
export default App;
링크에서는...
//.....
return (
<ul>
<li><Link to='/info/1'>1번 info</Link></li>
<li><Link to='/info/2'>2번 info</Link></li>
<li><Link to='/info/3'>3번 info</Link></li>
</ul>
)
컴포넌트에서는...
useParams() 훅
/param에는 link로 넘어온 키가 담겨 있습니다.
let param = useParams();
중첩라우터로 공통 부분 처리하기
- 글페이지가 있고, 글에 따른 상세화면이 있다고 가정해 봅시다.
- 라우터의 설정은 아래 처럼 보여질 수 있습니다.
- 아래 설정은 두 라우터가 다르기 때문에 각각 다른 화면이 보입니다.
<Routes>
<Route path='/board' element={<Board/>}/>
<Route path='/board/:num' element={<BoardContent/>}/>
</Routes>
- 만약 Board 목록 페이지를 공통으로 사용하고 상세페이지를 서브로 보여주도록 처리하려면 중첩라우터를 활용할 수 있습니다.
- 중첩라우터로 적용되면 부모컴포넌트에서 <Outlet> 컴포넌트를 활용해서 하위 라우터를 보여지게 할 수 있습니다.
<Routes>
<Route path='/board' element={<Board/>}>
<Route path=':num' element={<BoardContent/>}/>
</Route>
</Routes>
Board에서는...
const Board = () => {
return (
<div>
<h3>게시글목록</h3>
<ul>
<li><Link to='/board/1' >글1</Link></li>
<li><Link to='/board/2' >글2</Link></li>
<li><Link to='/board/3' >글3</Link></li>
</ul>
{/* Oulet컴포넌트가 사용된 자리에 중첩된 내용이 보여지게됩니다 */}
<Outlet/>
</div>
)
}
export default Board;
BoardContent에서는...
const BoardContent = () => {
let {num} = useParams()
return (
<div>
<h3>글 상세페이지</h3>
{num}번 글입니다
</div>
)
}
export default BoardContent;
결과
헤더 태그 분리하기
라우터의 부가적인 기능
1. NavLink 컴포넌트
- 링크에서 사용하는 경로가 라우터의 경로와 일치하면 특정스타일을 적용 (활성화기능)
2. useNavigate() 훅 vs Navigate 컴포넌트
useNavigate() 훅
- JS의 history객체를 대신합니다.
- 이벤트에서 사용
Navigate 컴포넌트
- 리다이렉트기능
- 렌더링시에 사용
NavLink컴포넌트
- NavLink는 링크의 경로가 라우터의 경로와 일치하면 특정스타일을 적용해 줍니다.
- NavLink는 style속성을 제공하합니다
- style속성에는 실행시킬 함수를 작성합니다.
- 이 함수에 매개변수로 {isActive : boolean}객체를 넣어주는데, 활성화 여부를 표시가 가능합니다.
- 사용은 반드시 {isActive}변수로 구조분해할당 합니다.
Board컴포넌트 에서는...
const Board = () => {
return (
<div>
<h3>게시글목록</h3>
<ul>
{/*
<li><Link to='/board/1' >글1</Link></li>
<li><Link to='/board/2' >글2</Link></li>
<li><Link to='/board/3' >글3</Link></li>
*/}
<li><NavLink to='/board/1' style={
({isActive}) => {
return isActive ? myStyle : undefined
}
}>글1</NavLink></li>
<li><NavLink to='/board/2' style={({isActive}) => (isActive ? myStyle : undefined )}>글2</NavLink></li>
<li><NavLink to='/board/3' style={({isActive}) => (isActive ? myStyle : undefined )}>글3</NavLink></li>
</ul>
{/* Oulet컴포넌트가 사용된 자리에 중첩된 내용이 보여지게됩니다 */}
<Outlet/>
</div>
)
}
export default Board;
useNavigate() 훅
- useNavigate훅 은 특정 event가 발생할 때, url을 조작할 수 있는 함수를 제공합니다.
- react v6 에서 useHistory 가 변화한 것입니다. (JS의 history객체를 대신 합니다)
let navigator = useNavigate();
import { Fragment } from "react";
import { NavLink, Outlet, useNavigate } from "react-router-dom";
const Header = () => {
//useNavigate() 훅
let nav = useNavigate();
const goHome = () => {
nav('/내가원하는 주소')
}
return (
<button onClick={goHome}>이동</button>
)
}
export default Header;
JS의 history를 다루는 기능도 제공합니다.
예시) history.go(-1)
예시) history.go(1)
...
let nav = useNavigate();
return(
<>
<button onClick={() => nav(-1)}>
Go back
</button>
<button onClick={() => nav(1)}>
Go forward
</button>
<>
)
Navigate 컴포넌트
- <Navigate> 컴포넌트는 렌더링 될 때 현재 위치를 변경합니다.
- useNavigate()훅과 비슷해보이지만 useNavigate()훅은 렌더링 과정에 사용할 수 없습니다.
const MyPage = () => {
/*
렌더링 과정에 nav를 쓰지말라는 경고 후 작동이 안됩니다.
let nav = useNavigate()
let loginYN = false;
if(!loginYN) {
nav('/');
}
*/
//Navigate컴포넌트
let loginYN = false;
if(!loginYN) {
return <Navigate to='/' replace={true}/>
}
return (
<div>
여기는 권한있는 사람만 들어옴
</div>
)
}
export default MyPage;
'Front-End > React' 카테고리의 다른 글
10. 리액트 ContextAPI (0) | 2023.01.02 |
---|---|
9. Ajax로 외부 데이터 통신하기 (0) | 2022.12.29 |
7. React에 CSS적용하기 (0) | 2022.12.27 |
6. 리액트 기본훅 (0) | 2022.12.26 |
5. 컴포넌트 반복 (0) | 2022.12.23 |