Nest + Graphql + Mongoose
최근에 Express환경에서 Graphql을 구현할 일이 있었다. 원하는대로 완성은 했지만 자유도가 높은 Express 환경에서 구현하다보니 원하는 아키텍처를 구현하는데 어려움(+ 귀찮음)이 있었다.
그래서 이번엔 어느정도 아키텍처가 세팅되어있는 Nest 환경에서 Graphql을 구현해보려고 한다.
Express + Graphql에서 나타났던 문제들
첫 번째로 타입 중복선언과 두 번째로 의존성 주입패턴이 있다. 타입 중복선언은 graphql의 typeDef 선언과 DB schema가 따로 선언되는 문제였고, 의존성 주입패턴은 Express에서 구현하다보니 DI나 IoC의 개념들도 직접 구현해줘야 하는 문제들이었다. 하지만 해당 문제들은 Nest에서 기본으로 제공하는 기능들을 통해 해결할 수 있었다.
1. 타입 중복선언
Nest에선 Type-graphql 라이브러리를 사용하지 않더라도 @nestjs/graphql 라이브러리 내에 @ObjectType() 이라는 데코레이터를 지원한다.
또한 @nestjs/mongoose 라이브러리 내에 @Schema() 데코레이터와 @Prop() 데코레이터를 통해 graphql의 타입과 DB schema를 하나의 class에서 관리할 수 있다.
// src/entities/User.entity.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Field, ObjectType } from '@nestjs/graphql';
export type UserDocument = User & Document;
@Schema()
@ObjectType()
export class User {
@Prop({ required: true })
@Field({ nullable: true })
readonly userId: string;
@Prop({ required: false })
@Field({ nullable: true })
readonly group: string;
@Prop({ required: true, unique: true, type: String })
@Field({ nullable: true })
readonly email: string;
@Prop({ required: false })
@Field({ nullable: true })
readonly phone: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
이렇게 Nest에 내장된 라이브러리만으로도 쉽게 구현이 가능하다.
2. 의존성 주입패턴
사실 Nest는 module과 @Service() 데코레이터를 통해 DI(의존성 주입) 과 IoC(제어 역전)를 지원한다.
먼저 최상위 module에서 GraphQLModule과 UsersModule을 imports해준다.
// src/app.module.ts
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
playground: false,
plugins: [ApolloServerPluginLandingPageLocalDefault()],
}),
MongooseModule.forRoot(DB 주소),
UsersModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
UsersModule과 같이 추가되는 module에는 controller가 없기 때문에 resolver와 service 모두 provider 위치에 입력해준다.
import { Args, Query, Resolver } from '@nestjs/graphql';
import { UsersService } from './users.service';
import { User } from '../entities/User.entity';
@Resolver('User')
export class UsersResolver {
constructor(private usersService: UsersService) {}
@Query(() => [User])
async getUsers(@Args('userId') userId: string) {
return await this.usersService.getUsers(userId);
}
}
이렇게 Nest를 환경에서는 다른 라이브러리를 설치할 필요없이 Nest에서 기본적으로 제공하는 라이브러리를 통해 쉽게 좀 더 구조적인 Graphql 환경을 구성할 수 있다.
끝
'GraphQL' 카테고리의 다른 글
nestjs-query_02_Hook, Authorize (0) | 2024.01.14 |
---|---|
nestjs-query_01_세팅 (1) | 2024.01.10 |
Express + Graphql 좀 더 구조적으로 짜기 (+ Type-graphql, Typegoose, Typedi) (0) | 2022.09.29 |
TypeScript로 GraphQL 사용할 때의 문제 (0) | 2022.09.28 |