next.js와 Apollo GraphQL을 이용한 웹 서비스 개발하기(2)
지난 시간에 Next App을 새로 생성하고 Apollo-server api를 통해 GraphQL 방식으로 데이터를 전달받는 초기 세팅을 완료했습니다.
이번에는 페이지를 routing하고 uri에 따라 동적으로 페이지를 rendering해보도록 하겠습니다.
Github Source Code
먼저 npm 스크립트를 통해 생성된 next 앱의 root페이지(‘/’)를 수정하겠습니다.
root 페이지에서는 유저들의 정보를 보여주는 users페이지(‘/users’)로 이동할 수 있는 링크를 생성해주고 그 외에 불필요한 코드를 모두 제거했습니다.
(css 코드는 이번 포스팅 내용의 주제가 아니기 때문에 생략하였습니다)
<h1> tag로 작성된 제목 아래에는 Show all users라는 링크(Link)를 생성하고, 해당 링크는 ‘/users’ 경로로 연결합니다.
코드를 수정한 후 서버를 실행하고 http://loacalhost:3000 도메인으로 접속하면 다음과 같이 수정된 페이지를 확인할 수 있습니다.
여기서 링크를 클릭하면 브라우저가 성공적으로 http://loacalhost:3000/users 경로로 routing되고 아직은 users 페이지를 생성하지 않았기 때문에 status code 404를 반환되는 모습을 확인할 수 있습니다.
링크를 생성했으니 이제 링크가 연결될 users 페이지를 만들어보겠습니다.
nextjs에서는 pages directory안의 파일 구조에 따라 웹 페이지를 생성해주기 때문에 users domain에 연결될 페이지는 ‘pages/users/index.js’의 경로로 파일을 생성해야 합니다.
생성된 파일에서는 각 user들의 상세페이지로 이동할 수 있는 링크를 리스트로 보여주려고 합니다.
지난 시간에 만들었던 fetch 코드를 ‘users/index.js’파일로 옮기고, 응답받은 users 데이터를 state에 저장하여 동적으로 rendering해줍니다.
지난 포스팅에서 ‘Nextjs’라는 name을 유일한 키값으로 가진 1개의 user만 배열로 리턴해주던 graphQL 쿼리 역시 여러개를 다양한 key값으로 리턴해주기 위해 일부 수정합니다.
‘pages/api/data.json’파일을 생성하고 7개의 users 데이터를 작성했고, user의 스키마는 ‘name’외에 ‘id’와 ‘color’값을 추가했습니다.
// pages/api/graphql.js...type User { id: String name: String color: String}...
이제 users 페이지는 useEffect에 따라 처음 렌더링하면서 users data를 graphQL format으로 fetch해오고, ‘/users/${id}’ 경로로 링크가 연결된 list를 생성합니다.
이번에는 각 user의 상세정보를 보여줄 UserDetail 페이지입니다.
uri는 ‘/users/{id}’형식으로 구성되고, id는 uri parameter로서 매번 동적으로 다른 값이 요청됩니다.
nextjs에서는 해당 페이지를 ‘[id].js’와 같은 형식의 이름으로 작성합니다.
‘pages/users/[id].js’ 파일을 생성하고 useRouter api를 이용해 현재 라우팅된 페이지에 관한 정보를 받아옵니다.
// pages/users/[id].js
import { useRouter } from 'next/router'function UserDetail() { const router = useRouter(); console.log( router ); return ( <>User Detail</> );}export default UserDetail;
우선 router정보가 잘 넘어오는지 찍어봅니다.
query와 path정보 등을 포함한 router 정보가 출력됩니다.
이제 UserDetail 페이지에서는 전달받은 query에서 user id정보를 확인하여 해당 user의 상세 정보를 요청하고, 전달받은 user 상세정보를 화면에 rendering 해주면 됩니다.
지금까지는 graphQL요청을 보낼 때 단순히 POST요청에 body값을 설정했다면 이제부터는 좀 더 간편하게 요청에 parameter를 설정하고 캐시기능도 함께 사용하기 위해 apollo-client를 사용하겠습니다.
‘@apollo/client’ 모듈을 설치하고 ‘ApolloClient’, ‘InMemoryCache’, ‘gql’를 사용하여 단일 user 정보를 불러오는 함수를 작성합니다.
이후에는 apollo-client의 요청을 받아 처리해줄 graphql.js파일에 단일 유저정보를 반환하는 ‘user’ query를 typeDefs와 resolver에 정의해줍니다.
// pages/api/graphql.js
const typeDefs = gql` type Query { users: [User!]! user(id:String!): User! } type User { id: String name: String color: String }`;const resolvers = { Query: { users( _parent, _args, _context ) { return data.users; }, user( parent, args, context ) { return data.users.find( user => user.id === parseInt( args.id ) ); } },};...
페이지에 접근하면 다음과 같이 선택한 user의 정보를 동적으로 요청하여 렌더링하는 user/{id} 페이지가 동작하는 모습을 확인할 수 있습니다.