서버 사이드 렌더링
비공식 베타 번역
이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
SSR을 활성화하려면 createTRPCNext 설정 콜백에서 ssr: true를 설정하기만 하면 됩니다.
정보
서버 사이드 렌더링 단계에서 쿼리를 올바르게 실행하려면 config 내부에 추가 로직을 포함해야 합니다:
추가적으로 Response Caching을 고려해보세요.
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr: true,});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr: true,});
또는 특정 요청에 따라 SSR을 조건부로 적용하려면 ssr에 콜백 함수를 전달할 수 있습니다. 이 콜백은 boolean을 반환하거나 boolean으로 resolve되는 Promise를 반환할 수 있습니다:
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr(opts) {// only SSR if the request is coming from a botreturn opts.ctx?.req?.headers['user-agent']?.includes('bot');},});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr(opts) {// only SSR if the request is coming from a botreturn opts.ctx?.req?.headers['user-agent']?.includes('bot');},});
pages/_app.tsxtsximport { trpc } from '~/utils/trpc';import type { AppProps } from 'next/app';import React from 'react';const MyApp: AppType = ({ Component, pageProps }: AppProps) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
pages/_app.tsxtsximport { trpc } from '~/utils/trpc';import type { AppProps } from 'next/app';import React from 'react';const MyApp: AppType = ({ Component, pageProps }: AppProps) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
FAQ
Q: 클라이언트 헤더를 서버에 수동으로 전달해야 하는 이유는 무엇인가요? tRPC가 자동으로 처리해주지 않는 이유는?
SSR 수행 시 클라이언트 헤더를 서버에 전달하지 않는 경우는 드물지만, 헤더에 동적으로 내용을 추가해야 할 수 있습니다. 따라서 tRPC는 헤더 키 충돌 등에 대한 책임을 지지 않기로 했습니다.
Q: Node 18에서 SSR을 사용할 때 connection 헤더를 삭제해야 하는 이유는?
connection 헤더를 제거하지 않으면 데이터 가져오기가 TRPCClientError: fetch failed로 실패합니다. connection은 금지된 헤더 이름이기 때문입니다.
Q: 네트워크 탭에서 여전히 네트워크 요청이 보이는 이유는?
기본적으로 데이터 가져오기 훅에 사용하는 @tanstack/react-query는 SSR을 통해 초기 데이터를 이미 받아온 경우에도 마운트 시와 윈도우 포커스 시 데이터를 재요청합니다. 이는 데이터가 항상 최신 상태임을 보장하기 위함입니다. 이 동작을 비활성화하려면 SSG 페이지를 참조하세요.