[TIL] 22.11.04 - Routing, 정적/동적 라우팅, Apollo-Client로 Query, 조건부 렌더링, try-catch

nana·2022년 11월 4일
0

TIL

목록 보기
21/50
post-thumbnail

Routing

라우터(router) 객체란, 페이지 이동 및 주소와 관련된 기능을 가지고 있는 객체이다.

router를 사용해서 A 페이지에서 B 페이지로 이동할 때, "B 페이지로 라우팅한다" 고 말한다.

next.js에서 useRouter를 제공해준다.

import Router from 'next/router'

export default function Routing() {
    const handleClickPathname = () => {
        const pathname = Router.pathname
        alert(pathname)
    }

    const handleClickAsPath = () => {
        const asPath = Router.asPath
        alert(asPath)
    }

    const handleClickBack = () => {
        Router.back()
    }

    const handleClickPush = () => {
        Router.push('/이동할 페이지')        // https는 제외한다.
    }

    const handleClickReload = () => {
        Router.reload()
    }

    const handleClickReplace = () => {
        Router.replace('/')
    }


    return (
      <>
        <button onClick={handleClickPathname}>현재 위치 주소: Router.pathname</button><br/>
        <button onClick={handleClickAsPath}>현재 위치 주소: Router.asPath</button><br/>
        <button onClick={handleClickBack}>뒤로가기 버튼: Router.back()</button><br/>
        <button onClick={handleClickPush}>현재 페이지에서, 다른 페이지로 이동: Router.push()</button><br/>
        <button onClick={handleClickReload}>새로고침: Router.reload()</button><br/>
        <button onClick={handleClickReplace}>현재 페이지 삭제 후, 다른 페이지로 이동: Router.replace()</button><br/>
      </>
    )
  }

정적 라우팅, 동적 라우팅

1) 정적 라우팅 (static routing)

/boards 페이지는 누가 언제 접속해도 항상 게시판 등록 페이지가 나타난다.

이러한 페이지로 이동하는 것을 "정적 라우팅한다"고 한다.


2) 동적 라우팅 (dynammic routing)

반면 게시판 상세보기와 같은 경우, 글 번호에 따라서 주소가 변경된다.

하지만, 이러한 경우에는 게시글이 100개, 1000개가 넘어가게 되면 각각의 글 번호에 따라 페이지를 100개, 1000개씩 만들어 정적라우팅을 해주기는 어렵기 때문에 이러한 라우팅을 효과적으로 처리하기 위해서 동적 라우팅을 사용한다.

/board/11번 게시글 상세보기 페이지
/board/22번 게시글 상세보기 페이지
/board/33번 게시글 상세보기 페이지

이러한 페이지로 이동하는 것을 "동적 라우팅한다" 고 한다.


next.js에서는 동적 라우팅을 제공해주는데,
위의 폴더 구조와 같이 보여주고자 하는 폴더 이름의 하위 폴더로 [boardId] 폴더를 만들어 준 후,
이 안에 index.js 파일을 만들어주면 동적 라우팅을 사용할 수 있다.

대괄호로 감싸준 폴더를 만들어주면 이동해주고자 하는 페이지 번호, 혹은 게시글 번호가 대괄호 안에 쓰여진 변수명에 담겨져 그 변수 안에 있는 데이터를 꺼내 조회할 수 있다.

실제로 router.query = { boardId: 1 } 이런 형식으로 들어가게 되면서 자동으로 게시글 번호를 꺼내올 수 있다.

📌 이때, 주소는 무조건 문자이다
-> 문자를 숫자로 변환해준다.


Apollo-Client / Query

게시물 조회시 useQuery를 사용한다.

const {data} = useQuery()  // {} 안에 정해진 변수 data를 넣어준다. 

예시) fetchBoard

import { gql, useQuery } from "@apollo/client";
import { useRouter } from "next/router";

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

export default function StaticRoutedPage() {
  const router = useRouter();

  const { data } = useQuery(FETCH_BOARD, {
    variables: { number: Number(router.query.number) },	// 데이터 타입을 숫자로 변환해준다.
  }); // 비동기 방식

  console.log("============");
  console.log(data); // undefined (비동기 방식이기 때문)
  console.log("============");

  return (
    <>
      <div>{router.query.number}번 게시글로 이동이 완료되었습니다</div>
      <div>작성자: {data?.fetchBoard.writer}</div>	// 옵셔널 체이닝
      <div>제목: {data?.fetchBoard.title}</div>
      <div>내용: {data?.fetchBoard.contents}</div>
    </>
  );
}

비동기 통신과 조건부렌더링

javascript는 작성된 코드가 상단에서부터 순서대로 실행되기 때문에,
데이터를 요청하고 응답을 받아오는 동안 화면에 그려질 데이터의 내용이 undefined이므로
첫 화면이 그려지는 시기에 데이터를 불러오면서 에러가 발생한다.

이 부분이 효율적으로 실행되기 위해서 화면을 미리 그려놓고 데이터를 그려주기 위해서 조건부렌더링을 사용한다.

조건부 렌더링에는 &&연산자, 삼항연산자, 옵셔널체이닝이 있다.

1) 삼항 연산자

data는 동기적으로 받아와야하는 데이터이다.
그러나 데이터가 오기 전에 이미 return 부분에서 rendering을 해주고 있기 때문에,
삼항 연산자를 사용하여 데이터가 있을 때, 없을 때를 모두 적어준다.

data ? data.fetchProfile : undefined

2) && 연산자

data && data.fetchProfile

&&연산자는 데이터가 없을 경우 자동으로 undefined를 반환한다.
데이터가 없을 때 따로 div를 쓸 필요가 없으면 else 부분을 쓸 필요가 없다.

&&연산자는 앞의 값이 참일 경우에만 뒤의 값을 보여주었는데, 반대로 앞의 값이 거짓일때 뒤의 값을 보여주는 경우도 있다.
Nullish coalescing 연산자라 불린다.

??연산자는 앞의 값이 빈 값이면 뒤의 값을 보여주며 ||연산자는 앞의 값이 거짓(false)일 경우 뒤의 값을 보여준다.

data ?? data.fetchProfile

data || data.fetchProfile

3) 옵셔널 체이닝 (Optional-Chaining)

optional-chaing이란, 기존의 && 연산자를 쓰면서 길어졌던 코드를 더욱 간결하게 사용하는 연산자이다.

optional-chaing은 ES2020에서 나온 최신 문법이다.

data?.fetchProfile

optional-Chaining은 ? 연산자 앞 객체의 참조가 undefined || null 이라면 undefined를 리턴해준다.

위에 있는 삼항연산자, && 연산자와 똑같은 기능을하지만, 훨씬 간단해졌다.


조건부 렌더링 비교

data ? data.fetchProfile : undefined	// 삼항 연산자
data && data.fetchProfile				// && 연산자
data?.fetchProfile						// 옵셔널 체이닝

try-catch

graphql로 mutation시 항상 성공하는 것은 아니다.

Backend 컴퓨터에 문제가 발생할 수도 있고, 내가 수정하려는 게시물이 갑자기 삭제가 되는 바람에 수정에 문제가 발생하는 등 여러가지 실패 가능성이 있다.

따라서, API 요청시 성공에 대한 처리, 실패에 대한 처리를 나누어 작업해야 한다.

try {
    await createBoard({
       variables: {
            aaa: "훈이",
            bbb: "1234",
            ccc: "안녕하세요 훈이에요",
            ddd: "반갑습니다"
        }
    })
} catch(error) {
		alert(error.message)     // 백엔드 개발자가 보내주는 실패 메시지
} finally {
	// 성공, 실패 여부와 상관없이 무조건 마지막에 실행되는 부분
	// 필요없다면 생략 가능
}

📌 shorthand property
shorthand property는 객체를 정의할 때 객체의 key값과 value 값이 같으면, 각각 표기하지 않고 한 번만 표기하는 것을 의미한다.

const result = await createUseditem({
        variables: {
          createUseditemInput: {
            name         // name: name
            remarks      // remarks: remarks
            contents.    // contents: contents
            },
          },
        },
      });
profile
프론트엔드 개발자 도전기

0개의 댓글