Nest.js로 GraphQL API를 구축하는 방법은 무엇인가요?
이 문서에서는 깔끔한 아키텍처와 유형 안전성을 활용하여 NestJS로 GraphQL API를 빌드하는 방법을 알아봅니다.
NestJS는 유형 안전성과 엄격한 아키텍처 패턴을 제공하여 사용자가 확장 가능한 엔터프라이즈급 백엔드 애플리케이션을 만들 수 있도록 도와주는 NodeJS 프레임워크입니다.
GraphQL은 속도와 안정성으로 인해 REST의 대안으로 널리 사용되는 애플리케이션 프로그래밍 인터페이스(API)용 쿼리 언어로, 쿼리가 요청하는 데이터를 정확하게 응답함으로써 그 성능을 발휘합니다. 이 GraphQL 기능은 REST에서 발생하는 오버페칭 및 언더페칭 문제를 해결합니다.
Contents
개발 환경 설정
시스템에 Nest.js CLI가 전역적으로 설치되어 있지 않은 경우 아래 명령을 실행하여 설치하세요:
npm i -g @nestjs/cli
Nest.js CLI에는 개발 프로세스를 간소화하는 상용구 코드를 생성하는 데 도움이 되는 몇 가지 명령어가 포함되어 있습니다.
그런 다음 아래 명령을 실행하여 프로젝트를 만들고 필요한 스타터 파일을 생성합니다:
nest new graphql-api
그런 다음 아래 명령을 실행하여 프로젝트 디렉토리에 cd를 합니다:
cd graphql-api
그런 다음 아래 명령을 실행하여 필요한 종속성을 설치합니다:
npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-express
위에 설치된 종속성에는 다음이 포함됩니다:
nest/graphql
nestjs/apollo
graphql
apollo-server-express
그런 다음 아래 명령을 실행하여 TypeORM 패키지와 sqlite 데이터베이스 드라이버를 설치합니다:
npm install @nestjs/typeorm typeorm sqlite3
데이터베이스에 연결하고, 읽고, 쓰려면 위에 설치한 패키지가 필요합니다.
Nest.js에서 GraphQL 구성
Nest.js는 코드 우선 접근 방식과 스키마 우선 접근 방식의 두 가지 GraphQL API 생성 방법을 제공합니다.
코드 우선 접근 방식은 TypeScript 데코레이터와 클래스를 사용하여 해당 GraphQL 스키마를 생성하는 것이 특징입니다.
스키마 우선 접근 방식은 GraphQL 스키마 정의 언어(SDL) 파일을 사용하는 것이 특징이며, Nest.js는 GraphQL 스키마에 기반한 클래스 또는 인터페이스를 사용하여 TypeScript 정의를 생성합니다.
이 튜토리얼에서는 서로 다른 언어 간의 컨텍스트 전환을 피하기 위해 코드 우선 접근 방식을 사용합니다.
코드 우선 접근 방식을 사용하려면 애플리케이션의 엔트리 파일인 app.module.ts로
이동하여 @nestjs/graphql에서
GraphQLModule을
가져오세요. 이렇게 하세요:
import { GraphQLModule } from '@nestjs/graphql';
그런 다음 가져오기
배열에서 GraphQLModule의
forRoot
메서드를 호출합니다. 이 메서드는 구성 객체를 인수로 받습니다. 구성 옵션은 기본 GraphQL 드라이버를 통해 전달됩니다(이 자습서에서는 Apollo 드라이버를 사용합니다). 구성 개체의 autoSchemaFile
속성을 schema.gql로
설정합니다. 이렇게 설정합니다:
//app.module.ts
GraphQLModule.forRoot({ autoSchemaFile: 'schema.gql' }),
자동 스키
마 파일
속성은 자동으로 생성된 스키마가 저장될 파일 경로입니다.
데이터베이스에 연결하기
애플리케이션을 데이터베이스에 연결하려면 app.module.ts
파일로 이동하여 @nestjs/typeorm에서
TypeOrmModule을
가져오세요.
이렇게요:
import { TypeOrmModule } from '@nestjs/typeorm';
다음으로 가져오기
배열에 아래 코드 블록을 추가합니다:
TypeOrmModule.forRoot({
type: 'sqlite',
database: ':memory:',
entities: ['dist/**/*.entity{.ts,.js}'],
synchronize: true,
}),
위의 코드 블록은 애플리케이션과 Sqlite 데이터베이스 사이에 데이터베이스 연결을 생성하고 애플리케이션의 모든 모듈에서 연결을 공유합니다.
리소스 생성
그런 다음 아래 명령을 실행하여 코드를 정리하는 모듈을 만듭니다:
nest g module blog
위의 명령은 애플리케이션에 대한 블로그 모듈을 생성합니다.
그런 다음 아래 명령을 실행하여 서비스를 생성합니다:
nest g service blog
위의 코드 블록은 애플리케이션에 서비스를 생성하고 등록합니다. 이 서비스는 애플리케이션의 모든 비즈니스 로직을 포함하고 처리합니다.
다음으로 아래 명령을 실행하여 리졸버를 생성합니다:
nest g resolver
위의 코드 블록은 애플리케이션에서 리졸버를 생성하고 등록합니다. 해석기는 GraphQL 쿼리 및 변형을 데이터로 변환하기 위한 지침을 지정하고 스키마에 지정된 데이터의 형태를 동기 또는 비동기식으로 반환합니다.
엔티티 만들기
엔티티는 데이터베이스에 데이터가 저장되는 방식을 지정하는 필드 모음입니다.
엔티티를 만들려면 모듈 폴더(블로그)에서 .entity.ts
규칙에 따라 엔티티 파일을 만듭니다(예: blog.entity.ts
).
엔티티 파일에서 typeform에서
Column
, Entity
및 PrimaryGeneratedColumn을
가져옵니다. 이렇게 하세요:
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
열
데코레이터는 주석이 달린 필드를 데이터베이스의 열로 추가합니다. 엔티티
데코레이터는 주석이 달린 클래스를 엔티티로 표시합니다. PrimaryGeneratedColumn
데코레이터는 주석이 달린 프로퍼티를 테이블의 고유 식별자로 표시하고 자동으로 생성합니다.
다음으로 Blog
클래스를 만들고 내보냅니다. 그런 다음 엔티티
데코레이터를 사용하여 클래스에 주석을 달아 엔티티로 표시합니다. 이렇게 하세요:
@Entity()
export class Blog {}
이 튜토리얼에서는 블로그 API를 사용하므로 아이디, 제목, 본문, 작성자 및 날짜 속성을 클래스에 추가합니다. 그런 다음 id
속성을 제외한 각 속성에 Column
데코레이터를 사용하여 주석을 추가합니다. id
속성에 PrimaryGeneratedColumn
데코레이터를 사용하여 주석을
추가합니다.
이렇게요:
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Blog {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
body: string;
@Column()
author: string;
@Column()
date: string;
}
객체 유형 만들기
객체 유형은 클라이언트가 상호 작용해야 하는 객체를 나타내는 GraphQL 스키마 정의입니다. 예를 들어, 블로그 API를 빌드하는 경우 TypeScript 클래스로 블로그 스키마/엔터티를 정의하고 각 필드에 적절한 데코레이터를 주석으로 지정해야 합니다.
그런 다음 엔티티 파일에서 @nestjs/graphql에서
Int
유형과 필드
및 객체 유형
데코레이터를 가져옵니다. 이렇게 하세요:
import { Field, Int, ObjectType } from '@nestjs/graphql';
필드
데코레이터는 특정 클래스 속성을 GraphQL 필드로 표시합니다. 이 데코레이터로 주석이 달린 속성만 스키마에 정의됩니다. 선택적 반환 유형 함수와 구성 객체를 인수로 받아들입니다.
Int
유형은 TypeScript와 GraphQL 유형 시스템 간의 잠재적인 모호성을 제거하기 위해 필요합니다. 숫자 값이 정수이거나 실수일 수 있으므로 숫자 값이 있는 프로퍼티에만 필요합니다.
ObjectType
데코레이터는 클래스를 GraphQL 유형으로 표시합니다.
그런 다음 ObjectType
데코레이터를 사용하여 블로그 클래스에 주석을 달아 그래프QL 유형으로 표시합니다. 이렇게 하세요:
@ObjectType()
export class Blog {}
마지막으로 클래스 내에서 유형에 필요한 속성을 지정하고 필드
데코레이터를 사용하여 각 속성에 주석을 달면 됩니다. 예를 들어
//blog.entity.ts
import { Field, Int, ObjectType } from '@nestjs/graphql';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
@ObjectType()
export class Blog {
@PrimaryGeneratedColumn()
@Field((type) => Int)
id: number;
@Column()
@Field()
title: string;
@Column()
@Field()
body: string;
@Column()
@Field()
author: string;
@Column()
@Field()
date: string;
}
완성된 객체 유형은 위의 코드 블록과 같아야 합니다.
위의 코드 블록에서 숫자
유형이 있는 ID는
TypeScript와 GraphQL 유형 시스템 간의 모호성을 피하기 위해 정수로 명시적으로 지정되었음을 알 수 있습니다.
마지막으로 엔티티를 애플리케이션에 삽입하여 애플리케이션과 데이터베이스 사이에 액세스 계층을 생성합니다.
이렇게 하려면 blog.module.ts
파일로 이동하여 @nestjs/typeorm에서
TypeOrmModule을
가져온 다음 블로그 엔티티를 가져오세요.
그런 다음 모듈 데코레이터에 아래 코드 블록을 추가합니다:
imports: [TypeOrmModule.forFeature([Blog])],
위의 코드 블록은 애플리케이션과 데이터베이스 사이의 액세스 계층 역할을 하는 리포지토리를 생성합니다.
서비스 만들기
이전에 생성한 서비스 파일인 blog.service.ts로
이동하여 @nestjs/typeorm
및 개체 유형에서 InjectRepository를
가져옵니다.
이렇게요:
import { InjectRepository } from '@nestjs/typeorm';
import { Blog } from './blog.entity';
그런 다음 아래 코드 블록을 BlogService
클래스에 추가하여 리포지토리를 삽입합니다:
constructor(
@InjectRepository(Blog)
private blogRepository: Repository<Blog>,
) {}
그런 다음 서비스 클래스에 아래 코드 블록을 추가하여 데이터베이스의 모든 블로그를 검색하는 로직을 구현합니다:
async getAll(): Promise<Blog[]> {
return await this.blogRepository.find();
}
다음으로 데이터베이스에 새 블로그를 추가하는 로직을 구현해야 하는데, 먼저 입력 유형을 만들어야 합니다.
입력 유형 만들기
복잡한 객체를 사용하는 돌연변이에 대한 입력 유형을 만들려면 블로그
폴더에 dtos
폴더를 만듭니다. 그런 다음 dtos
폴더에 create-blog.input.ts라는
새 파일을 만듭니다.
create-blog.input.ts
파일에서 필드
및 입력 유형
데코레이터를 가져옵니다. 이렇게 하세요:
import { Field, InputType } from '@nestjs/graphql';
InputType
데코레이터는 클래스를 GraphQL 입력 유형으로 표시합니다.
다음으로 BlogInput
클래스를 만들고 내보냅니다. 그런 다음 InputType
데코레이터를 사용하여 클래스에 주석을 달면 됩니다. 이렇게 하세요:
@InputType()
export class BlogInput {}
마지막으로 필요한 모든 블로그 속성을 추가하고 필드
데코레이터로 주석을 달면 됩니다.
이렇게요:
//create-blog.input.ts
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class BlogInput {
@Field()
id: number;
@Field()
title: string;
@Field()
body: string;
@Field()
author: string;
@Field()
date: string;
}
완성된 입력 유형은 위의 코드 블록과 같아야 합니다.
그런 다음 입력 유형을 서비스 파일로 가져오고 아래 코드 블록을 서비스 클래스에 추가하여 데이터베이스에 블로그를 추가하는 로직을 구현합니다:
async createBlog(blogInput: BlogInput): Promise<Blog> {
const newBlog = this.blogRepository.create(blogInput);
return this.blogRepository.save(newBlog);
}
입력 유형은 들어오는 데이터에 대한 유효성 검사 메커니즘으로 일반 Nest.js 데이터 전송 객체가 적용되는 것과 동일한 방식으로 적용됩니다. dtos와 마찬가지로 클래스 유효성
검사기 패키지를 사용하여 데이터에 대한 추가 유효성 검사를 수행할 수도 있습니다.
리졸버 생성
이전에 생성한 해결사 파일인 blog.resolver.ts로
이동하여 엔티티, 입력 유형 및 서비스를 가져옵니다. 이렇게 하세요:
import { Blog } from './blog.entity';
import { BlogService } from './blog.service';
import { BlogInput } from './dto/create-blog.input';
다음으로, 아래 코드 블록을 리졸버 클래스에 추가하여 서비스를 리졸버에 삽입합니다:
constructor(private blogService: BlogService) {}
다음으로 @nestjs/graphql에서
Args
, Mutation
및 Query
데코레이터를 가져옵니다.
이렇게요:
import { Args, Mutation, Query } from '@nestjs/graphql';
Args
데코레이터는 기본 플랫폼에서 인수 객체를 추출하고 모든 인수 또는 지정된 단일 인수의 값으로 데코레이션된 매개변수를 채웁니다.
돌연변이
데코레이터는 경로를 돌연변이로 지정합니다.
쿼리
데코레이터는 경로를 쿼리로 지정합니다.
그런 다음 아래 함수를 리졸버
데코레이터에 전달하여 객체 유형을 지정합니다:
(of) => Blog
그런 다음 아래 코드 블록을 Resolver 클래스에 추가하여 getAll
메서드를 해결합니다.
@Query((type) => [Blog])
async getAllBlogs() {
return this.blogService.getAll();
}
마지막으로, 아래 코드 블록을 Resolver 클래스에 추가하여 createBlog
메서드를 해결합니다.
@Mutation((returns) => Blog)
createBlog(@Args('blogInput') blogInput: BlogInput): Promise<Blog> {
return this.blogService.createBlog(blogInput);
}
참고: 각 데코레이터에 대해 반환 유형 함수를 지정해야 합니다.
완성된 리졸버 클래스는 아래 코드 블록과 같아야 합니다:
@Resolver((of) => Blog)
export class BlogResolver {
constructor(private blogService: BlogService) {}
@Query((type) => [Blog])
async getAllBlogs() {
return this.blogService.getAll();
}
@Mutation((returns) => Blog)
createBlog(@Args('blogInput') blogInput: BlogInput): Promise<Blog> {
return this.blogService.createBlog(blogInput);
}
}
GraphQL 플레이그라운드를 사용하여 API 테스트
기본적으로 제공되는 GraphQL 플레이그라운드를 사용하여 애플리케이션을 테스트하려면 아래 명령을 실행하고 http://localhost:3000/graphql 으로 이동합니다.
npm start
다음으로 아래 이미지와 같이 쿼리 및 변형을 테스트할 수 있는 놀이터가 표시됩니다.
데이터베이스에서 모든 블로그를 검색하려면 아래 쿼리를 실행하세요:
query getAll{
getAllBlogs {
id,
title,
body,
author,
date
}
}
아래 이미지에 예시가 나와 있습니다:
데이터베이스에 블로그를 추가하려면 아래의 변형을 실행하세요:
mutation createBlog {
createBlog (blogInput: {
id: 1,
title: "GraphQL is great",
body: "GraphQL APIs are faster than REST APIs",
author: "David Ekete",
date: "01-02-03"
}) {
id,
title,
body,
author,
date,
}
}
아래 이미지에 예시가 나와 있습니다:
Back4app 및 GraphQL
데이터 가져오기 제어와 같이 GraphQL이 REST에 비해 갖는 많은 장점으로 인해 Back4app 플랫폼은 플랫폼에서 실행되는 구문 분석 애플리케이션에 통합된 GraphQL API를 제공합니다.
이 통합을 통해 서버의 백엔드 상태를 확인하고, 간단한 GraphQL 쿼리 및 변형을 작성하여 데이터베이스에 대한 CRUD(생성, 읽기, 업데이트, 삭제) 작업을 수행하는 등 다양한 작업을 수행할 수 있습니다.
예를 들어 GraphQL API를 사용하여 백엔드 서버의 상태를 확인하려면 아래 쿼리를 실행하세요:
query Health {
health
}
위의 쿼리가 반환됩니다:
{
"data": {
"health": true
}
}
GraphQL 기능을 시작하려면 분석 대시보드로 이동하여 앱을 선택하고 클릭합니다. 앱의 UI에서 코어를 선택하고 클릭한 다음 API 콘솔을 선택하고 클릭한 다음 GraphQL 콘솔을 선택합니다.
위의 지침을 따르면 개발에서 사용한 GraphQL 놀이터와 유사한 쿼리 및 변형을 실행할 수 있는 GraphQL 콘솔이 열립니다. Back4app의 GraphQL 기능에 대한 자세한 내용은 Back4app 문서에서 확인할 수 있습니다.
결론
이 문서에서는 Nest.js에서 GraphQL API를 만들고 GraphQL 플레이그라운드를 사용하여 API를 테스트하는 방법에 대해 설명했습니다. GraphQL API는 REST API에 비해 몇 가지 장점이 있습니다.
하지만 모든 애플리케이션에 이상적인 것은 아닙니다. 애플리케이션에 적합한 것을 선택하기 전에 GraphQL과 REST의 장단점을 고려해야 합니다.
GraphQL 또는 REST 중 어떤 것을 선택하든 애플리케이션을 배포해야 합니다. Back4app은 재사용 가능한 템플릿을 사용하여 반복적인 작업을 없애고 대부분의 백엔드 인프라를 관리함으로써 백엔드 구축 프로세스를 간소화하는 오픈 소스 기술 기반의 로우코드 BaaS입니다.
Back4app의 일부 기능에는 실시간 데이터베이스, 클라우드 기능, 네이티브 API 및 SDK, 완벽한 사용자 관리 시스템 등이 있습니다.
이 플랫폼에는 수수료를 지불하지 않고 플랫폼을 탐색할 수 있는 무료 티어도 있습니다.
행복한 건물!
자주 묻는 질문
GraphQL이란?
GraphQL은 Facebook이 2012년에 만든 API를 위한 오픈소스 데이터 쿼리 및 조작 언어입니다.
Nest.JS란 무엇인가요?
Nest.JS는 효율적이고 확장 가능한 서버 사이드 애플리케이션을 구축하기 위한 오픈소스 Node.js 프레임워크입니다.
Nest.JS로 GraphQL API를 만드는 방법은?
– Nest.js에서 GraphQL 구성
– 데이터베이스에 연결
– 리소스 생성
– 엔티티 생성
– 객체 유형 생성
– 서비스 생성