간단한 1:N 관계 예제를 통해, 1:N 관계에 대한 스키마,resolver를 어떻게 작성하는지 연습합니다.
post.graphql
type Post {
id: Int!
userId: Int!
title: String!
votes: Int
}
user.graphql
type Query {
users: [User]
getUserById(id: Int!): User
}
type User {
id: Int!
name: String!
age: Int!
posts: [Post]
}
사용자(User)는 여러개의 글(Post)를 게시할 수 있습니다.
이 경우 User:Post = 1:N 관계가 성립합니다.
그리고 위와 같이 User, Post, Query 스키마를 작성할 수 있습니다.
user.resolver.ts
import { Args, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { User } from '../../autogen/schema.graphql';
import { UserService } from './user.service';
import { PostService } from '../post/post.service';
@Resolver('User')
export class UserResolver {
constructor(private readonly userService: UserService, private readonly postService: PostService) {}
@Query('users')
async getAll(): Promise<User[]> {
console.log(`getAll()`);
return await this.userService.findAll();
}
@Query('getUserById')
async getById(@Args('id') id: number) {
console.log(`getById(id: ${id})`);
return await this.userService.findOneById(id);
}
@ResolveField()
async posts(@Parent() user: User) {
console.log(`posts(user: ${JSON.stringify(user)})`);
const { id } = user;
return await this.postService.findAllByUserId(id);
}
}
post데이터는 user.id = post.userId 로 join 하여 가져올 수 있습니다.
user의 posts 필드는 위와 같이 @ResolveField()를 이용하여 postService를 통하여 데이터를 가져와서 fetch 하도록 설정할 수 있습니다.
그런데, user가 N명이면 postService.findAllByUserId()가 N번 호출되어 post db에서 데이터를 가져오는 행위를 N번 하는 비효율적인 일이 생길 수 있습니다.
이를 1:N 문제라고 하며, 이를 해결하는 방법으로 Dataloader를 많이 사용한다고 합니다.