Quick start
Quick start
GraphQLμ APIμ λν 쿼리 μΈμ΄μ΄λ©° κΈ°μ‘΄ λ°μ΄ν°λ‘ 쿼리λ₯Ό μννκΈ°μν λ°νμμ
λλ€. μΌλ°μ μΈ REST APIμμ λ°μνλ μ΄λ¬ν λ§μ λ¬Έμ λ₯Ό ν΄κ²°νλ μ°μν μ κ·Ό λ°©μμ
λλ€. GraphQLκ³Ό REST μ¬μ΄μλ νλ₯ν λΉκ΅κ° μμ΅λλ€. μ΄ κΈ°μ¬μμλ GraphQLμ΄ λ¬΄μμΈμ§ μ€λͺ
νμ§ μκ³  μ μ© @nestjs/graphql λͺ¨λλ‘ μμ
νλ λ°©λ²μ 보μ¬μ€λλ€. μ΄ μ±ν°μμλ μ΄λ―Έ GraphQL κΈ°λ³Έ μ¬νμ μ΅μνλ€κ³  κ°μ ν©λλ€.
GraphQLModuleμ [Apollo] (https://www.apollographql.com/) μλ²μ λνΌμ μ§λμ§ μμ΅λλ€. μ°λ¦¬λ λ°ν΄λ₯Ό μ¬λ° λͺ
νμ§ μκ³  λμ  μ¬μ©ν  μ€λΉκ° λ λͺ¨λμ μ κ³΅νμ¬ GraphQLκ³Ό Nestλ₯Ό ν¨κ» μ¬μ©ν  μ μμ΅λλ€.
Installation
λ¨Όμ  νμν ν¨ν€μ§λ₯Ό μ€μΉν΄μΌν©λλ€.
$ npm i --save @nestjs/graphql apollo-server-express graphql-tools graphqlOverview
Nestλ GraphQL μ΄ν리μΌμ΄μ μ λΉλνλ λ κ°μ§ λ°©λ², μ¦ μ€ν€λ§ μ°μ κ³Ό μ½λ μ°μ μ μ 곡ν©λλ€.
μ€ν€λ§ μ°μ μ κ·Όλ²μμ μ§μ€μ κ·Όμμ GraphQL SDL (μ€ν€λ§ μ μ μΈμ΄)μ λλ€. κΈ°λ³Έμ μΌλ‘ μλ‘ λ€λ₯Έ νλ«νΌκ°μ μ€ν€λ§ νμΌμ 곡μ ν μ μλ μΈμ΄μ ꡬμ λ°μ§ μλ λ°©μμ λλ€. λν Nestλ GraphQL μ€ν€λ§ (ν΄λμ€ λλ μΈν°νμ΄μ€ μ¬μ©)λ₯Ό κΈ°λ°μΌλ‘ TypeScript μ μλ₯Ό μλμΌλ‘ μμ±νμ¬ μ€λ³΅μ±μ μ€μ λλ€.
λ°λ©΄μ μ½λ μ°μ λ°©μμμλ λ°μ½λ μ΄ν°μ TypeScript ν΄λμ€ λ§ μ¬μ©νμ¬ ν΄λΉ GraphQL μ€ν€λ§λ₯Ό μμ±ν©λλ€. TypeScriptλ‘ λ μ μ μΌλ‘ μμ νκ³ μΈμ΄ ꡬ문 κ°μ 컨ν μ€νΈ μ νμ νΌνλ κ²μ΄ λ§€μ° νΈλ¦¬ν©λλ€.
Getting started
ν¨ν€μ§κ° μ€μΉλλ©΄ GraphQLModuleμ λ±λ‘ ν  μ μμ΅λλ€.
@@filename()
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
@Module({
  imports: [
    GraphQLModule.forRoot({}),
  ],
})
export class ApplicationModule {}.forRoot()λ©μλλ μ΅μ
 κ°μ²΄λ₯Ό μΈμλ‘ λ°μ΅λλ€. μ΄λ¬ν μ΅μ
μ κΈ°λ³Έ Apollo μΈμ€ν΄μ€λ‘ μ λ¬λ©λλ€ (μ¬μ© κ°λ₯ν μ€μ μ λν μμΈν λ΄μ©μ μ¬κΈ°. μλ₯Ό λ€μ΄, λμ΄ν°λ₯Ό λΉνμ±ννκ³  λλ²κ·Έ λͺ¨λλ₯Ό λλ €λ©΄ λ€μ μ΅μ
μ μ λ¬νμμμ€.
@@filename()
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
@Module({
  imports: [
    GraphQLModule.forRoot({
      debug: false,
      playground: false,
    }),
  ],
})
export class ApplicationModule {}μΈκΈ ν λ°μ κ°μ΄ μ΄ λͺ¨λ  μ€μ μApolloServer μμ±μλ‘ μ λ¬λ©λλ€.
Playground
λμ΄ν°λ κ·Έλν½ λν ν λΈλΌμ°μ  λ΄ GraphQL IDEμ΄λ©° κΈ°λ³Έμ μΌλ‘ GraphQL μλ² μ체μ λμΌν URLμμ μ¬μ©ν  μ μμ΅λλ€. μ ν리μΌμ΄μ
μ΄ λ°±κ·ΈλΌμ΄λμμ μ€νλλ λμ μΉ λΈλΌμ°μ λ₯Ό μ΄κ³  http://localhost:3000/graphqlλ‘ μ΄λνμμμ€ (νΈμ€νΈ λ° ν¬νΈλ ꡬμ±μ λ°λΌ λ€λ₯Ό μ μμ).
Multiple endpoints
μ΄ λͺ¨λμ λ λ€λ₯Έ μ μ©ν κΈ°λ₯μ μ¬λ¬ μλ ν¬μΈνΈλ₯Ό ν λ²μ μ κ³΅νλ κΈ°λ₯μ
λλ€. λλΆμ μ΄λ€ μλ ν¬μΈνΈμ μ΄λ€ λͺ¨λμ ν¬ν¨ν μ§ κ²°μ ν  μ μμ΅λλ€. κΈ°λ³Έμ μΌλ‘ GraphQLμ μ μ²΄ μ±μμ 리쑸λ²λ₯Ό κ²μν©λλ€. λͺ¨λμ μλΈμ
λ§ μ ννκΈ° μν΄ include μμ±μ μ¬μ©ν  μ μμ΅λλ€.
GraphQLModule.forRoot({
  include: [CatsModule],
}),Schema first
μ€ν€λ§λ₯Ό λ¨Όμ  μ¬μ©νλ €λ©΄ options κ°μ²΄ μμtypePaths λ°°μ΄μ μΆκ°νλ©΄λ©λλ€.
GraphQLModule.forRoot({
  typePaths: ['./**/*.graphql'],
}),typePaths μμ±μ GraphQLModuleμ΄ GraphQL νμΌμ μ°ΎμμΌνλ μμΉλ₯Ό λνλ
λλ€. μ΄λ¬ν λͺ¨λ  νμΌμ κ²°κ΅ λ©λͺ¨λ¦¬μ κ²°ν©λλ―λ‘ μ€ν€λ§λ₯Ό μ¬λ¬ νμΌλ‘ λΆν νμ¬ λ¦¬μ‘Έλ² κ·Όμ²μ μ μ§ν  μ μμ΅λλ€.
GraphQL μ νκ³Ό ν΄λΉ TypeScript μ μλ₯Ό λ³λλ‘ μμ±νλ©΄ λΆνμν μ€λ³΅μ΄ μμ±λ©λλ€. κ²°κ΅, μ°λ¦¬λ λ¨μΌν μ§μ€μ μμ²μμ΄ κ²°κ΅ SDL λ΄μμ μ΄λ£¨μ΄μ§ κ° λ³κ²½μΌλ‘ μΈν΄ μΈν°νμ΄μ€λ μ‘°μ ν΄μΌ ν©λλ€. λ°λΌμ@nestjs/graphql ν¨ν€μ§λ λ λ€λ₯Έ ν₯λ―Έλ‘μ΄ κΈ°λ₯μ μ κ³΅νλλ°, μ΄λ μΆμ ꡬ문 νΈλ¦¬ (AST)λ₯Ό μ¬μ©ν TS μ μμ μλ μμ±μ
λλ€. μ΄λ₯Ό κ°λ₯νκ²νλ €λ©΄ definitions μμ±μ μΆκ°νλ©΄ λ©λλ€.
GraphQLModule.forRoot({
  typePaths: ['./**/*.graphql'],
  definitions: {
    path: join(process.cwd(), 'src/graphql.ts'),
  },
}),src/graphql.tsλ TypeScript μΆλ ₯μ μ μ₯ν  μμΉλ₯Ό λνλ
λλ€. κΈ°λ³Έμ μΌλ‘ λͺ¨λ  μ νμ΄ μΈν°νμ΄μ€λ‘ λ³νλ©λλ€. κ·Έλ¬λ outputAs μμ±μ classλ‘ λ³κ²½νμ¬ λμ  ν΄λμ€λ‘ μ νν  μ μμ΅λλ€.
GraphQLModule.forRoot({
  typePaths: ['./**/*.graphql'],
  definitions: {
    path: join(process.cwd(), 'src/graphql.ts'),
    outputAs: 'class',
  },
}),κ·Έλ¬λ κ° μμ© νλ‘κ·Έλ¨ μμμ μ ν μ μλ₯Ό μμ±νμ§ μμλλ©λλ€. λμ , μ μ© λͺ
λ Ήμ΄ μ€νλ  λλ§ μμ ν μ μ΄νκ³  μ
λ ₯μ μμ±νλ κ²μ μ νΈ ν  μ μμ΅λλ€. μ΄ κ²½μ° generate-typings.tsλΌκ³  νλ μ체 μ€ν¬λ¦½νΈλ₯Ό λ§λ€ μ μμ΅λλ€.
import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
import { join } from 'path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
  typePaths: ['./src/**/*.graphql'],
  path: join(process.cwd(), 'src/graphql.ts'),
  outputAs: 'class',
});κ·Έλ° λ€μ κ°λ¨ν νμΌμ μ€ννμμμ€.
ts-node generate-typingsinfo ννΈ λ―Έλ¦¬ μ€ν¬λ¦½νΈλ₯Ό μ»΄νμΌνκ³ λμ node μ€ν νμΌμ μ¬μ©ν μλ μμ΅λλ€.
κ°μ λͺ¨λλ‘ μ ννλ €λ©΄ (.graphql νμΌ λ³κ²½μ μλμΌλ‘ μ
λ ₯μ μμ±) watch μ΅μ
μ generate()λ©μλμ μ λ¬νμμμ€.
definitionsFactory.generate({
  typePaths: ['./src/**/*.graphql'],
  path: join(process.cwd(), 'src/graphql.ts'),
  outputAs: 'class',
  watch: true,
});μμ ν μλνλ μνμ μ¬κΈ°μμ μ¬μ©ν μ μμ΅λλ€.
Code first
μ½λ μ°μ λ°©λ²μμλ λ°μ½λ μ΄ν°μ TypeScript ν΄λμ€ λ§ μ¬μ©νμ¬ ν΄λΉ GraphQL μ€ν€λ§λ₯Ό μμ±ν©λλ€.
Nestλμ΄ κΈ°λ₯μ μ 곡νκΈ° μν΄ νλ μλμμ λλΌμ΄ type-graphql λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκ³ μμ΅λλ€. λ°λΌμ κ³μ μ§ννκΈ° μ μ μ΄ ν¨ν€μ§λ₯Ό μ€μΉν΄μΌν©λλ€.
$ npm i type-graphqlμ€μΉ κ³Όμ μ΄ μλ£λλ©΄, autoSchemaFile μμ±μ μ΅μ
 κ°μ²΄μ μΆκ° ν  μ μμ΅λλ€.
GraphQLModule.forRoot({
  autoSchemaFile: 'schema.gql',
}),autoSchemaFileμ μλμΌλ‘ μμ±λ μ€ν€λ§κ° μμ±λ  κ²½λ‘λ₯Ό λνλ
λλ€. λν buildSchemaOptions μμ±-type-graphql ν¨ν€μ§μμ buildSchema()ν¨μλ‘ μ λ¬λλ μ΅μ
 κ°μ²΄λ₯Ό μ λ¬ν  μ μμ΅λλ€.
μμ ν μλνλ μνμ μ¬κΈ°μμ μ¬μ©ν μ μμ΅λλ€.
Async configuration
λͺ¨λ μ΅μ
μ 미리 μ λ¬νλ λμ  λΉλκΈ°μμΌλ‘ μ λ¬νλ €λ κ²½μ°κ° μ’
μ’
 μμ΅λλ€. μ΄ κ²½μ° λΉλκΈ° λ°μ΄ν°λ₯Ό μ²λ¦¬νλ λͺ κ°μ§ λ€μν λ°©λ²μ μ κ³΅νλ forRootAsync()λ©μλλ₯Ό μ¬μ©νμμμ€.
κ°λ₯ν 첫 λ²μ§Έ λ°©λ²μ ν©ν 리 κΈ°λ₯μ μ¬μ©νλ κ²μ λλ€.
GraphQLModule.forRootAsync({
  useFactory: () => ({
    typePaths: ['./**/*.graphql'],
  }),
}),λΆλͺ
ν, μ°λ¦¬ ν©ν λ¦¬λ λ€λ₯Έ λͺ¨λ  κ²μ²λΌ νλν©λλ€ ( asyncμΌ μλ μκ³  injectμ ν΅ν΄ μμ‘΄μ±μ μ£Όμ
ν  μλ μμ΅λλ€).
GraphQLModule.forRootAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    typePaths: configService.getString('GRAPHQL_TYPE_PATHS'),
  }),
  inject: [ConfigService],
}),λλ ν©ν 리 λμ ν΄λμ€λ₯Ό μ¬μ©ν μ μμ΅λλ€.
GraphQLModule.forRootAsync({
  useClass: GqlConfigService,
}),μμ ꡬμ±μ GraphQLModule λ΄μμ GqlConfigServiceλ₯Ό μΈμ€ν΄μ€ν νκ³  μ΄λ₯Ό νμ©νμ¬ μ΅μ
 κ°μ²΄λ₯Ό μμ±ν©λλ€. GqlConfigServiceλ GqlOptionsFactory μΈν°νμ΄μ€λ₯Ό ꡬνν΄μΌν©λλ€.
@Injectable()
class GqlConfigService implements GqlOptionsFactory {
  createGqlOptions(): GqlModuleOptions {
    return {
      typePaths: ['./**/*.graphql'],
    };
  }
}GraphQLModule λ΄μ GqlConfigServiceκ° μμ±λλ κ²μ λ§κ³  λ€λ₯Έ λͺ¨λμμ κ°μ Έμ¨ μ κ³΅μλ₯Ό μ¬μ©νλ €λ©΄useExisting ꡬ문μ μ¬μ©ν  μ μμ΅λλ€.
GraphQLModule.forRootAsync({
  imports: [ConfigModule],
  useExisting: ConfigService,
}),νλμ μ€μν μ°¨μ΄μ μΌλ‘ useClassμ λμΌνκ² μλν©λλ€. GraphQLModuleμ κ°μ Έμ¨ λͺ¨λμ μ‘°ννμ¬ μ΄λ―Έ μμ±λ ConfigServiceλ₯Ό μ체μ μΌλ‘ μΈμ€ν΄μ€ν νλ λμ  μ¬μ¬μ©ν©λλ€.
Last updated
Was this helpful?