20230620 TIL

뿌링클 치즈맛·2023년 6월 24일
0

Elice AI트랙 8기

목록 보기
23/28

SPA와 라우팅

SPA(Single Page Application)은 하나의 페이지 요청으로 전체 웹앱을 사용하는 방식.
Client-side routing 기술(클라이언트쪽에서 발생하는 라우팅) 을 활용, 페이지 진입 시 리로드없이 라우팅함.(전체 사이트를 다시 그리는 것이 아니라 필요한 부분만 다시 그림)
AJAX 기술을 활용, 페이지 이동 시 서버에 데이터만 요청하여 자바스크립트로 페이지를 만듦.(서버가 직접 페이지를 그리는 것이 아니기 때문에 fetch로 데이터를 얻어와 페이지 이동시 데이터만 요청)
MPA와 다르게, 여러 페이지를 하나의 앱의 구성요소로 보고 여러 페이지 간의 스타일, 컴포넌트를 재활용하는 방향으로 구현.(블로그,카페의 프로필을 통일한다거나)
자바스크립트만을 활용해 전체 페이지를 만들기에, 첫 요청 시 빈 페이지를 받게 됨.
단 하나의 페이지를 관리하며, 모든 라우트에서 해당 페이지를 내려준다.
모바일 앱을 사용하는 듯한 경험을 주기 위해 자바스크립트와 History API 등의 Web API를 이용하고 페이지 리로드 없는 네비게이션을 구현한다.

장점
서버에서 페이지를 만들 필요가 없으므로(서버에 무리가 가지 않음) 서버렌더링 없이 CDN에 캐싱이 가능(보다 빠르게 실행)
매번 페이지 요청을 할 필요가 없어 네트워크 요청이 줄어듦.
마찬가지로 데이터 요청 등을 캐싱하여 재사용하는 등 제약 조건이 줄어듦.
웹사이트를 개별 페이지보다는 하나의 앱으로 보는 설계로 고도의 소프트웨어 설계(상태관리,라우팅,컴포넌트 재사용,훅을 통한 로직)와 패턴을 적용할 수 있음.

단점
SPA는 페이지 요청시 주로 빈 페이지를 전송하므로, 서버에서 모든 페이지 정보를 렌더링하는 MPA방식 보다는 정보를 적게 갖고 있어 Search Engine Optimization(검색엔진 최적화)에 불리함.
하나의 자바스크립트 앱이 지속하므로, 메모리 관리와 성능, 데이터 활용 등이 중요.메모리관리와 성능유지에 대한 고민이 필요.
여러 페이지를 전송받는 것 보다, 하나의 거대한 자바스크립트 앱을 전송받아야 하므로 코드가 많아질수록 로드 속도가 느려짐(code-splitting,tree-shaking으로 코드의 양을 줄이고 lazy loading 처리를 통해 빠르게 로딩하려고 보완함)

SPA에서 라우팅
주로 History API 혹은 URL Hash(naver.com에 #a #b를 넣으면 리로드하지 않고 url을 변경함) 를 이용해 페이지 리로드 없는 페이지 전환을 구현.
• history, location 등 HTML5 API를 활용.
• visibilitychange, popstate, beforeunload 등 window event를 활용하여 페이지
전환 등의 이벤트 시 핸들러를 등록.
• react-router, reach-router 등의 라이브러리를 활용하면, 라우팅 관련 기능을 쉽게
사용할 수 있음

MPA(Multi Page Application)은 서버에 미리 여러 페이지를 두고,
유저가 네비게이션 시 요청에 적합한 페이지를 전달.페이지 요청마다 모든 리소스를 다시 받아오므로, 페이지 간 데이터를 재활용하기 힘듦

<Link href="/">WEB</Link>
          {/* a태그를 링크 컴포넌트로 바꿈 */}
          {/* Single Page Application */}
          {/* input에 입력을 하고 html을 클릭해도 값이 그대로  유지됨*/}
        </h1>
        <input type='text' placeholder='search'/>

input에 입력을 하고 WEB을 클릭해도 값이 그대로 유지되는 이유

react-router

Declarative routing for React.(함수를 연결하지 않고 컴포넌트로 만들어 사용, 반대의 방식은 Imperative)
React의 JSX(<Link to='login'>)를 이용하거나, History API(handClick=()=>push('login'))를 사용하여 라우팅을 구현.
웹에서는 react-router-dom을 사용.
적용 시, 서버의 모든 path에서 같은 앱을 서빙하도록 해야 함
서버에서 다른 path일 때 다른 앱을 내리면 MPA가 된다.

기능
React 컴포넌트를 특정 path와 연결하면, 해당하는 path로 진입 시 컴포넌트를 렌더링하게 함.
(<Route path='login'> =>Login Page를 렌더링하라. <Login Page/> </Route>)
query, path variable 등 URL parameter를 얻어 활용함.(/login? pathquery로 email='abc@abc.com'을 입력하면 자동으로 form 완성)
조건에 맞지 않을 경우 redirect 함. <Redirect to='/register'/>
페이지 이동 시, history.listen(callback) 으로 이벤트 핸들러를 등록함.
/posts/my-post-1 등의 nested route를 구현함. Route 안에 Route가 들어갈 경우, nested route로 구현한다.
nested route(/posts 안에 post1,post2가 있고 post2를 클릭할 경우 /posts 뒤에 post-id를 연결해 /posts/post2 식으로 path variable을 넣어 /posts는 유지하고 그 뒤에 /post2을 붙여 구현 )

사용
<BrowserRouter> 로 감싸 Router Context(React Context)를 제공해야 함.Router Context 안에서만 BrowserRouter가 동작한다.
Route로 path를 정의하고, 그 안에 렌더링하고자 하는 컴포넌트를 넣음.(<Route path='login'> =>Login Page를 렌더링하라. <Login Page/> </Route>)
Link로 특정 페이지로 이동 시, 리로드 없이 페이지가 이동함. Link는 anchor tag를 래핑한다.
Switch로, 가장 위의 매칭되는 path의 라우트 하나를 렌더링하게 함.

import { BrowserRouter, Route, Switch } from 'react-router-dom'
export function App() {
	return (
	<BrowserRouter>{/*BrowserRouter로 감싸기*/}
	<Switch> {/*이때의 switch는 매칭되는 하나만을 route함!*/}
		<Route path="/about"><AboutPage /></Route>
      	/contact로 접속하면 아래의 Route(path='contact')에 매칭된다!
      내부에 있는 children인 ContactPage를 렌더링
		<Route path="/contact"><ContactPage /></Route>
		<Route path="/"><HomePage /></Route>
      //가장 마지막에 있는 이유: 모든 path가 /로 시작해서 항상 HomePage가 렌더링되기 때문에 가장 마지막에 둠. 위에서부터 읽어 내려오는 방식이다.
      // <Route path="/"><HomePage /></Route>를 가장 위에 두더라도 exact를 사용하면 정확하게 path가 / 일때만 HomePage가 렌더링된다.
	</Switch>
	</BrowserRouter>
    )
}

react-router 컴포넌트

BrowserRouter

  • 브라우저 환경에서 라우팅 기능을 동작할 수 있게 라우터 컨텍스트를 하위 앱에 적용해 내부에서 라우터 기능을 이용할 수 있게 한다.HTML5의 History API를 사용하여, UI와 URL의 싱크를 맞추는 역할.
  • 모든 URL에 대해 동작하게 하기 위해서는 서버 설정 필요.
    브라우저에서 요청을 서버에 보내면 서버는 브라우저로 리액트 앱A/페이지A 을 보낸다. 이후 브라우저가 서버로 /register를 요청하면 서버는 브라우저로 리액트앱R/페이지R 을 보낸다. 이렇게 서로 다른 페이지를 보내게 되면 앱이 동작하기 전에(path가 변하고 리로드를 했을 때) 서버에서 전혀 다른 동작을 하게끔 하면 앱이 일관성없어진다. 모든 URL에 대해서 일관성있게 동작하게 하기 위해서는 서버가 모든 path로 진입했을 때, 동일한 클라이언트를 내려주도록 설정하는 것이 필요!
  • 모든 path 앞의 basename을 지정할 수 있음.
    ex) basename="/ko" test.com/ko/users 와 test.com/en/users
  • forceRefresh로, 페이지 이동 시 리프레시할 것인지 지정할 수 있음.

Switch
여러 Route 중 매치되는 Route 위에서부터 하나 선택하여 렌더링함.(원래는 위에서 아래로 매칭되는 것을 모두 렌더링하는 것인데, Switch는 매칭되는 것 중 가장 위의 것을 렌더링함.)
매칭되는 Route가 없으면 아무것도 보여주지 않음.
fallback용으로 404 Not Found Page를 추가함.<Route components={404 Not Found Page}>
path="/"의 경우 모든 path에 매칭되므로 exact 키워드를 추가하거나 가장 아래로 내림

Route

  • path와 컴포넌트를 매칭함.
  • 매칭되는 컴포넌트는 children<Route path='/users'> <UsersPage></Route>으로 넣어주거나 component prop으로 넘김. <Route component={UserPage} path='/users'/>
  • exact 키워드로 정확하게 매칭하는 path를 설정함. <Route exact path='/register'><Register></Route>
    exact를 설정하지 않으면 path가 Route path='/register'이고 컴포넌트 중 '/'가 가장 위에 있는 경우, '/'과 매칭될 수 있음
  • Route로 렌더링 되는 최상위 컴포넌트는 match, location, history를 prop으로 받음.
  • render prop으로, 매칭되었을 때 실제 어떤 컴포넌트를 렌더링할지 통제함

예시)

<Route render={(props)=>{
	if (props.id>=10){
		return Big
	}else{
		return Small}
	}>

props를 받아 id값이 10보다 크거나 같으면 Big 컴포넌트를 렌더링하고, 10보다 작으면 Small 컴포넌트를 렌더링하는 코드

Redirect

Link와 비슷하나, 렌더링되면 to prop으로 지정한 path로 이동함.
Switch 안에서 쓰일 경우, from, to를 받아 이동하게 만듦.
ex) <Redirect from="/" to="/login" />

if (!users){
  //users가 없으면 Redirect
  return (
    <Redirect to='/abc'/>)
  return ()
if(!users){
  history.push('/abc')
}
return (
<div></div>
)

Redirect는 첫번째 코드와 같은 방식으로 보통 사용된다.

Link,NavLink

  • to prop을 특정 URL로 받아(to가 속성!), 클릭 시 네비게이션 함.
    <Link to '/users'> To Users </Link>
    To Users라는 텍스트를 가진 anchor tag를 래핑함.
  • anchor tag를 래핑함.
  • NavLink의 경우, 매칭 시 어떤 스타일을 가질지 등의 추가 기능이 있음. <NavLink to='register'> Register</NavLink>
  • to에 가고자 하는 URL 이외에 location object(location={hash,pathname,state}) 나 함수를 받을 수 있음.

useHistory,useLocation,useParams,useRouteMatch
최상위 컴포넌트가 아니더라도 hook으로 react-router 관련 객체에 접근할 수 있음.
history,location,params,match 객체에 접근

profile
뿌링클 치즈맛

0개의 댓글