React Router(리액트 라우터) - 2

Jonghan·2020년 4월 24일
3

react

목록 보기
3/5

리액트 라우터 2탄

저번글이 좀 길어질 것 같아 2부로 나눠서 쓰는데.. 이번글도 상당히 길어질 것 같다.
아마 3탄까지 나올것 같음..

URL Parameters and QueryString

URL로 우리는 가끔 유동적인 값을 전달할때가 있다.
예를 들면,
localhost:3000/user라는 URL이 있다고 가정해보자.
우리는 pkbird라는 유저에 대한 정보가 보고싶다.

하지만 그냥 localhost:3000/user라고 치면 유저 전체에 대한 정보가 나올 뿐, pkbird라는 유저의 정보가 나오지 않는다. 물론 유저 전체에 대한 정보를 뒤지다보면 나오긴 하겠지만, 그건 우리가 원하는 것이 아니고, 찾고나서 세부 정보를 보기 위해 클릭한 경우 어떤 방식으로 그 사람의 세부 정보를 가져올 수 있을까?

말이 길어졌는데 답은 그냥 간단하다.
localhost:3000/user/pkbird이런식으로 user라는 URL 뒤편에 id를 집어넣는 것이다. 이것을 파라미터라고 하는데 흔히 파라미터는 특정 아이디 혹은 이름을 사용해 뭔가를 조회할 때 쓴다. 예를 들면 위에 유저 정보 조회처럼 말이다.

localhost:3000/about?all=true와 같은 방식은 쿼리라고 부르는데, 보통 다른데선 쿼리스트링이라고 부르기도 한다. 근데 그냥 길게 쓰기 귀찮으니 쿼리라고 부르겠다. 이 쿼리 같은 건 어떤 키워드를 검색하거나, 페이지에 옵션을 전달할 때 사용한다.

URL Parameter 실습

저번시간에 쓰던 코드를 이어서 사용해보겠다.
User.js파일을 만들어주고 다음과 같이 코드를 작성해보자.

import React from 'react';

const users = {
  pkbird: {
    name: '비빔면',
    age: 25,
  },
  fahrenheit: {
    name: '화씨',
    age: 12,
  },
};
const User = ({ match }) => {
  const { userid } = match.params;
  const user = users[userid];
  if (!user) return null;

  return (
    <div>
      <b>{user.name}</b> ({user.age})
    </div>
  );
};

export default User;

여기서 살펴볼 것은 크게 세가지인데,
첫번째로는
const { userid } = match.params; 이부분이다.
match를 User 컴포넌트를 렌더링할때 불러오는데, 이게 바로 parameter에 대한 정보를 갖고 있는 객체이다.

두번째로는
const user = users[userid];
이 부분인데, 자바스크립트에 대한 이해가 필요한 부분이다. users[pkbird]를 할 경우, 마치 배열같이 사용하지만 이는 객체이다. 따라서, pkbird 프로퍼티가 갖는 내용에 대한 정보를 불러온다.

세번째로는
if (!user) return null;
이 부분이다. user가 없을 경우라는건, 파라미터가 잘못 들어왔거나, 아예 들어오지 않았을 경우이다.
return null을 해줌으로써 아예 아무것도 화면에 출력하지 않도록 하는 부분이다.

이제 여기까지 이해가 되었으면, App.js도 좀 바꿔주자.

(... 중략)
import User from './User';

function App() {
  return (
    <div>
      <ul>
        (... 중략)
        <li>
          <Link to="/user">조회</Link>
        </li>
      </ul>
      (... 중략)
      <Route path="/user/:userid" component={User} />
    </div>
  );
}

export default App;

기존의 코드에서 좀 길어질 수 있는 부분을 제외시켰다. 스크롤이 많이 내려가면 가독성이 떨어지더라고.
특히 벨로그가 예전과 다르게 업데이트 되면서 전체적으로 폰트가 너무 많이 커진 느낌이 든다.
그래서 가독성이 좀 떨어지게 됐는데 그 부분이 개인적으로 좀 아쉽다.

아무튼, 이렇게 코드를 작성하게 되면 눈에 띄는 부분이 있을텐데,
<Route path="/user/:userid" component={User} /> 이 부분에서 :userid 부분이다.
:오타냈네 ㅋㅋ 라고 생각하시는 분이 계실지 모르겠으나(물론 없겠..?) 저 부분은 유동적인 부분이다.
무슨말이냐면, /user/pkbird라고 URL을 적어서 전달하게 되면 위에 나왔던 match부분에 다음과 같이 값이 입력된다.
match.params.userid = pkbird라고 말이다.

즉 변수의 이름이라고 보면 되겠다. 실제로 URL을 통해서 넣어주는건 변수에 넣을 값이고... 쓰면서 좀 알아들을 수 있을까 고민이 되는데 내 설명이 좀 부족해서..

const userid = 'pkbird' 대충 이런느낌이라고 보시면 될 것 같다. 저 부분은 fahrenheit도 되고 아무튼 모든지 들어갈 수 있다. 그 상태에서 User 컴포넌트가 생성이 되면 컴포넌트 측에서 match라는 props를 받아 그 값을 확인할 수 있다.

결과적으로
localhost:3000/user/pkbird 입력시에, User 컴포넌트에서 match.params.useridpkbird가 되고, users라는 객체로부터 pkbird 프로퍼티가 있는지 확인 후 있으면 이름(나이)가 적혀있는 컴포넌트를 렌더링해주고, 없으면 그냥 null을 리턴해준다.

괜히 다들 이해했는데 나혼자 이해 못하실까봐 노심초사해서 긴 글을 써서 가독성을 떨어뜨리기보단 다들 이해했다고 생각하고 넘기는게 맞다고 생각되어 넘기도록 하겠다.


URLfahrenheit로 했을때 결과값이 잘 출력되는 모습을 볼 수 있다.

pkbird역시 마찬가지

조회버튼을 누르자, 아이디가 들어가지 않았기 때문에 아무것도 출력되지 않는다.

URL Query 실습

URL parametermatch.params로 받아왔다면, URL Querylocation.search를 통해 받아올 수 있다.
왜 굳이 props를 둘로 나눠서 번거롭게 하는건지는 잘 모르겠지만, 나보다 똑똑하신 양반들이 만들었으니 불만가져봤자,

그럼 니가 만들든가.

소리 들으면 할 말이 없기 때문에, 그냥 받아들였다.

const User = ({ match, location }) => {
  const { userid } = match.params;
  const queryData = location.search;
  const user = users[userid];
  if (!user) return null;
  return (
    <div>
      <b>{user.name}</b> ({user.age})
      {queryData && <p>{queryData}</p>}
    </div>
  );
};

유저 부분을 조금 건드려서, location.search값을 받아올 수 있는 코드를 짜보자. queryData라는 변수에 넣고, 문제가 없으면 <p></p> 태그로 출력해준다.

http://localhost:3000/user/pkbird?query=string
위와 같은 URL을 넣게되면, pkbird는 파라미터로, query=string은 쿼리로 받아들여오게 된다.

따라서 결과값은 다음과 같다.

문제는 일단 데이터를 받아오면 ?는 아무런 쓸모가 없다. 그리고 진짜로 string으로 받아오기 때문에 쓰기가 다소 애매하다.

이럴때는 yarn add qs를 통해 쿼리 스트링을 객체로 변환해주는 라이브러리를 사용하면 된다.

  const queryData = qs.parse(location.search, { ignoreQueryPrefix: true });
  console.log(queryData);

ignoreQueryPrefix: true라는 객체를 뒤에 넣어주게 되는데 쿼리스트링 앞에 붙는 ?를 빼고 객체로 변환해준다.

queryData를 위와같이 바꿔준다음에 console.log를 사용해 결과값을 출력해본다. 그리고 위에 적었던 {queryData && <p>{queryData}</p>} 이 부분은 지워주자.

그럼 렌더링 후에 콘솔창에 보면 다음과 같은 결과를 볼 수 있다.

queryData가 객체가 되었고, 프로퍼티로는 query: 'string'을 가지고 있는 모습을 볼 수 있다.

따라서 키와 값을 분리해서 사용할 수 있게 되었다.

여기서 주의할 점이 한가지 있다.

true와 숫자

show=true와 같이 쿼리스트링에 true를 넣거나, user?detail=1과 같이 숫자를 넣게되는 경우 둘다 해당되는 얘긴데, location.search로 컴포넌트에서 쿼리스트링에 대한 값을 받을 경우에 문자열로 받게된다. 즉 true, 1로 받게 된다는 얘기다.

const query = qs(location.search, { ignoreQueryPrefix: true });
if(query.show){
  // query.show === 'true'이지
  // query.show === true가 아니다!!
}

이 부분을 꼭 유의해서 코드를 작성해야 한다.

숫자도 마찬가지로, === '1' 이런식으로 문자열과 비교해주거나 parseInt()를 사용하여 문자열을 숫자로 바꿔준 다음에 비교를 한다거나 둘 중에 필요한 방식을 사용하면 된다.

profile
열정적으로 살고 싶다.

0개의 댓글