Next.js는 SSR을 용이하게 해준다.
SSR은 서버단에서 사용자에게 보여줄 페이지를 모두 구성하여 사용자에게 페이지를 보여주는 방식이다. JSP/Servlet의 아키텍처에서 이 방식을 사용했다.
SSR을 사용하면 모든 데이터가 매핑된 서비스 페이지를 클라이언트 즉시 보여줄 수 있다.
서버를 이용해서 페이지를 구성하기 때문에 클라이언트에서 구성하는 CSR(client-side rendering)보다 페이지를 구성하는 속도는 늦어지지만 전체적으로 사용자에게 보여주는 콘텐츠 구성이 완료되는 시점은 빨라진다는 장점이 있다. 더불어 SEO(search engine optimization) 또한 쉽게 구성할 수 있다.
페이지를 이동시키는 기능을 쉽게 구현하기위해 next.js를 설치 후
import {useRouter} from 'next/router';
모듈을 불러와주자.
const router = useRouter();
그리고 useRouter의 함수를 선언 해주고
router.push('/query/${inputs.name}');
를 통해(백쿼터) 다이나믹 라우터를 해보자.
Next.js는 외부 데이터에 의존하는 path를 가지고 정적 페이지를 생성하는데 이를 dynamic URL이라고 한다.
[id]
라는 이름의 페이지를 생성하기 위해[ ]
형태로 이루어진 페이지가 Next.js에서 동적라우팅이 된다. [Kenneth]
란 이름의 폴더를 만들어 이를 페이지로 사용하자.graphql 에서
const {data} = useQuery(postLoadGql, {//setState...
variables: {name: router.query.name}
})
console.log('data', data)
이런식으로 useQuery를 통해서 gql을 보내 원하는 페이지를 동적 라우팅을 하여 가져올때 발생하는 문제점이 있다.
바로 loading이다.
const {data, loading, error} = useQuery(postLoadGql, {//setState...
variables: {name: router.query.name}
})
console.log('data', data)
useQuery
는 함수의 리턴값으로 부터 결과 데이터(data)
뿐만 아니라, 로딩 여부(loading)
와 오류 데이터(error)
까지 한번에 처리할수 있도록 해주는 매우 파워풀한 친구다.
일단 우리가 쿼리를 날릴경우 서버에서 쿼리를 받는다.
그런데 처리가 끝나기전 먼저 우리가 쿼리가 끝나기전 데이터를 달라고 요청할경우?
아무런 데이터도 받지 못했지에 화면에서 보여주는것은 아무것도 없을것이고 오히려 없는 데이터를 참조 하라고 했으니 에러메세지를 미친듯이 뿜어낼것이다.
UseQuery는 간단하게 생각하면 React의 UseState개념이라 생각하면 된다. 상태가 전환 될때마다 동적으로 해당 값들을 리랜더링 하기 때문이다. 하지만 만일 loading
이라는 값을 useQuery에서 처리해준다고 생각하지 못했을경우 어떻게 해야할까?
그럴 때 필요한것은 당연히 if
문일것이다. 하지만 react에선 if
문을 그대로 넣는거 보단 삼항 조건 연산문
을 사용하는것이 좋다
<div>
학교 : {data ? data.fetchProfile.shool : ''}
</div>
만약 가져오려는
data
가 있다면 data의 fetchProfile이란 객체 안의 school이란 키값으로 값을 가져오고 data가 존재하지 않으면 그냥 빈값으로 내줘!
만일 이게 싫으면 &&연산자를 이용해서 간단하게 줄일수있다.
<div>
학교 : {data && data.fetchProfile.shool : ''}
</div>
둘다 true
일경우 true
를 반환한다. 왼쪽 피연산자가 false
면 바로 false
로 평가된다.
false && true; // false
false && false; // false
왼쪽이 true이고 오른쪽도 true라면 오른쪽의 true값을 반환한다.
즉 위의 문장에서 data
가 존재한다면 data.fetchProfile.school
을 반환하라는 간결한 식이라 생각하면 된다.
하지만 useQuery가 지원하는 loading, error를 사용할경우 더욱 보기 간결해지고 이해가 쉬워진다.
useQuery에선 쿼리가 실행 중일 경우 아직 보여줄 데이터가 없는 동안에는 loading
값이 true
이기 때문에
if(loading) return <p>loading</p>
loading중이란 문장을 보여주고
<ProfileHeader>
<HeaderNamePlace>
<GuestImgContentContainer>
<GuestImgContainer>
<GuestImg src='/guest.png'></GuestImg>
</GuestImgContainer>
<GuestContentContainer>
<HeaderNamePlace_Name>{data && data.fetchBoard.writer}</HeaderNamePlace_Name>
......
그것이 아니라면 원래의 페이지를 가져온 data
를 통해 가져온 결과와 같이 보여주면 끝난다.
그리고 만일 에러가 발생했을 경우에는 error
에 왜 이런 오류가 발생했는지 저장되기 때문에 나중에 error를 볼수도 있다는 큰 장점이 있다.
중요한것.
Query를 날린다고 바로 데이터가 도착하는것은 아니다. 서버단에서 쿼리를 실행하고 그것을 처리하고 반환이 되어야 원하는 값을 보여줄수 있다.
const postContentGql = gql`
mutation aaa ($writer: String, $password: String, $title: String!, $contents: String!){
createBoard(createBoardInput: {
writer:$writer
password:$password
title:$title
contents:$contents
})
{
_id
}
}
`;
게시물 등록시 만들어 둔 api를 이용하여 필요한 정보들을 입력받는 form
을 통해 mutation
으로 저장한 후
async function hadleClickOnPost(){
const result = await postRequest({
variables:{...inputs}
});
console.log('This is Mutation Function');
router.push(`/board/${result.data.createBoard._id}`);
}
async & await
를 통해 등록시 비동기 처리로 게시물을 전송할 수 있도록 한다.
여기서 router.push(`/board/${result.data.createBoard._id}`);
를 통해
반환하는 _id
를 Key
값으로 설정하여 해당 키값을 통해 동적 라우팅이 될수 있도록 하자.
const postLoadGql = gql`
query loadingPost($boardId: ID!){
fetchBoard(boardId: $boardId){
writer
title
contents
_id
}
}
`
Query문을 본다면 Query문의 fetchBoard가 요구하는것은 게시물의 Id이기에 $boardId
라는 이름으로 필요한 ID값을 담아주자.
그리고 동적 라우팅을 위해 위에서 []
을 통해 아이디 값이 들어가는 폴더 하나를 만들었으니 그것의 이름으로
$boardId
에 넣어 주어야한다.
const{data,loading,error} = useQuery(postLoadGql, {
variables: {boardId: router.query.id}
})
useQuery
에 실행할 gql
문의 이름을 넣고
gql
의 매개변수의 이름은 boardId
라 명명했으니 boardId
안에 우리가 원하는 id값을 넣어준다. 여기서 중요한것은 router.query.[]
라는것이다. 만일 []
에 올바른 폴더의 이름을 넣지 않는다면 반환받은 값을 원하는 곳으로 동적라우팅을 못하니 반드시 다시 살펴볼것.
이제 여기까지 하면 축하한다. 동적라우팅의 기본적인 개념을 알게되었다.
1.쿼리 실행시 곧바로 결과가 나오는것이 아니다. Loading을 고려해야한다. 서버단에 요청을 했으면 서버는 그것을 처리하는 시간이 존재하는데 이에 걸리는 Loading
을 숙지하자.
2.동적라우팅을 사용한다면 일일히 게시물당 페이지를 만들 필요가 없으니 유지보수 측면에서도 유리하다. 하지만 주의점이 생각보다 좀 많으니 그것을 잘 숙지하자.
3.위의 query
와 mutation
은 이미 정의가 되어있기에 문서를 보고 값만 잘 넣으면 되지만, 값을 넣을때 문서를 해석하는 능력이 필요하다. 처음에는 어려우나 조금 지나면 쉽게 볼 수 있을것이다.