Project
WebSocket/ Subscription
프도의길
2023. 8. 29. 16:35
메시지웹을 만들려면 WevSocket이 필요합니다 세팅을 시작하겠습니다.
https://www.apollographql.com/docs/react/data/subscriptions
Subscriptions
Get real-time updates from your GraphQL server
www.apollographql.com
npm i graphql-ws 설치해줍니다.
//frontend src/graphql/apollo-client.ts
import { ApolloClient, HttpLink, InMemoryCache, split } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { getMainDefinition } from "@apollo/client/utilities";
import { createClient } from "graphql-ws";
import { getSession } from "next-auth/react";
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql",
credentials: "include",
});
const wsLink =
typeof window !== "undefined"
? new GraphQLWsLink(
createClient({
url: "ws://localhost:4000/graphql/subscriptions",
connectionParams: async () => ({
session: await getSession(),
}),
})
)
: null;
const link =
typeof window !== "undefined" && wsLink !== null
? split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
httpLink
)
: httpLink;
export const client = new ApolloClient({
link,
cache: new InMemoryCache(),
});
wsLink 서버와 통신할 수 있게 url 주소를 통일시켜줘야 합니다.
graphQL Subscript는 웹소켓을 사용합니다.
https://www.apollographql.com/docs/apollo-server/data/subscriptions/
Subscriptions in Apollo Server
Persistent GraphQL read operations
www.apollographql.com
npm install graphql-ws ws @graphql-tools/schema apollo-server-core
npm install graphql-subscriptions
백엔드에다 설치해줍니다.
//backend src/index.ts
import { makeExecutableSchema } from "@graphql-tools/schema";
import { ApolloServer } from "apollo-server-express";
import {
ApolloServerPluginDrainHttpServer,
ApolloServerPluginLandingPageLocalDefault,
} from "apollo-server-core";
import express from "express";
import http from "http";
import typeDefs from "./graphql/typeDefs";
import resolvers from "./graphql/resolvers";
import { getSession } from "next-auth/react";
import { GraphQLContext, Session, SubscriptionContext } from "./util/types";
import { WebSocketServer } from "ws";
import { PubSub } from "graphql-subscriptions";
import { useServer } from "graphql-ws/lib/use/ws";
import * as dotenv from "dotenv";
import { PrismaClient } from "@prisma/client";
async function main() {
dotenv.config();
const app = express();
const httpServer = http.createServer(app);
const schema = makeExecutableSchema({
typeDefs,
resolvers,
});
// Creating the WebSocket server
const wsServer = new WebSocketServer({
server: httpServer,
path: "/graphql/subscriptions",
});
const prisma = new PrismaClient();
const pubsub = new PubSub();
const serverCleanup = useServer(
{
schema,
context: async (ctx: SubscriptionContext): Promise<GraphQLContext> => {
if (ctx.connectionParams && ctx.connectionParams.session) {
const { session } = ctx.connectionParams;
return { session, prisma, pubsub };
}
return { session: null, prisma, pubsub };
},
},
wsServer
);
const corsOptions = {
origin: process.env.CLIENT_ORIGIN,
credentials: true,
};
const server = new ApolloServer({
schema,
csrfPrevention: true,
cache: "bounded",
context: async ({ req, res }): Promise<GraphQLContext> => {
const session = (await getSession({ req })) as Session;
return { session, prisma, pubsub };
},
plugins: [
// Proper shutdown for the HTTP server.
ApolloServerPluginDrainHttpServer({ httpServer }),
// Proper shutdown for the WebSocket server.
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
],
});
await server.start();
server.applyMiddleware({ app, cors: corsOptions });
await new Promise<void>((resolve) =>
httpServer.listen({ port: 4000 }, resolve)
);
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}
main().catch((err) => console.log(err));
클라이언트와 통신 및 실시간 업데이트할 수 있게 wsServer, pubsub 선언해줍니다