6. 서버 사이드 렌더링

2020-10-08
SSR
Server-Side Rendering (서버 측 렌더링) - 클라이언트 측 또는 유니버설 앱을 서버의 HTML로 렌더링
CSR
Client-Side Rendering (클라이언트 측 렌더링) - 브라우저에서 애플리케이션을 렌더링. 일반적으로 DOM을 사용

서버 렌더링은 탐색에 대한 응답으로 서버의 페이지에 대한 전체 HTML을 생성한다.

브라우저에서 응답을 받기 전에 처리되므로 클라이언트에서 데이터 가져 오기 및 템플릿 작성에 대한 추가 왕복이 발생하지 않는다.

yarn add next-urql react-is urql
Next.js
This integration contains convenience methods specifically for Next.js.
react-is
This package allows you to test arbitrary values and see if they’re a particular React element type.

withUrqlClient 고차 컴포넌트(Higher-Order Components)로 어떤 페이지이든 감싸 자동으로 서버 사이드 렌더링을 할 수 있다.

(alias) withUrqlClient(getClientConfig: NextUrqlClientConfig, options?: WithUrqlClientOptions | undefined)

utils/createClient.ts

import { dedupExchange, fetchExchange } from "urql";
import { cacheExchange } from "@urql/exchange-graphcache";
import {
  LogoutMutation,
  MeQuery,
  MeDocument,
  LoginMutation,
  RegisterMutation,
} from "../generated/graphql";
import { betterUpdateQuery } from "./betterUpdateQuery";

export const createUrqlClient = (ssrExchange: any) => ({
  url: "http://localhost:4000/graphql",
  fetchOptions: {
    credentials: "include" as const,
  },
  exchanges: [
    dedupExchange,
    cacheExchange({
      updates: {
        Mutation: {
          logout: (_result, args, cache, info) => {
            betterUpdateQuery<LogoutMutation, MeQuery>(
              cache,
              { query: MeDocument },
              _result,
              (result, query) => ({ me: null })
            );
          },
          login: (_result, args, cache, info) => {
            betterUpdateQuery<LoginMutation, MeQuery>(
              cache,
              { query: MeDocument },
              _result,
              (result, query) => {
                if (result.login.errors) {
                  return query;
                } else {
                  return {
                    me: result.login.user,
                  };
                }
              }
            );
          },

          register: (_result, args, cache, info) => {
            betterUpdateQuery<RegisterMutation, MeQuery>(
              cache,
              { query: MeDocument },
              _result,
              (result, query) => {
                if (result.register.errors) {
                  return query;
                } else {
                  return {
                    me: result.register.user,
                  };
                }
              }
            );
          },
        },
      },
    }),
    ssrExchange,
    fetchExchange,
  ],
});

index.tsx

const Index = () => {
  const [{ data }] = usePostsQuery();
  return (
    <>
      <NavBar></NavBar>
      <div>hello world</div>
      {!data ? null : data.posts.map((p) => <div key={p.id}>{p.title}</div>)}
    </>
  );
};
export default withUrqlClient(createUrqlClient, { ssr: true })(Index);