안녕하세요. 주니어 백엔드 개발자 입니다.
심바 블로그
안녕하세요. 주니어 백엔드 개발자 입니다.
>> Github 바로가기
  • 분류 전체보기 (31)
    • AWS (3)
    • DATABASE (2)
    • Docker (1)
    • Architecture (3)
    • GraphQL (5)
    • JS (1)
    • NestJS (8)
    • 테스트 코드 (3)
    • 세미나 (4)
    • 기타 (1)
    • 이전 블로그 자료들 (0)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
안녕하세요. 주니어 백엔드 개발자 입니다.

심바 블로그

TypeScript로 GraphQL 사용할 때의 문제
GraphQL

TypeScript로 GraphQL 사용할 때의 문제

2022. 9. 28. 15:14
반응형

TypeScript로 GraphQL 사용할 때의 문제

문제

  • graphQL은 gql을 사용해 graphQL에서 사용할 데이터의 타입을 다음과 같은 형태로 지정해줘야 한다. (숫자는 Int, 문자열은 String)
    사실 이것만 생각하면 별 문제가 없지만 TypeScript와 (or TypeORM) 함께 사용하게되면 귀찮은 일이 발생한다.
    바로 TypeScript와 graphQL의 타입 형태가 다르다는 점이다.
// graphQL에서의 타입 정의
type User {
          id: ID!
        userId: Int
        name: String
        email: String
        company: String
    }

// TypeScript에서의 타입 정의
interface User {
          id: string;
        userId: number;
          name: string;
          email: string;
          company: string;
    }
  • 보이는 것처럼 타입의 형태가 달라 각각 따로 지정해줘야하기 때문에 귀찮아진다. 하지만 당연하게 이런 중복된 타입 지정을 도와주는 프레임워크가 존재한다. 바로 Type-GraphQL이다. (Prisma써도 됨)

 

Type-GraphQL

  1. 설치 (reflect-metadata, type-graphql)
npm i reflect-metadata type-graphql
  • reflect-metadata는 데코레이터 문법을 사용하기 위해 설치하는 라이브러리.
  1. 예제 코드
// 기타 apollo-server나 express등은 생략함...

import 'reflect-metadata';
import { ObjectType, ID, buildSchema, Resolver, Query } from 'type-graphql';
import { Inject, Service, Container } from 'typedi';

@Service()
class UserRepository {
    async getUserss() {
        const [rows] = await connection.query(`
            SELECT *
            FROM Users
            `);
        return rows;
    }
}

@ObjectType()
class User {
    @Field(() => ID)
    userId!: string;
    @Field()
    name!: string;
    @Field({ nullable: true })
    email!: string;
    @Field()
    company!: string;
}


@Service()
@Resolver()
class UserResolver {
    constructor(private dependencies: UserRepository) {}

    @Query(() => [User])
    async getUsers() {
        const rows = await this.dependencies.getUserss();
        return rows;
    }
}

Promise.resolve()
    .then(() =>
        buildSchema({
            resolvers: [UserResolver],
            container: Container,
        }),
    )
    .then(schema => new ApolloServer({ schema }))
    .then(apolloServer => {
        apolloServer.start().then(res => {
            apolloServer.applyMiddleware({
                app,
                path: '/graphql',
            });

            app.listen(3000, () => {
                console.log(`server listening on port 3000`);
            });
        });
    });

- 사실 계층화를 해줘야하지만 코드설명을 위해 그냥 한 파일에 나열함.

  • 코드를 하나하나 살펴보면 먼저 type-graphql 라이브러리에서 필요한 메서드들을 불러오고
  • 비즈니스 로직과 데이터베이스 로직을 분리하기 위해서 UserRepository를 만들어주고
  • 기존 gql에서 사용하던 타입선언을 User 클래스에서 @ObjectType()를 선언해 하나로 묶어주고
    (이때 @Field가 graphQL 타입 선언 부분. String은 생략가능)
  • UserResolver 클래스에 비즈니스 로직을 작성함.

 

TypeDi

  • 해당 코드를 의존성 주입 관점에서 보면 UserResolver 클래스의 생성자에서 UserRepository를 주입 받아 느슨하게 결합됨.
  • 하지만 graphQL 특성상 UserResolver 클래스를 인스턴스화 하지 않고 알아서 Apollo-server에서 구현되기 때문에 UserRepository를 인식하지 못하는 문제가 발생함.
  • 이를 해결하기 위해 TypeDi 라이브러리를 통해 의존성 주입을 할 수 있음.
  • 의존성 주입을 하려는 클래스들에 @Service 데코레이터를 작성하고, buildSchema의 옵션으로 container:Container를 입력해주면 끝. 자세한건 아래 링크
    Type-GraphQL docs
반응형

'GraphQL' 카테고리의 다른 글

nestjs-query_02_Hook, Authorize  (0) 2024.01.14
nestjs-query_01_세팅  (1) 2024.01.10
Nest + Graphql 구현하기  (0) 2022.09.29
Express + Graphql 좀 더 구조적으로 짜기 (+ Type-graphql, Typegoose, Typedi)  (0) 2022.09.29
    'GraphQL' 카테고리의 다른 글
    • nestjs-query_02_Hook, Authorize
    • nestjs-query_01_세팅
    • Nest + Graphql 구현하기
    • Express + Graphql 좀 더 구조적으로 짜기 (+ Type-graphql, Typegoose, Typedi)
    안녕하세요. 주니어 백엔드 개발자 입니다.
    안녕하세요. 주니어 백엔드 개발자 입니다.

    티스토리툴바