반응형
0. 패키지 설치
$ npm i @nestjs/graphql graphql-tools graphql apollo-server-express
- apollo server를 기반으로하는 @nestjs/graphql을 활용해 nest.js 환경에서 GraphQL을 사용할 수 있다.
- Apollo server나 기존 GraphQL 라이브러리도 당연히 필요하기 때문에 함께 설치해준다.
1. 모듈 연결하기
import { GraphQLModule } from '@nestjs/graphql';
@Module({
imports: [
GraphQLModule.forRoot({
autoSchemaFile: true,
})
],
controllers: [],
providers: [],
})
- GraphQL 모듈이 정상적으로 돌아가도록 하기 위해, 적용될 범위의 모듈에 GraphQL 모듈을 추가해주어야 한다. (물론 대부분의 경우 최상위 모듈인 app.module이 될 것이다.)
- GraphQLModule.forRoot로 root 모듈 설정을 해준다.
- autoSchemaFile는 작성된 typescript 코드를 기반으로 자동으로 스키마를 작성해준다.
- autoSchemaFile을 true로 설정하면 메모리 상에서 자동으로 스키마가 처리된다.
- autoSchemaFile에 join(process.cwd(), 'schema.gql')와 같이 경로와 파일명을 입력하면 해당 경로에 파일명의 스키마 파일이 생성된다.
- 물론, GraphQL이 Apollo server에서 정상적으로 돌아가기 위해선 typeDefs(schema)와 resolvers(query, mutation)의 내용이 명시되어 있어야 한다.
2. Resolver 작성 예시 및 설명
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
import { Restaurant } from "./entities/restaurant.entity";
@Resolver(of => Restaurant)
export class RestaurantResolver {
@Query(returns => [Restaurant])
restaurant(): Restaurant[] {
return Restaurants;
}
@Mutation(returns => Boolean)
createRestaurant(
@Args('name') name: string, @Args('address') address: string): boolean {
return true;
}
}
- @Resolver 데코레이터를 활용해 resolver를 작성한다.
- of => Restaurant 로 어떤 resolver인지 명시할 수도 있다. (필수는 아님)
- 내부에서는 @Query, @Mutation 데코레이터를 활용해 GraphQL-Yoga에서 작성한 것처럼 Resolver를 작성한다.
- 단, @Query, @Mutation 데코레이터에 리턴값의 형식을 typeFunc 형식으로 입력해 알려주어야 한다. (해당 typeFunc는 ()=> Boolean , type => Boolean 등 다양한 형식으로 작성할 수 있다.)
- argument가 필요한 요청의 경우 @Args 데코레이터를 통해 하나씩 명시 후 작성한다.
- Query나 Mutation에 대한 typeDefs는 각 데코레이터로 인해 알아서 처리되니 이제 우리는 추가적으로 필요한 형식에 대해서만 처리해주면 된다. (by. autoSchemaFile)
- 해당 resolver파일은 모듈의 providers에 입력되어야 정상적으로 작동한다.
- cf. graphql로 해석되는 코드에서 특정 타입의 집합을 표현할 때는 type[]가 아닌, [type]으로 명시해야한다. 그 외에도 타입의 입력형식이 조금씩 다른 경우가 있으므로 주의하자.
3. typeDefs 작성 예시 및 설명
import { Field, ObjectType } from "@nestjs/graphql";
@ObjectType()
export class Restaurant {
@Field(type => String)
name: string;
@Field(type => String)
address: string;
@Field(type => String, { nullable: 'items' })
ownerName?: string;
}
- @ObjectType 데코레이터와 @Field 데코레이터를 사용하면 entitiy 파일에 작성된 모델을 그대로 활용해 typeDefs로 사용할 수 있다.
- @ObjectType 데코레이터는 해당 class가 graphql 상에서 typeDefs로 인식되도록 해준다.
- @Field는 해당 type의 속성이며, typeFuncs로 형식을 입력해주어야한다.
- @Field 데코레이터는 {nullalbe:true} 등의 옵션 부여도 가능하다.
cf. resolver에서 하나의 object로 전달받는 방법
@InputType()
export class createRestaurantDto {
@Field(type => String)
name: string;
@Field(type => Boolean)
isVegan: boolean;
@Field(type => String)
address: string;
@Field(type => String)
ownerName: string;
}
- 위와 같은 형식으로 dto를 작성해 typeDefs를 해준다.
- 핵심은 @inputType 데코레이터이다. 해당 데코레이터가 class를 하나의 object로 인식하도록 해준다.
@Mutation(returns => Boolean)
createRestaurant(
@Args('createRestaurantInput') createRestaurantInput: createRestaurantDto): boolean {
return true;
}
- @inputType 데코레이터 덕분에 createRestaurantDto 형식을 createRestaurantInput, 하나의 input object로 받아들일 수 있게된다.
cf2. 하나의 object지만 분리된 형태로 전달받고 싶을 경우
@ArgsType()
export class createRestaurantDto {
@Field(type => String)
name: string;
@Field(type => Boolean)
isVegan: boolean;
@Field(type => String)
address: string;
@Field(type => String)
ownerName: string;
}
- @ArgsTypes()를 활용해 하나의 object를 확인하되, 전달받을 땐 분리된 형태로 받을 수 있다.
- 보통 create 등의 작업을 할 땐 하나의 object로 만들어서 전달하기보단, 내부 속성을 작성하여 분리된 형태로 받기 때문에 해당 방법이 더 유용하다고 할 수 있다.
@Mutation(returns => Boolean)
createRestaurant(
@Args() createRestaurantDto: createRestaurantDto): boolean {
return true;
}
- @Args 파라미터에 이름을 따로 명시하지 않아도된다.
- 이는 파라미터에 필요한 Argument들을 모두 하나씩 명시한 것과 같은 효과를 지닌다.
cf3. class validator와 class-transformer로 args 유효성 체크하기
$ npm i class-validator class-transformer
- class-validator와 class-transformer를 통해 args의 유효성을 체크할 수 있다.
import { ArgsType, Field } from "@nestjs/graphql";
import { IsBoolean, IsString, Length } from "class-validator";
@ArgsType()
export class createRestaurantDto {
@Field(type => String)
@IsString()
@Length(5, 10)
name: string;
@Field(type => Boolean)
@IsBoolean()
isVegan: boolean;
@Field(type => String)
@IsString()
address: string;
@Field(type => String)
@IsString()
ownerName: string;
}
- @IsString, @IsBoolean과 같은 tpye 데코레이터로 type을 확인하도록 할 수 있다.
- 뿐만 아니라 @Length 로 길이도 설정할 수 있다.
- 단, main.ts에 validationPipe를 설정해야 한다.
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe()
);
await app.listen(3000);
}
bootstrap();
- 파이프는 일종의 미들웨어로서 작동해 객체의 유효성을 체크해준다.
GraphQL Playground
- root url에서 /graphql로 접속하면 GraphQL 개발자도구인 GraphQL Playground에도 접속할 수 있다.
반응형
'🛠 기타 > WEB' 카테고리의 다른 글
Node.js - multer (파일 업로드) (0) | 2021.01.31 |
---|---|
Node.js - Sequelize (0) | 2021.01.28 |
React - GraphQL Client (with Apollo) (0) | 2021.01.12 |
React - Styled Components (0) | 2021.01.12 |
React - React Router (0) | 2021.01.11 |