TypeGraphQL
TypeScript
와 GraphQL
을 함께 사용하려고 한다면 TypeScript
가 생산성을 감소시키는 복병이 될 수 있습니다. 편하게 작업하려고 도입한 TypeScript
가 오히려 개발을 어렵게 만들다니. 이게 어떻게 된 걸까요?
타입 불일치
문제는 SDL
과 Actual Type
이 일치하지 않을 때 발생합니다. Int
라고 써놓고 String
으로 읽는다거나 nullable
을 빼먹는다거나... 문제는 이런 상황이 의외로 흔하고, 에러가 발생하기 전까지는 눈치채기도 어렵다는 것 입니다.
// SDL
type book {
title : String!
price : Int
}
// TypeScript
class book {
title : string;
price : number; //< type mismatch. (must be nullable)
}
이것은 당연히 스키마를 수정하는 비용도 증가시키는데, SDL
이 변경되면 TypeScript
도 수정해야 한다는 것이죠. 잘못 수정하는 날에는 고난이도의 틀린 그림 찾기
가 펼쳐질 수 있습니다. 🥶
어디서 본 것 같은데?
슬슬 어디서 익숙한 느낌이 드실 겁니다. 사실 이것은 이미 겪었고 이미 해결했던 문제이기 때문이죠. 바로 database
에서 말이지요. 데이터베이스의 table
을 class
로 표현하려고 할 때 겪은 문제들이며 객체-관계 매핑(ORM
)을 통해서 해결한 문제이기도 합니다.
import {Entity, Column} from "typeorm"
@Entity()
class Book extends BaseEntity{
@Column()
title !: string
@Column({ default: null, nullable: true })
price ?: number
}
이것을 GraphQL
로 가져오면 편할 것 같지 않나요? TypeGraphQL
이 바로 이러한 기능을 제공합니다. class
만 정확하게 작성한다면 SDL
은 더 이상 신경쓰지 않아도 됩니다. 😄
@ObjectType()
class Book {
@Field()
title !: string;
@Field({nullable: true})
price ?: number;
}
Getting Start
TypeScript 프로젝트 생성
새로운 타입스크립트 프로젝트를 생성합니다. 소스 코드는 src/
에 작성하겠습니다.
mkdir new_project
cd new_project
npm init -y
npm install @types/node typescript -D
npx tsc --init
mkdir src
tsconfig.json
에서 소스파일 루트를 수정합니다.
//
// tsconfig.json
{
"compilerOptions": {
"rootDir": "./src"
}
}
라이브러리 설치
Apollo
, TypeGraphQL
과 각각의 필수 라이브러리를 설치합니다.
npm install apollo-server graphql
npm install type-graphql class-validator reflect-metadata
type-graphql
은 es2018
이상의 문법, decorator
, decorator-metadata
를 사용하기 때문에 tsconfig.json
에서 해당 기능을 활성화시켜줍니다.
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018", "esnext.asynciterable"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
Hello World!
다음 소스코드를 ./src/index.ts
로 저장합니다.
//
// reflect-metadata는 프로그램 진입점 최상단에 적어야 한다.
import "reflect-metadata";
import { Resolver, Query, buildSchemaSync } from "type-graphql";
import { ApolloServer } from "apollo-server";
@Resolver()
class MyFirstResolver {
@Query(() => String)
hello(): string {
return "world!";
}
}
//
// 클래스 형태의 리졸버로 스키마를 생성한다.
const schema = buildSchemaSync({
resolvers: [MyFirstResolver],
});
//
// 만들어진 스키마를 아폴로에 넘긴다.
const server = new ApolloServer({ schema });
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
컴파일 없이 소스코드를 실행하기 위해 ts-node
를 사용합니다.
npm install ts-node -D
npx ts-node ./src/index.ts
[output]
Server ready at http://localhost:4000/
첫번째 서버가 실행되었습니다! 출력된 주소에서 hello
를 가져오는 쿼리를 작성하면 world!
문자열이 반환됩니다.
'# GraphQL > TypeGraphQL' 카테고리의 다른 글
[TypeGraphQL] 상속, Inheritance (0) | 2020.07.04 |
---|---|
[TypeGraphQL] @EnumType (0) | 2020.06.18 |
[TypeGraphQL] Scalar (0) | 2020.06.14 |
[TypeGraphQL] @InputType, @ArgsType (0) | 2020.06.13 |
[TypeGraphQL] 기본 자료형과 @ObjectType (0) | 2020.06.08 |