리졸버와 구독
데이터를 가져오고 조작하는 GraphQL 리졸버를 구현하고 실시간 데이터 업데이트를 위한 구독을 설정합니다.
리졸버와 구독은(는) CoddyKit의 무료 NestJS Enterprise Backend APIs 강의입니다. 이것은 3개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 NestJS Enterprise Backend APIs 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. NestJS Enterprise Backend APIs 강의에는 총 3개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Intro to GraphQL Resolvers
Welcome to the world of GraphQL resolvers in NestJS! Resolvers are the core of your GraphQL API, acting as the bridge between your GraphQL schema and your application's data sources.
- They define how to fetch the data for a specific field in your schema.
- Think of them as functions that execute when a corresponding field is requested in a GraphQL query or mutation.
- Resolvers can interact with databases, REST APIs, or any other data source.
Resolver Structure in NestJS
NestJS simplifies resolver creation using decorators. You define a class as a resolver and then use specific decorators for different GraphQL operations:
@Resolver(): Marks a class as a GraphQL resolver.@Query(): Maps a method to a GraphQL query operation (data fetching).@Mutation(): Maps a method to a GraphQL mutation operation (data modification).@Subscription(): Maps a method to a GraphQL subscription operation (real-time data).
Implementing a Basic Query
Let's create a simple query resolver that returns a 'Hello world!' string. This demonstrates the basic setup for a query:
import { Module, Injectable } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { Query, Resolver } from '@nestjs/graphql';
@Injectable()
class AppService {
getHello(): string {
return 'Hello world!';
}
}
@Resolver()
class AppResolver {
constructor(private readonly appService: AppService) {}
@Query(() => String)
hello(): string {
return this.appService.getHello();
}
}
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
],
providers: [AppResolver, AppService],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();Handling Query Arguments
Queries often need arguments to filter or specify data. Use the @Args() decorator to extract arguments from the GraphQL request.
Here, we'll create a query that greets a specific name.
import { Module, Injectable } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { Args, Query, Resolver } from '@nestjs/graphql';
@Injectable()
class AppService {
getGreeting(name: string): string {
return `Hello, ${name}!`;
}
}
@Resolver()
class AppResolver {
constructor(private readonly appService: AppService) {}
@Query(() => String)
greet(@Args('name') name: string): string {
return this.appService.getGreeting(name);
}
}
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
],
providers: [AppResolver, AppService],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();Introducing GraphQL Mutations
While queries fetch data, mutations are used for modifying data on the server. This includes operations like creating, updating, or deleting records.
- Mutations are similar to queries in structure but clearly signal a side effect.
- They typically return the modified object or a status indicating success.
- Use the
@Mutation()decorator to define them in NestJS.
Implementing a Basic Mutation
Let's create a mutation to add a simple 'Item'. We'll define an Item type and a mutation that takes a name and returns the newly created item.
import { Module, Injectable, Field, ObjectType, InputType } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
@ObjectType()
class Item {
@Field(() => String)
id: string;
@Field(() => String)
name: string;
}
@Injectable()
class ItemsService {
private readonly items: Item[] = [];
create(name: string): Item {
const newItem = { id: String(this.items.length + 1), name };
this.items.push(newItem);
return newItem;
}
findAll(): Item[] { return this.items; }
}
@Resolver(() => Item)
class ItemsResolver {
constructor(private readonly itemsService: ItemsService) {}
@Query(() => [Item])
items(): Item[] {
return this.itemsService.findAll();
}
@Mutation(() => Item)
createItem(@Args('name') name: string): Item {
return this.itemsService.create(name);
}
}
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
],
providers: [ItemsResolver, ItemsService],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();What are GraphQL Subscriptions?
Subscriptions are a GraphQL feature that allows clients to receive real-time updates from the server. Unlike queries and mutations (which are request-response), subscriptions are long-lived connections, typically over WebSockets.
- When a client subscribes, it opens a persistent connection.
- The server pushes data to the client whenever a specific event occurs.
- Perfect for chat applications, live dashboards, or notifications.
Setting up PubSub for Subscriptions
To implement subscriptions, NestJS GraphQL often uses graphql-subscriptions's PubSub (Publish-Subscribe) mechanism. The server publishes events, and subscribers listen for them.
You need to configure GraphQLModule for subscriptions and provide a PubSub instance.
import { Module, Injectable } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { PubSub } from 'graphql-subscriptions';
// We need a module to provide PubSub
@Module({
providers: [
{
provide: 'PUB_SUB', // Token for PubSub instance
useValue: new PubSub(),
},
],
exports: ['PUB_SUB'], // Export to use in other modules
})
class PubSubModule {}
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
// Crucial for subscriptions:
subscriptions: {
'graphql-ws': true, // Enable WebSocket for subscriptions
'subscriptions-transport-ws': true,
},
}),
PubSubModule,
],
// No resolvers needed for this example, just setup
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
console.log('GraphQL server with subscriptions running on port 3000');
}
bootstrap();Implementing a Subscription
Now let's build a subscription! We'll create a postAdded subscription that emits an event whenever a new post is created via a mutation.
- Use
@Subscription()to define the subscription method. - Inject
PubSubto publish events. - The mutation will trigger the event.
import { Module, Injectable, Field, ObjectType, Inject } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';
const POST_ADDED_EVENT = 'postAdded';
@ObjectType()
class Post {
@Field(() => String)
id: string;
@Field(() => String)
title: string;
@Field(() => String)
content: string;
}
@Injectable()
class PostsService {
private readonly posts: Post[] = [];
create(title: string, content: string): Post {
const newPost = { id: String(this.posts.length + 1), title, content };
this.posts.push(newPost);
return newPost;
}
findAll(): Post[] { return this.posts; }
}
@Module({
providers: [
{
provide: 'PUB_SUB', // Token for PubSub instance
useValue: new PubSub(),
},
],
exports: ['PUB_SUB'], // Export to use in other modules
})
class PubSubModule {}
@Resolver(() => Post)
class PostsResolver {
constructor(
private readonly postsService: PostsService,
@Inject('PUB_SUB') private pubSub: PubSub,
) {}
@Query(() => [Post])
posts(): Post[] {
return this.postsService.findAll();
}
@Mutation(() => Post)
async createPost(
@Args('title') title: string,
@Args('content') content: string,
): Promise<Post> {
const newPost = this.postsService.create(title, content);
await this.pubSub.publish(POST_ADDED_EVENT, { postAdded: newPost });
return newPost;
}
@Subscription(() => Post, { name: POST_ADDED_EVENT })
postAdded() {
return this.pubSub.asyncIterator(POST_ADDED_EVENT);
}
}
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
subscriptions: {
'graphql-ws': true,
'subscriptions-transport-ws': true,
},
}),
PubSubModule,
],
providers: [PostsResolver, PostsService],
})
class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
console.log('GraphQL server with subscriptions running on port 3000');
console.log('Try a POST_ADDED_EVENT subscription in your client!');
}
bootstrap();Resolver & Subscription Check
Time to test your knowledge on NestJS GraphQL resolvers and subscriptions!
Recap: Resolvers & Real-time
Congratulations! You've grasped the essentials of GraphQL resolvers and subscriptions in NestJS.
- Resolvers are the backbone, connecting your schema to your data.
- Queries fetch data, Mutations change data, and Subscriptions provide real-time updates.
- We explored how to implement simple queries and mutations, and set up real-time features using
PubSubfor subscriptions.
Keep practicing to build dynamic and responsive GraphQL APIs!
자주 묻는 질문
“리졸버와 구독” 강의는 무료인가요?
네 — “리졸버와 구독” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 NestJS Enterprise Backend APIs 강의 전체를 잠금 해제할 수 있습니다. NestJS Enterprise Backend APIs 강의에는 총 3개의 강의가 포함되어 있습니다.
“리졸버와 구독”에서 뭘 배우나요?
데이터를 가져오고 조작하는 GraphQL 리졸버를 구현하고 실시간 데이터 업데이트를 위한 구독을 설정합니다. 브라우저에서 직접 실행하는 실습 코드로 NestJS Enterprise Backend APIs을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
NestJS Enterprise Backend APIs을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 NestJS Enterprise Backend APIs은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 3번째 강의입니다.
“리졸버와 구독” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 NestJS Enterprise Backend APIs 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 NestJS Enterprise Backend APIs 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- GraphQL 기초
- NestJS GraphQL 설정
- 리졸버와 구독