라우팅

nn·2022년 4월 15일
0

리액트

목록 보기
8/10

라우팅이란 페이지를 나누는 방법을 말한다.


라우터 셋팅

라우팅을 하기 위해서는 react-router-dom이라는 라이브러리를 사용해야한다.

터미널에 다음과 같이 입력한다.

yarn add react-router-dom@5

라우터 셋팅은 index.js파일에서 할 수있다.
index.js는 App.js에 있는 컴포넌트를 index.html에 넣어주는 역할을 한다.

그러므로 html을 라우팅하기 위해선 index.js의 수정이 필요한 것이다.

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

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

react-router-dom 라이브러리를 임포트하고, BrowserRouter 컴포넌트를 추가했다.

BrowserRouter VS HashRouter
라우팅을 할때 HashRouter를 사용할 수도 있다.

둘의 차이점은 보안상의 이유이다.
BrowserRouter를 사용하면 url은 localhost:3000과 같이 시작된다.

반면 HashRouter은 같은 화면임에도 localhost:3000/#/ 과 같이 #이 붙는다.

이 이유는 브라우저 주소창의 역할때문이다.
Url은 서버에게 페이지를 요청하는 역할을 한다.
HashRouter는 # 뒤로 붙은 모든 것들을 무시하므로 잘못된 주소를 서버로 요청하지 않게 할 수있다.


라우팅하기

아직 메인페이지밖에 없는 App.js를 보자.

todo
1. 메인페이지는 / 로 접속했을때만 보여지게 하자.
2. /detail 로 접속하면 세부페이지로 화면이 바뀌게 하자.

  import { Link, Route, Switch } from 'react-router-dom';

라우팅을 위한 여러 태그를 임포트했다.
라우팅을 위해서 먼저 <Route>태그를 사용하자 .

function App(){
return (
  <div>
...
    <Route path="/"> 
      <div>메인페이지에요</div>
    </Route>
    <Route path="/detail">
      <div>디테일페이지에요</div>
    </Route>
  </div>
)
}

위와 같이 Route 태그에 path 속성을 사용해 주소를 지정할 수 있다.

 <Route path="/어쩌구" component={Card} ></Route> 

<div>대신 컴포넌트를 사용하여 특정 주소로 접속했을 때 컴포넌트가 보여지게 하는 것도 가능하다.

라우터의 특징
사실 라우터는 페이지마다 각각 다른 html을 보여주는 것이 아니다.
단지 html의 내용을 바꾸면서 다른 내용을 보여주는 것이다.

그러므로 다음과 같이 각각의 라우터 태그에 있는 내용들이 한 화면에 나올 수도 있게 되는 것이다.

위와 같은 상황이 발생하는 이유는 / 라는 path가 메인페이지의 / path에도, 디데일페이지의 /detail path에도 포함되어있기 때문이다.

경로가 정확히 일치 할때만 보여지게 하기위해선

<Route exact path="/"> 
<div>메인페이지에요</div> 
</Route> 

위와 같이 exact 속성을 부여해주면 된다.


react-router-dom에서 임포트해온 Link 컴포넌트를 알아보자.

Link태그는 a 태그와 유사한 기능으로 페이지를 이동할 경로를 지정해주는 역할을 한다.

function App(){
return (
  <div>
    <Navbar>
       <Nav.Link> <Link to="/">Home</Link> </Nav.Link>
       <Nav.Link> <Link to="/detail">Detail</Link> </Nav.Link>
    </Navbar> 
    ...
  </div>
)
}

태그의 사용법은 위와 같다.

  1. 페이지 이동을 담당 할 글자를 Link 태그로 감싼다.

  2. to 속성을 사용해 경로를 적어준다.


    useHistory 태그

    useHistory 컴포넌트도 react-router-dom에서 사용할 수 있다.

    useHistroy 태그는 방문기록을 담고있다.
    즉, 뒤로가기와 같은 기능을 구현하고자 할 때 직접 경로를 적지 않고도 사용할 수 있다.

  // 임포트
import { useHistory } from 'react-router-dom';

function Detail(){
  // 방문기록을 저장할 오브젝트 선언.
  let history = useHistory();
  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6 mt-4">
          <h4 className="pt-5">상품명</h4>
          <p>상품설명</p>
          <p>120000</p>
          <button className="btn btn-danger">주문하기</button> 
          <button onClick={()=>{ 
            	history.goBack() 
            }} className="btn btn-danger">뒤로가기</button> 
        </div>
      </div>
  </div>  
  )
};

useHistory 사용 예시를 보자.

위 html은 / 메인페이지에서 /detail 경로를 입력했을 때 나오는 디테일페이지이다.

뒤로가기 버튼을 클릭하면 뒤로 가는 함수가 실행되도록 하였다.
history 변수는 임포트한 useHistory를 통해 방문한 기록이 저장되어있다.

goBack() 함수를 작동시켜 경로를 적지 않고도 바로 직전의 페이지로 이동할 수 있다.


Switch 태그

Switch 태그는 Routh 태그의 path에 중복되는 것들이 있어도 하나의 Routh 태그만 보여준다.

function App(){
return (
  <div>
    <나머지HTML/>
    <Route exact path="/">
      어쩌구
    </Route>
    <Route path="/detail">
      <Detail/>
    </Route>
    <Route path="/:id">
      <div>새로 만든 route입니다</div>
    </Route>
  </div>
)
}

/:id 는 URL 파라메터를 뜻하는 것으로 / 뒤에 문자가 있으면 해당 Route를 보여주라는 의미이다.

그러므로 /detail 경로로 이동하면, /detail과 /:id 두가지 Route가 보여질 것이다.

이 때 하나의 Routh가 보여지게 하기위해선 아래처럼 모든 Routh 태그를 Switch로 감싸주면 된다.

function App(){
return (
 <div>
   <나머지HTML/>
   <Switch>
     <Route exact path="/">
       어쩌구
     </Route>
     <Route path="/detail">
       <Detail/>
     </Route>
     <Route path="/:id">
       <div>새로 만든 route입니다</div>
     </Route>
   </Switch>
 </div>
)
}

URL 파라메터로 상세페이지 여러개 만들기

일단 URL 주소부터 생각해보자.
3개의 상품이 있고 다음 경로로 이동했을 때 각각의 상세 페이지가 나오게 해야한다.

/detail/0으로 접속하면 0번째 상품의 상세페이지
/detail/1으로 접속하면 1번째 상품의 상세페이지
/detail/2으로 접속하면 2번째 상품의 상세페이지
function App(){
return (
 <div>
   ...
     <Route path="/detail/:id">
       <Detail shoes={shoes}/>
     </Route>
 </div>
)
}

위에서 언급했지만, : 콜론기호는 :id 자리에 어느 문자가 오던간에 <Detail> 컴포넌트를 보여달라는 의미이다.

  • id라는 부분은 함수명처럼 자유롭게 작성하면 된다.
  • 파라메터는 여러개를 추가 할 수 있다.
    ex) /detail/:id/:name
import React from 'react';
  // useParams추가
import { useHistory, useParams } from 'react-router-dom';
  
function Detail(props){
  // useParams 변수에 저장
  let { id } = useParams();
  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
        </div>
        <div className="col-md-6 mt-4">
          <h4 className="pt-5">	
            {props.shoes[id].title}</h4>
          <p>{props.shoes[id].content}</p>
          <p>{props.shoes[id].price}</p>
          <button className="btn btn-danger">주문하기</button> 
        </div>
      </div>
  </div>  
  )
};
export default Detail 

Detail.js를 보자.
useParams를 추가했다.
useParams는 URL에 적힌 모든 파라메터를 {파라메터1, 파라메터2,,}와같이 저장해주는 함수이다.

즉 {id}에는 detail/:id에서 id로 적힌 문자를 파라메터로 가져오게 되는 것이다.


추가

만약 상품의 순서가 바뀌면 어떻게 할까?
0번 경로로 들어가면 언제나 같은 상품이 나와야하는데 상품의 정렬이 바뀌면 0번째 상품이 3번째에 있던 상품이 올 수도 있다.

그러므로 데이터 바인딩을 할때 상품의 순서가 아닌 상품의 id와 같이 고유한 번호의 숫자를 파라미터로 사용하여 언제나 같은 상품이 보이도록 하면 된다.

예시를 보자.

{
    id : 0,
    title : "White and Black",
    content : "Born in France",
    price : 120000,
    img : "https://codingapple1.github.io/shop/shoes1.jpg"
  },

  {
    id : 1,
    title : "Red Knit",
    content : "Born in Seoul",
    price : 110000,
    img :  "https://codingapple1.github.io/shop/shoes2.jpg"
  },

  {
    id : 2,
    title : "Grey Yordan",
    content : "Born in the States",
    price : 130000,
    img : "https://codingapple1.github.io/shop/shoes3.jpg"
  }

위 상품 데이터에는 상품의 고유번호인 id가 있다.
즉 상품의 순서가 아닌 고유번호를 /:id에 넣어주면 될 것이다.

자바스크립트 ES6에있는 find()라는 문법을 사용해 보았다.
filer()함수 혹은 반복문을 사용해도 상관없다.

import React from 'react';
import { useHistory, useParams } from 'react-router-dom';

function Detail(props){

let { id } = useParams();
let 찾은상품 = props.shoes.find(function(상품){
  return 상품.id == id
});

return (
  <div className="container">
    <div className="row">
      <div className="col-md-6">
        <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
      </div>
      <div className="col-md-6 mt-4">
        <h4 className="pt-5">{찾은상품.title}</h4>
        <p>{찾은상품.content}</p>
        <p>{찾은상품.price}</p>
        <button className="btn btn-danger">주문하기</button> 
      </div>
    </div>
</div>  
)
};

export default Detail 

find()는 Array에서 원하는 자료를 찾고 싶을 때 사용한다.

  1. find()는 array뒤에 위치하며 콜백함수를 작성해주어야한다.

  2. 콜백함수는 array안에있는 하나하나의 데이터를 의미한다.
    즉, 각각의 상품정보들이 들어가 있다.

  3. return엔 조건식을 넣을 수 있다.
    상품의 id가 :/id 파라미터로 붙은 문자와 같은 상품을 변수에 저장해준다.

    프론트에서 모든 데이터를 다루기 때문에 반복문 스러운 find()와 같은 함수를 사용하지만 실제론 Ajax를 통해 서버로 id : 0 인 상품데이터를 요청하는 것이 일반적이다.

    이런 경우 find대신 ajax를 요청하는 코드를 작성하고 응답받은 데이터를 {}안에 넣어주기만 하면된다.

profile
내가 될 거라고 했잖아

0개의 댓글

관련 채용 정보