Node, Nest, Deno/🦁 Nest - Series
Nest + graphql (3) : Mutation, @ArgsType 과 Validation
DarrenKwonDev
2020. 11. 21. 01:30
@Mutation
@Query를 통해서 쿼리를 작성하였듯 @Mutation을 @nestjs/graphql에서 가져와 @Resolver 안에 정의해서 사용할 수 있습니다.
The official Apollo documentation uses an upvotePost() mutation example. This mutation implements a method to increase a post's votes property value. To create an equivalent mutation in Nest, we'll make use of the @Mutation() decorator.
@Mutation(returns => Post)
async upvotePost(@Args({ name: 'postId', type: () => Int }) postId: number) {
return this.postsService.upvoteById({ id: postId });
}
@ArgsType
다음과 같이 간단한 Mutation을 resolver 안에 정의했다고 가정해봅시다.
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { Restaurant } from './entities/restaurant.entity'; // @ObjectType임
@Resolver((of) => Restaurant)
export class RestaurantResolver {
@Mutation(() => Boolean)
createRestaurant(
@Args('name') name: string,
@Args('address') address: string,
@Args('ownersName') ownersName: string,
@Args('isVegan') isVegan: boolean,
): boolean {
console.log(name, isVegan, address, ownersName);
return true;
}
}
지금도 작동하긴 하지만 어딘가 아쉽습니다. @Args를 반복해서 넣는 부분 때문이죠
이런 부분은 @ArgsType을 이용해서 대체할 수 있습니다. @InputType를 이용하는 방식은 직관적이지 않아 생략합니다.
import { ArgsType, Field } from '@nestjs/graphql';
@ArgsType()
export class CreateRestaurantDto {
@Field(() => String)
name: string;
@Field(() => String)
address: string;
@Field(() => String)
ownersName: string;
@Field(() => Boolean)
isVegan?: boolean;
}
@Mutation(() => Boolean)
createRestaurant(@Args() createRestaurantDto: CreateRestaurantDto): boolean {
console.log(createRestaurantDto);
return true;
}
추가적으로 @ArgsType에 Validation을 해보겠습니다. 당연히 class니까 class-validation, class-transformer 패키지를 이용할 수 있겠죠
import { ArgsType, Field } from '@nestjs/graphql';
import { IsBoolean, IsString, Length } from 'class-validator';
@ArgsType()
export class CreateRestaurantDto {
@Field(() => String)
@IsString()
@Length(5, 10)
name: string;
@Field(() => String)
@IsString()
address: string;
@Field(() => String)
@IsString()
ownersName: string;
@Field(() => Boolean)
@IsBoolean()
isVegan?: boolean;
}
class-validator를 설치했다면 검증할 수 있도록 listen 전에 GlobalPipes를 이용하여 ValidationPipe를 전역으로 사용하도로 설정해줍시다.
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
const PORT = 4000;
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(PORT);
console.log(`server on : http://localhost:${PORT}`);
}
bootstrap();