Quick start

Quick start

GraphQL์€ API์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ ์–ธ์–ด์ด๋ฉฐ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ์œ„ํ•œ ๋Ÿฐํƒ€์ž„์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ REST API์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋Ÿฌํ•œ ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์šฐ์•„ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. GraphQL๊ณผ REST ์‚ฌ์ด์—๋Š” ํ›Œ๋ฅญํ•œ ๋น„๊ตarrow-up-right๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” GraphQL์ด ๋ฌด์—‡์ธ์ง€ ์„ค๋ช…ํ•˜์ง€ ์•Š๊ณ  ์ „์šฉ @nestjs/graphql ๋ชจ๋“ˆ๋กœ ์ž‘์—…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ด ์ฑ•ํ„ฐ์—์„œ๋Š” ์ด๋ฏธ GraphQL ๊ธฐ๋ณธ ์‚ฌํ•ญ์— ์ต์ˆ™ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

GraphQLModule์€ [Apollo] (https://www.apollographql.com/arrow-up-right) ์„œ๋ฒ„์˜ ๋ž˜ํผ์— ์ง€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฐ”ํ€ด๋ฅผ ์žฌ๋ฐœ ๋ช…ํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋œ ๋ชจ๋“ˆ์„ ์ œ๊ณตํ•˜์—ฌ GraphQL๊ณผ Nest๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Installation

๋จผ์ € ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

$ npm i --save @nestjs/graphql apollo-server-express graphql-tools graphql

Overview

Nest๋Š” GraphQL ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋นŒ๋“œํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•, ์ฆ‰ ์Šคํ‚ค๋งˆ ์šฐ์„ ๊ณผ ์ฝ”๋“œ ์šฐ์„ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์Šคํ‚ค๋งˆ ์šฐ์„  ์ ‘๊ทผ๋ฒ•์—์„œ ์ง„์‹ค์˜ ๊ทผ์›์€ GraphQL SDL (์Šคํ‚ค๋งˆ ์ •์˜ ์–ธ์–ด)์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ํ”Œ๋žซํผ๊ฐ„์— ์Šคํ‚ค๋งˆ ํŒŒ์ผ์„ ๊ณต์œ  ํ•  ์ˆ˜ ์žˆ๋Š” ์–ธ์–ด์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ Nest๋Š” GraphQL ์Šคํ‚ค๋งˆ (ํด๋ž˜์Šค ๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ TypeScript ์ •์˜๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ค‘๋ณต์„ฑ์„ ์ค„์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์— ์ฝ”๋“œ ์šฐ์„  ๋ฐฉ์‹์—์„œ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์™€ TypeScript ํด๋ž˜์Šค ๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. TypeScript๋กœ ๋…์ ์ ์œผ๋กœ ์ž‘์—…ํ•˜๊ณ  ์–ธ์–ด ๊ตฌ๋ฌธ ๊ฐ„์˜ ์ปจํ…์ŠคํŠธ ์ „ํ™˜์„ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

Getting started

ํŒจํ‚ค์ง€๊ฐ€ ์„ค์น˜๋˜๋ฉด GraphQLModule์„ ๋“ฑ๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@@filename()
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';

@Module({
  imports: [
    GraphQLModule.forRoot({}),
  ],
})
export class ApplicationModule {}

.forRoot()๋ฉ”์†Œ๋“œ๋Š” ์˜ต์…˜ ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ต์…˜์€ ๊ธฐ๋ณธ Apollo ์ธ์Šคํ„ด์Šค๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค (์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์„ค์ •์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์—ฌ๊ธฐarrow-up-right. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋†€์ดํ„ฐ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ  ๋””๋ฒ„๊ทธ ๋ชจ๋“œ๋ฅผ ๋„๋ ค๋ฉด ๋‹ค์Œ ์˜ต์…˜์„ ์ „๋‹ฌํ•˜์‹ญ์‹œ์˜ค.

์–ธ๊ธ‰ ํ•œ ๋ฐ”์™€ ๊ฐ™์ด ์ด ๋ชจ๋“  ์„ค์ •์€ApolloServer ์ƒ์„ฑ์ž๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

Playground

๋†€์ดํ„ฐ๋Š” ๊ทธ๋ž˜ํ”ฝ ๋Œ€ํ™” ํ˜• ๋ธŒ๋ผ์šฐ์ € ๋‚ด GraphQL IDE์ด๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ GraphQL ์„œ๋ฒ„ ์ž์ฒด์™€ ๋™์ผํ•œ URL์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์—ด๊ณ  http://localhost:3000/graphql๋กœ ์ด๋™ํ•˜์‹ญ์‹œ์˜ค (ํ˜ธ์ŠคํŠธ ๋ฐ ํฌํŠธ๋Š” ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ).

Multiple endpoints

์ด ๋ชจ๋“ˆ์˜ ๋˜ ๋‹ค๋ฅธ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์€ ์—ฌ๋Ÿฌ ์—”๋“œ ํฌ์ธํŠธ๋ฅผ ํ•œ ๋ฒˆ์— ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๋•๋ถ„์— ์–ด๋–ค ์—”๋“œ ํฌ์ธํŠธ์— ์–ด๋–ค ๋ชจ๋“ˆ์„ ํฌํ•จํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ GraphQL์€ ์ „์ฒด ์•ฑ์—์„œ ๋ฆฌ์กธ๋ฒ„๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์˜ ์„œ๋ธŒ์…‹๋งŒ ์ œํ•œํ•˜๊ธฐ ์œ„ํ•ด include ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Schema first

์Šคํ‚ค๋งˆ๋ฅผ ๋จผ์ € ์‚ฌ์šฉํ•˜๋ ค๋ฉด options ๊ฐ์ฒด ์•ˆ์—typePaths ๋ฐฐ์—ด์„ ์ถ”๊ฐ€ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค.

typePaths ์†์„ฑ์€ GraphQLModule์ด GraphQL ํŒŒ์ผ์„ ์ฐพ์•„์•ผํ•˜๋Š” ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ชจ๋“  ํŒŒ์ผ์€ ๊ฒฐ๊ตญ ๋ฉ”๋ชจ๋ฆฌ์— ๊ฒฐํ•ฉ๋˜๋ฏ€๋กœ ์Šคํ‚ค๋งˆ๋ฅผ ์—ฌ๋Ÿฌ ํŒŒ์ผ๋กœ ๋ถ„ํ• ํ•˜์—ฌ ๋ฆฌ์กธ๋ฒ„ ๊ทผ์ฒ˜์— ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GraphQL ์œ ํ˜•๊ณผ ํ•ด๋‹น TypeScript ์ •์˜๋ฅผ ๋ณ„๋„๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ์ค‘๋ณต์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ, ์šฐ๋ฆฌ๋Š” ๋‹จ์ผํ•œ ์ง„์‹ค์˜ ์›์ฒœ์—†์ด ๊ฒฐ๊ตญ SDL ๋‚ด์—์„œ ์ด๋ฃจ์–ด์ง„ ๊ฐ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋„ ์กฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ@nestjs/graphql ํŒจํ‚ค์ง€๋Š” ๋˜ ๋‹ค๋ฅธ ํฅ๋ฏธ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, ์ด๋Š” ์ถ”์ƒ ๊ตฌ๋ฌธ ํŠธ๋ฆฌ (AST)๋ฅผ ์‚ฌ์šฉํ•œ TS ์ •์˜์˜ ์ž๋™ ์ƒ์„ฑ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒํ•˜๋ ค๋ฉด definitions ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

src/graphql.ts๋Š” TypeScript ์ถœ๋ ฅ์„ ์ €์žฅํ•  ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ์œ ํ˜•์ด ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ outputAs ์†์„ฑ์„ class๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋Œ€์‹  ํด๋ž˜์Šค๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ฐ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘์‹œ ์œ ํ˜• ์ •์˜๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‹ , ์ „์šฉ ๋ช…๋ น์ด ์‹คํ–‰๋  ๋•Œ๋งŒ ์™„์ „ํžˆ ์ œ์–ดํ•˜๊ณ  ์ž…๋ ฅ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ generate-typings.ts๋ผ๊ณ  ํ•˜๋Š” ์ž์ฒด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ„๋‹จํžˆ ํŒŒ์ผ์„ ์‹คํ–‰ํ•˜์‹ญ์‹œ์˜ค.

info ํžŒํŠธ ๋ฏธ๋ฆฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  ๋Œ€์‹  node ์‹คํ–‰ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ์‹œ ๋ชจ๋“œ๋กœ ์ „ํ™˜ํ•˜๋ ค๋ฉด (.graphql ํŒŒ์ผ ๋ณ€๊ฒฝ์‹œ ์ž๋™์œผ๋กœ ์ž…๋ ฅ์„ ์ƒ์„ฑ) watch ์˜ต์…˜์„ generate()๋ฉ”์†Œ๋“œ์— ์ „๋‹ฌํ•˜์‹ญ์‹œ์˜ค.

์™„์ „ํžˆ ์ž‘๋™ํ•˜๋Š” ์ƒ˜ํ”Œ์€ ์—ฌ๊ธฐarrow-up-right์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Code first

์ฝ”๋“œ ์šฐ์„  ๋ฐฉ๋ฒ•์—์„œ๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์™€ TypeScript ํด๋ž˜์Šค ๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

Nest๋Š”์ด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ํ›„๋“œ ์•„๋ž˜์—์„œ ๋†€๋ผ์šด type-graphqlarrow-up-right ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ณ„์† ์ง„ํ–‰ํ•˜๊ธฐ ์ „์— ์ด ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์„ค์น˜ ๊ณผ์ •์ด ์™„๋ฃŒ๋˜๋ฉด, autoSchemaFile ์†์„ฑ์„ ์˜ต์…˜ ๊ฐ์ฒด์— ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

autoSchemaFile์€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ์Šคํ‚ค๋งˆ๊ฐ€ ์ƒ์„ฑ๋  ๊ฒฝ๋กœ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๋˜ํ•œ buildSchemaOptions ์†์„ฑ-type-graphql ํŒจํ‚ค์ง€์—์„œ buildSchema()ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋Š” ์˜ต์…˜ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™„์ „ํžˆ ์ž‘๋™ํ•˜๋Š” ์ƒ˜ํ”Œ์€ ์—ฌ๊ธฐarrow-up-right์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Async configuration

๋ชจ๋“ˆ ์˜ต์…˜์„ ๋ฏธ๋ฆฌ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  ๋น„๋™๊ธฐ์‹์œผ๋กœ ์ „๋‹ฌํ•˜๋ ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” forRootAsync()๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

๊ฐ€๋Šฅํ•œ ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ํŒฉํ† ๋ฆฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ถ„๋ช…ํžˆ, ์šฐ๋ฆฌ ํŒฉํ† ๋ฆฌ๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์ฒ˜๋Ÿผ ํ–‰๋™ํ•ฉ๋‹ˆ๋‹ค ( async์ผ ์ˆ˜๋„ ์žˆ๊ณ  inject์„ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).

๋˜๋Š” ํŒฉํ† ๋ฆฌ ๋Œ€์‹  ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์˜ ๊ตฌ์„ฑ์€ GraphQLModule ๋‚ด์—์„œ GqlConfigService๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•˜๊ณ  ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์˜ต์…˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. GqlConfigService๋Š” GqlOptionsFactory ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

GraphQLModule ๋‚ด์— GqlConfigService๊ฐ€ ์ž‘์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ ๊ฐ€์ ธ์˜จ ์ œ๊ณต์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉดuseExisting ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋‚˜์˜ ์ค‘์š”ํ•œ ์ฐจ์ด์ ์œผ๋กœ useClass์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. GraphQLModule์€ ๊ฐ€์ ธ์˜จ ๋ชจ๋“ˆ์„ ์กฐํšŒํ•˜์—ฌ ์ด๋ฏธ ์ƒ์„ฑ๋œ ConfigService๋ฅผ ์ž์ฒด์ ์œผ๋กœ ์ธ์Šคํ„ด์Šคํ™” ํ•˜๋Š” ๋Œ€์‹  ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Last updated