페이지 이동과 관련된 기능을 가진 객체 (Next.js 에서 제공)
router 객체를 이용해서 A페이지에서 B페이지로 이동 => [B페이지로 라우팅 한다]
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('/')
}
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, .../2 로 지정되어 있고, 함수가 실행되면 router.push( ) 내 경로를 따라 해당 폴더의 페이지로 이동 (정적 라우팅 하다)
[BUT] => ex. 게시글이 100개가 넘는다면 각 게시글 페이지마다 폴더를 만들어서 라우팅 처리를 해줘야 함 (비효율적)
동적 라우팅 사용하기
- 위와 같이 라우팅 되는 페이지 하위 항목에
[]로 감싸진 폴더를 새로 만들어 줌 (해당 폴더 이름은 변수명이기 때문에 다른 이름도 사용 가능)- [aaa] 에는
router.push( )로 이동시키고자 하는 경로의 마지막 부분의 값이 담김
ex.
-A페이지에서 router.push(05-04/../123) => [변수 aaa의 값은 123]
-A페이지에서 router.push(05-04/../number) => [변수 aaa의 값은 number]
- 라우팅되어 넘어간 페이지에서
console.log(router)를 통해 query 객체 안의 aaa에 지정한 변수값이 담긴 것을 확인 가능
조회되는 query 내 aaa 변수 값 활용하기
// 글을 올리고 나면 올려진 해당 페이지로 이동
import { useMutation, gql } from "@apollo/client"
import { useRouter } from "next/router"
const CREATE_BOARD = gql` # $로 각각의 타입(type) 지정 [안 넣으면 오류남 (표시용)]
mutation createBoard($writer: String, $title: String, $contents: String) {
# $로 표시하면 변수로 지정됨
createBoard(writer: $writer, title: $title, contents: $contents) {
_id
number
message
}
}
`
// 앞에 붙이는 gql => 백틱으로 감싼 mutation이 gql임을 알리는 키워드
export default function GraphqlMutationPage() {
const router = useRouter()
const [createBoard] = useMutation(CREATE_BOARD)
const onClickSubmit = async () => {
try {
const result = await createBoard({
variables: {
writer: "현섭",
title: "안녕하세요",
contents: "반갑습니다"
}
})
console.log(result) // mutation 함수에 변수로 입력한 값을 포함한 각 데이터가 담김(id, number, message...)
console.log(result.data.createBoard.number) // 이 데이터에서 number(게시글 번호)를 꺼내옴
router.push(`/section05/05-05-dynamic-routing-board-mutation-moved/${result.data.createBoard.number}`)
// 경로 끝에 게시글 번호를 변수로 둬서 등록한 게시글로 바로 이동됨
} catch(error) {
alert(error.message)
}
}
A페이지에서 글을 작성하고 버튼을 누르면 onClickSubmit 함수가 실행되면서 내부의 createBoard 함수도 실행되어 글을 등록하는 API 요청이 전송됨
createBoard 함수를 result에 담아서 응답결과를 조회, 이를 통해 등록된 게시글의 글 번호를 확인하고, 이를 router.push( ) 경로 내 [aaa] 변수 값으로 적용
*결과적으로 게시글을 등록할 때마다 [aaa] 에는 해당 게시글 번호가 담기게 됨
// 조회되는 게시글의 각 항목
import { useQuery, gql } 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 StaticRoutingPage() {
const router = useRouter()
console.log(router)
Number(router.query.number) // 페이지 변수값으로 필요한 정보
const {data} = useQuery(FETCH_BOARD, {
variables: {
number: Number(router.query.number) }
}) // data는 처음에는 없는 값[undefined] (요청 후 응답을 받아서 데이터를 가져와야 data에 그 값이 할당됨)
// 비동기이기 때문에 바로 밑의 return이 동작하고 data가 없을때 data.~~을 불러올 수 없음으로 에러 발생
// 이후 백엔드에서 응답을 받고 data 값이 생기면서 data가 다시 재할당 됨
return (
<div>
<div>2번 게시글 이동이 완료되었습니다</div>
<div>작성자:{data && data?.fetchBoard?.writer}</div> //엔드 연산자 (조건부 렌더링)
<div>제목: {data?.fetchBoard?.title}</div> // optionalChaining (조건부 렌더링)
<div>내용: {data ? data?.fetchBoard?.contents : "로딩중입니다"}</div> //삼항 연산자 (조건부 렌더링)
</div>
)
}
FetchBoard graphql API 코드를 작성하고 조회 시 이용되는 number의 값을 변수로 지정 const {data} =useQuery(FETCH_BOARD, {variables:{}}) 로 조회 API 요청 시 들어가는 number 변수 값으로 [aaa]의 값을 넣도록 지정, 그 응답 결과가 data 라는 변수에 담김
위의 경우, useQuery로 데이터 조회를 요청하고 그 응답결과를 data라는 변수에 담음
API 요청이 비동기로 처리되기에 기다려지지 않고, 바로 return 문이 실행되어 처음에는 data에 값이 할당되지 않음(undefined) => 에러발생
이후 요청에 응답을 받아오면서 data에 값이 할당됨(BUT return 문의 실행은 끝났기에 data 값이 실시간 업데이트 되지는 않음) => 에러 그대로 유지
[문제 해결] => 조건부 렌더링 사용
1. 삼항연산자
2. && 연산자
3. Optional-Chaining
+a) Nullish coalescing
- &&연산자와 반대되는 개념
- data ?? data.fetchProfile
[data 값이 null or undefined 이면 data.fetchProfile 보여줌, 그렇지 않으면 data 보여줌]
or (||) 연산자 VS Nullish coalescing
- or(||) 연산자 => 앞의 data 값이 falsey 할 때 뒤의 값 보여줌(0, null, undefined,"",...)
-Nullish coalescing => 앞의 data 값이 Null, undefined 일 때만 뒤의 값 보여줌
try {
await createBoard({
variables: {
aaa: "훈이",
bbb: "1234",
ccc: "안녕하세요 훈이에요",
ddd: "반갑습니다"
}
})
} catch(error) {
alert(error.message) // 경고창(실패했습니다.) ==> 백엔드 개발자가 보내주는 실패 메시지
} finally {
// 성공, 실패 여부와 상관없이 무조건 마지막에 실행되는 부분
// 필요없다면 생략 가능
}
API 에 대한 요청이 항상 성공하는 것은 아님 (백엔드 컴퓨터 문제, 데이터의 갑작스런 변동 등)
이에 따라 성공 처리, 실패 처리를 나누어서 작업해야 함