5일차 라우팅, 리렌더링

osdsoonhyun·2023년 2월 10일
0

코드캠프

목록 보기
3/22
  1. 페이지를 이동하기 -> Routing
  2. 게시물을 가져오기(조회) -> Apollo-Client / Query
  3. API 요청시 에러가 발생(에러처리) -> try-catch

포트폴리오 리뷰

graphql mutation, query -> 모두 쿼리문이라고 부른다.

import React from 'react';
import { gql, useMutation } from '@apollo/client';

const CREATE_BOARD = gql`
  mutation {
    createBoard(writer: "승현", title: "카카오", contents: "카카오초콜릿") {
      _id , number, message
    }
  }
`;

$ 은 변수를 나타낸다. variables$를 의미한다.

또한 shorthand-property라고 객체에서 key와 value의 값이 같으면 value를 생략할 수 있다.

Routing

페이지 이동을 routing이라고 하고 페이지를 이동시키는 도구를 router라고 한다.

Router

Router 기능

  • 페이지 이동
  • 현재 주소 확인
  • 주소 관련 기능들
  1. 페이지 이동
const router = useRouter();

router.push("이동할 페이지"); // http://localhost:3000은 자동으로 붙기 때문에 적지 않아도 된다.

yarn dev 명령 하는 위치는 명령어가 적용되어 있는 공간인 package.json파일에서 "scripts"가 실행 명령어를 가지고 있기 때문에 package.json 파일이 있는 파일 공간에서 실행해주어야 한다.

  1. 게시물을 가져오기(조회) -> Apollo-Client / Query

...
const [나의함수] = useMutation(CREATE_BOARD);

const onClickSubmit = async () => {
  const result = await 나의함수({
    variables: {
      //variables $역할을 해준다.
      writer: writer,
      title: title,
      contents: contents,
    },
  });
  console.log(result);
  alert(result.data.createBoard.message);
};
...

useMutation을 동적으로 사용하기 위해 useMutation을 저장한 함수에 함수를 실행할 때 변수를 할당받아 동적으로 사용했다.

const FETCH_BOARD = gql`
  query {
    fetchBoard(number: 1) {
      writer
      title
      contents
    }
  }
`;

...
const { data } = useQuery(FETCH_BOARD);
...

위 코드는 하드코딩 했을 때 useQuery 사용

const FETCH_BOARD = gql`
  query fetchBoard($number: Int){  
//  query fetchBoard(변수명: 변수의 타입){ =>playground에서 확인
    fetchBoard(number: $number) {  //  fetchBoard(number: 변수명) {
      writer
      title
      contents
    }
  }
`;

...
const { data } = useQuery(FETCH_BOARD, {
  variables: { number: 1 },
});
...
return <>{data.fetchBoard.writer}</>

위 코드는 동적으로 할당할 때 useQuery 사용, 이때 쿼리문에서 데이터 타입을 기재해줘야 한다.

useMutation의 경우 함수를 정의하고 실행할 때에 사용하였다. useQuery의 경우도 실행할 때에 동적으로 할당해야 한다. query는 페이지 이동되면 자동으로 실행되기 때문에 useQuery의 두 번째 매개변수로 넣어준다.
두 번째 매개변수에 variables를 할당한다.

이렇게 출력을 해보면 FETCH_BOARD가 undefined가 되는데 그 이유는 API를 받아오는 useQuery가 비동기적으로 실행해서이다. API 요청과 동시에 화면에 뿌려주는 return 값이 실행되므로 fetchBoard에 에러가 발생한다.

일단 처음에 한번 실행이 되고 이때는 백엔드에 요청을 보냈으므로 값이 undefined가 나온다.
그렇다면 mutation에서와 같이 async/await 하면 되지 않나?
그렇게 동기적으로 실행하면 백엔드에서 응답할 때까지 화면에 보여지는 값이 없으므로 그렇게 하지 않는다. 더 빠르게 하기 위해 비동기적으로 실행을 하면서 조건부렌더링을 사용하였다.

조건부렌더링

  • && 연산자(앤드앤드)
  • 삼항연산자
  • 옵셔널 체이닝

'앞에 것이 있으면 뒤에 것을 보여줘!' 라고 데이터가 있을 때 보여지도록 하는 일종의 조건문, 코드 양을 주는 장점이 있다.

return (
    <>
      <div>1번 게시물로 이동이 완료되었습니다!!</div>;
      <div>작성자: {data && data.fetchBoard.writer}</div>
      <div>제목: {data && data.fetchBoard.title}</div>
      <div>내용: {data && data.fetchBoard.contents}</div>
    </>
  );
}

동기로 실행했을때보다 훨씬 효율적이다. 동기로 실행하게 되면 위에서 데이터를 받아올 때까지 기다렸다가 보여줘야하기 때문에 느리지만, 조건부렌더링을 사용하여 비동기적으로 실행하게 되면 일단 하드코딩된 부분이 바로 보여지고 데이터가 들어오면 보여지도록하였다.

  1. 삼항연산자
  2. && 연산자 (앤드앤드 연산자)
  3. 옵셔널 체이닝 -> 가장 많이 사용
<div>제목: {data ? data.fetchBoard.title : "로딩중"}</div>
<div>제목: {data && data.fetchBoard.title}</div>
<div>제목: {data?.fetchBoard.title}</div>

사람들은 1초만 빈화면이 떠도 느리다고 생각하고 2초가 넘어가면 화면을 끄는, 이탈율이 높아진다. 따라서 동적으로 받아오는 데이터는 나중에 보이더라도 비동기적으로 실행하여 보여줄 것은 보여주고 나중에 가져온 데이터를 화면에 렌더링 시키는 것이 UX으로 좋다.

페이지 이동 방식(라우팅 종류)

정적 라우팅

직접 폴더를 따로따로 만드는 방식

동적 라우팅

그때 그때 동적으로 페이지를 생성하는 방식

[] 를 사용하게 되면 대괄호 안에 있는 폴더로 만들어진다.
밑의 그림을 보면 1이 aaa에 들어가게 되고 [aaa] 안에 있는 폴더인 index.js에 접속이 되고 접속된 aaa에서 useRouter를 사용하여 변수를 꺼내 사용할 수 있고 변수는 우리가 사용한 변수 1인 들어간다. 또한 useRouter() 함수를 이용해 이동된 페이지에서 라우터 객체내에 있는 정보를 조회할 수 있는 방법이 있었다.

router.query

게시글 등록 -> 상세페이지 이동 프로세스

router.query를 활용하여 라우터 객체를 조회할 수 있다. 게시물ID 또는 게시물 번호를 가져올 수 있었습니다.
또한, 가져온 게시물ID와 게시물번호를 활용하여 데이터를 조회해보았다.

게시글 등록 상세페이지에서 useMutation의 함수를 요청하여 등록을 요청한다.
등록 요청에 대한 return 값으로 graphql에서는 원하는 값만 받을 수 있는데 게시글이 등록된 번호를 받아온다.
함수를 요청하면 백엔드에 요청이 들어가고 DB에 데이터가 쌓이고 그 결과로 해당 게시글의 번호를 받는다.
router.push("이동할 페이지"+게시글 번호)를 사용하여 상세페이지로 이동한다.
+를 이용하면 가독성이 좋지 않기 때문에 템플릿 리터럴을 활용하여 가독성을 높인다.

특정 게시물 조회

useQuery()의 사용 방법은 useMutation()과 거의 동일하지만 몇가지 차이점이 있다.

  1. 변수명의 지정
    useMutation()은 실행함수 이름을 적어줄 때 내 마음대로 변수명 선언이 가능했죠?
    하지만 useQuery()를 사용할 때에는 중괄호 안에 data라는 변수명이 지정되어있기때문에 해당 변수명으로만 받아와야 했습니다.
    정리하면, useMutation을 실행할 변수명은 내맘대로 지정이 가능하지만, useQuery()는 불가능 하다는 점 알고계시면 될 것 같습니다.

  2. 통신 방식
    useMutation과 useQuery는 모두 비동기 방식은 맞다. 사용될 때 useMutation은 async/await를 사용하여 비동기를 동기적으로 처리하였지만 useQuery는 페이지가 그려질(렌더링) 때 자동으로 요청이 날아간다.
    요청에 대한 응답을 받기 전에 먼저 html을 그려주고, data가 받아지면 내용을 채워 준다는 특징이 있다. 이로 인해 데이터가 들어오기 전에 데이터를 뿌려주는 명령이 실행되어 에러가 발생한다.
    그러나 useQuery는 async/await로 동기적으로 처리하지 않고 더 빠르게 처리하기 위해 비동기적으로 처리하고 대신 조건부 렌더링을 통해 보여질 것은 보여주고 데이터는 들어오면 뿌려주도록 하였다.

try-catch 에러 처리

API 요청시 백엔드에서 데이터베이스에 등록을 하고 그리고 등록 결과가 날아오게 되어 본다. 그 중간에 백엔드나, 데이터베이스에서 에러를 줄 수 있다. 따라서 try-catch를 통해 에러를 처리해야 한다.
try에 있는 내용을 시도하다가 실패하면, 아랫줄은 모두 무시하고 catch가 실행됨

소소한 꿀팁

렌더링 : 화면에 그려줘
조건부 렌더링 : 조건에 맞게 화면에 그려줘

0개의 댓글