สร้าง API ด้วย NestJS GraphQL ฉบับนักพัฒนาไทย

สร้าง RESTful API ด้วย NestJS และ GraphQL สำหรับนักพัฒนาชาวไทย

  • Estimated reading time: 20 minutes

Key takeaways:

  • NestJS และ GraphQL เป็นเครื่องมือที่ทรงพลังสำหรับการสร้าง API ที่มีประสิทธิภาพและทันสมัย
  • NestJS ช่วยให้การพัฒนา backend เป็นระเบียบและง่ายต่อการดูแลรักษาด้วย TypeScript และโครงสร้าง modular
  • GraphQL ช่วยลดปัญหา over-fetching และ under-fetching ทำให้ API มีประสิทธิภาพมากยิ่งขึ้น
  • การเชื่อมต่อกับ Database สามารถทำได้ง่ายโดยใช้ module ที่ชื่อว่า @nestjs/typeorm หรือ @nestjs/mongoose
  • การจัดการ Authentication และ Authorization สามารถทำได้โดยใช้ Passport.js

Table of contents:

ทำไมต้อง NestJS และ GraphQL?

ในช่วงไม่กี่ปีที่ผ่านมา ความต้องการระบบ API ที่มีประสิทธิภาพสูงและยืดหยุ่นได้ดีได้เพิ่มขึ้นอย่างมาก ในบทความนี้ เราจะมาเจาะลึกวิธีการ **สร้าง RESTful API ด้วย NestJS และ GraphQL สำหรับนักพัฒนาชาวไทย** ซึ่งเป็นแนวทางที่ได้รับความนิยมในการพัฒนา backend ที่ทันสมัยและตอบโจทย์ความต้องการทางธุรกิจได้อย่างมีประสิทธิภาพ

NestJS คือ framework ที่สร้างขึ้นบน TypeScript ซึ่งได้รับแรงบันดาลใจจาก Angular, React และ Vue ทำให้การพัฒนา backend เป็นระเบียบและง่ายต่อการดูแลรักษา ในขณะที่ GraphQL เป็น query language ที่ช่วยให้ client สามารถระบุข้อมูลที่ต้องการได้อย่างแม่นยำ ทำให้ API มีประสิทธิภาพมากยิ่งขึ้น

สำหรับนักพัฒนาชาวไทยที่กำลังมองหาวิธีการพัฒนา API ที่ทันสมัยและมีประสิทธิภาพ บทความนี้จะเป็นแนวทางที่ครอบคลุมตั้งแต่พื้นฐานไปจนถึงการนำไปใช้งานจริง

ก่อนที่เราจะลงลึกในรายละเอียดของการสร้าง API ด้วย NestJS และ GraphQL เรามาดูกันก่อนว่าทำไมสองเทคโนโลยีนี้ถึงได้รับความนิยมและเป็นที่ต้องการในวงการพัฒนา software

* **NestJS:** * **TypeScript:** NestJS ใช้ TypeScript ซึ่งเป็น superset ของ JavaScript ทำให้ code มีความน่าเชื่อถือและง่ายต่อการ debug มากยิ่งขึ้น นอกจากนี้ TypeScript ยังช่วยในการทำ code completion และ refactoring ซึ่งช่วยเพิ่ม productivity ให้กับนักพัฒนา * **โครงสร้างที่เป็นระเบียบ:** NestJS มีโครงสร้างที่เป็นระเบียบ (modular architecture) ทำให้ code สามารถนำกลับมาใช้ใหม่ได้ง่ายและง่ายต่อการบำรุงรักษา นอกจากนี้ NestJS ยังมี dependency injection ซึ่งช่วยลดความซับซ้อนของ code และทำให้ code สามารถทดสอบได้ง่ายยิ่งขึ้น * **รองรับหลากหลาย database:** NestJS รองรับการใช้งานร่วมกับ database ที่หลากหลาย เช่น PostgreSQL, MySQL, MongoDB และอื่นๆ ทำให้นักพัฒนาสามารถเลือกใช้ database ที่เหมาะสมกับความต้องการของโปรเจกต์ได้ * **รองรับ Real-time application:** NestJS รองรับการสร้าง Real-time application โดยใช้ WebSockets ทำให้สามารถสร้าง application ที่มีการสื่อสารแบบ real-time ได้อย่างง่ายดาย เช่น chat application หรือ online game* **GraphQL:** * **Query language:** GraphQL เป็น query language ที่ช่วยให้ client สามารถระบุข้อมูลที่ต้องการได้อย่างแม่นยำ ทำให้ API มีประสิทธิภาพมากยิ่งขึ้น * **ลด over-fetching และ under-fetching:** GraphQL ช่วยลดปัญหา over-fetching (การดึงข้อมูลที่ไม่จำเป็น) และ under-fetching (การดึงข้อมูลไม่ครบ) ทำให้ API มีประสิทธิภาพมากยิ่งขึ้น * **Strongly typed schema:** GraphQL มี strongly typed schema ซึ่งช่วยให้ client และ server สามารถตรวจสอบความถูกต้องของข้อมูลได้ ทำให้ API มีความน่าเชื่อถือมากยิ่งขึ้น * **Introspection:** GraphQL มี introspection ซึ่งช่วยให้ client สามารถสำรวจ schema ของ API ได้ ทำให้การพัฒนา client ง่ายยิ่งขึ้น

ขั้นตอนการสร้าง RESTful API ด้วย NestJS และ GraphQL

ต่อไปนี้เป็นขั้นตอนการสร้าง RESTful API ด้วย NestJS และ GraphQL อย่างละเอียด:

1. **ติดตั้ง NestJS CLI:** เริ่มต้นด้วยการติดตั้ง NestJS CLI (Command Line Interface) ซึ่งเป็นเครื่องมือที่ช่วยในการสร้างโปรเจกต์ NestJS ได้อย่างรวดเร็ว bash npm install -g @nestjs/cli 2. **สร้างโปรเจกต์ NestJS:** ใช้ NestJS CLI เพื่อสร้างโปรเจกต์ใหม่ bash nest new my-nest-graphql-api เลือก package manager ที่ต้องการ (เช่น npm หรือ yarn)3. **ติดตั้ง dependencies ที่จำเป็น:** ติดตั้ง dependencies ที่จำเป็นสำหรับ GraphQL และ NestJS bash npm install --save @nestjs/graphql @nestjs/apollo @apollo/server graphql หรือใช้ yarn: bash yarn add @nestjs/graphql @nestjs/apollo @apollo/server graphql 4. **สร้าง module สำหรับ GraphQL:** สร้าง module ใหม่สำหรับ GraphQL bash nest g module graphql 5. **สร้าง resolver:** สร้าง resolver สำหรับ GraphQL ซึ่งเป็นส่วนที่จัดการกับ query และ mutation bash nest g resolver products resolver จะเป็น class ที่มี method ที่จัดการกับ query และ mutation ต่างๆ

6. **สร้าง type definition (schema):** สร้าง type definition สำหรับ GraphQL ซึ่งเป็น schema ที่กำหนดโครงสร้างของข้อมูล สร้างไฟล์ `src/graphql/graphql.schema.ts` และกำหนด schema: typescript import { ObjectType, Field, Int } from '@nestjs/graphql'; @ObjectType() export class Product { @Field(() => Int) id: number; @Field() name: string; @Field(() => Int) price: number; } 7. **แก้ไข `app.module.ts`:** แก้ไข `app.module.ts` เพื่อ import `GraphQLModule` และ configure Apollo Server typescript import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { ProductsResolver } from './products/products.resolver'; @Module({ imports: [ GraphQLModule.forRoot({ driver: ApolloDriver, autoSchemaFile: 'schema.gql', // หรือ '/tmp/schema.gql' สำหรับ Linux }), ], providers: [ProductsResolver], }) export class AppModule {} 8. **แก้ไข `products.resolver.ts`:** แก้ไข `products.resolver.ts` เพื่อสร้าง query และ mutation typescript import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql'; import { Product } from '../graphql/graphql.schema'; @Resolver(() => Product) export class ProductsResolver { private products: Product[] = [ { id: 1, name: 'Product 1', price: 100 }, { id: 2, name: 'Product 2', price: 200 }, { id: 3, name: 'Product 3', price: 300 }, ]; @Query(() => [Product], { name: 'products' }) getProducts(): Product[] { return this.products; } @Query(() => Product, { name: 'product' }) getProduct(@Args('id', { type: () => Int }) id: number): Product { return this.products.find(product => product.id === id); } @Mutation(() => Product) createProduct( @Args('name') name: string, @Args('price', { type: () => Int }) price: number, ): Product { const newProduct: Product = { id: this.products.length + 1, name: name, price: price, }; this.products.push(newProduct); return newProduct; } } 9. **รันโปรเจกต์:** รันโปรเจกต์ NestJS bash npm run start:dev หรือใช้ yarn: bash yarn run start:dev เปิด browser ไปที่ `http://localhost:3000/graphql` เพื่อเข้าถึง GraphQL playground และทดสอบ API

การเชื่อมต่อกับ Database

ในการใช้งานจริง API ของคุณจะต้องเชื่อมต่อกับ database เพื่อดึงและบันทึกข้อมูล ใน NestJS สามารถทำได้โดยใช้ module ที่ชื่อว่า `@nestjs/typeorm` หรือ `@nestjs/mongoose` ขึ้นอยู่กับ database ที่คุณเลือกใช้

1. **ติดตั้ง TypeORM หรือ Mongoose:** * **TypeORM (สำหรับ relational database เช่น PostgreSQL, MySQL):** bash npm install --save @nestjs/typeorm typeorm mysql2 * **Mongoose (สำหรับ MongoDB):** bash npm install --save @nestjs/mongoose mongoose 2. **Configure TypeORM หรือ Mongoose:** * **TypeORM:** แก้ไข `app.module.ts` เพื่อ configure TypeORM typescript import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ProductsModule } from './products/products.module'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', // หรือ 'postgres' host: 'localhost', port: 3306, username: 'your_username', password: 'your_password', database: 'your_database', entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, // สำหรับ development เท่านั้น }), GraphQLModule.forRoot({ driver: ApolloDriver, autoSchemaFile: 'schema.gql', }), ProductsModule, ], }) export class AppModule {} * **Mongoose:** แก้ไข `app.module.ts` เพื่อ configure Mongoose typescript import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { MongooseModule } from '@nestjs/mongoose'; import { ProductsModule } from './products/products.module'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost/your_database'), GraphQLModule.forRoot({ driver: ApolloDriver, autoSchemaFile: 'schema.gql', }), ProductsModule, ], }) export class AppModule {} 3. **สร้าง entity (TypeORM) หรือ schema (Mongoose):** * **TypeORM:** สร้าง entity class ที่ define structure ของ table ใน database typescript // src/products/product.entity.ts import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity() export class Product { @PrimaryGeneratedColumn() id: number; @Column() name: string; @Column() price: number; } * **Mongoose:** สร้าง schema ที่ define structure ของ document ใน MongoDB typescript // src/products/product.schema.ts import * as mongoose from 'mongoose'; export const ProductSchema = new mongoose.Schema({ name: String, price: Number, }); export interface Product extends mongoose.Document { id: string; name: string; price: number; } 4. **แก้ไข resolver เพื่อใช้งาน database:** แก้ไข resolver เพื่อดึงและบันทึกข้อมูลจาก database * **TypeORM:** typescript import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql'; import { Product } from './product.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; @Resolver(() => Product) export class ProductsResolver { constructor( @InjectRepository(Product) private readonly productRepository: Repository, ) {} @Query(() => [Product], { name: 'products' }) async getProducts(): Promise { return this.productRepository.find(); } @Query(() => Product, { name: 'product' }) async getProduct(@Args('id', { type: () => Int }) id: number): Promise { return this.productRepository.findOne({ where: { id } }); } @Mutation(() => Product) async createProduct( @Args('name') name: string, @Args('price', { type: () => Int }) price: number, ): Promise { const product = this.productRepository.create({ name, price }); return this.productRepository.save(product); } } * **Mongoose:** typescript import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql'; import { Product } from './product.schema'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; @Resolver(() => Product) export class ProductsResolver { constructor( @InjectModel('Product') private readonly productModel: Model, ) {} @Query(() => [Product], { name: 'products' }) async getProducts(): Promise { return this.productModel.find().exec(); } @Query(() => Product, { name: 'product' }) async getProduct(@Args('id', { type: () => Int }) id: number): Promise { return this.productModel.findById(id).exec(); } @Mutation(() => Product) async createProduct( @Args('name') name: string, @Args('price', { type: () => Int }) price: number, ): Promise { const createdProduct = new this.productModel({ name, price }); return createdProduct.save(); } }

การจัดการ Authentication และ Authorization

Authentication และ Authorization เป็นส่วนสำคัญของ API ที่มีความปลอดภัย ใน NestJS สามารถทำได้โดยใช้ Passport.js ซึ่งเป็น library ที่ได้รับความนิยมในการจัดการ authentication

1. **ติดตั้ง Passport.js และ dependencies:** bash npm install --save @nestjs/passport passport passport-jwt jsonwebtoken 2. **สร้าง strategy:** สร้าง strategy สำหรับ authentication (เช่น JWT strategy) typescript // src/auth/jwt.strategy.ts import { ExtractJwt, Strategy } from 'passport-jwt'; import { PassportStrategy } from '@nestjs/passport'; import { Injectable } from '@nestjs/common'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, secretOrKey: 'your_secret_key', // ควรเก็บไว้ใน environment variable }); } async validate(payload: any) { return { userId: payload.sub, username: payload.username }; } } 3. **สร้าง guard:** สร้าง guard เพื่อป้องกัน endpoint ที่ต้องการ authentication typescript // src/auth/jwt-auth.guard.ts import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { canActivate(context: ExecutionContext) { return super.canActivate(context); } } 4. **ใช้ guard ใน controller:** ใช้ guard ใน controller เพื่อป้องกัน endpoint typescript import { Controller, Get, UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; @Controller('profile') export class ProfileController { @UseGuards(JwtAuthGuard) @Get() getProfile() { return { message: 'This is a protected route' }; } }

การทดสอบ API

การทดสอบ API เป็นส่วนสำคัญเพื่อให้แน่ใจว่า API ทำงานได้อย่างถูกต้อง สามารถใช้เครื่องมือต่างๆ เช่น Postman หรือ Insomnia ในการทดสอบ API

1. **ใช้ Postman หรือ Insomnia:** * สร้าง request ใหม่ใน Postman หรือ Insomnia * กำหนด method (GET, POST, PUT, DELETE) * กำหนด URL (เช่น `http://localhost:3000/graphql`) * กำหนด headers (เช่น `Content-Type: application/json`) * กำหนด body (สำหรับ POST, PUT) * ส่ง request และตรวจสอบ response

ข้อดีของการใช้ NestJS และ GraphQL สำหรับนักพัฒนาชาวไทย

* **ภาษาไทย:** NestJS และ GraphQL รองรับการใช้งานภาษาไทย ทำให้การพัฒนา application ที่รองรับภาษาไทยง่ายยิ่งขึ้น* **ชุมชน:** NestJS และ GraphQL มีชุมชนขนาดใหญ่และมีการสนับสนุนที่ดี ทำให้ง่ายต่อการค้นหาข้อมูลและแก้ไขปัญหา* **ความยืดหยุ่น:** NestJS และ GraphQL มีความยืดหยุ่นสูง สามารถปรับแต่งให้เข้ากับความต้องการของโปรเจกต์ได้* **ประสิทธิภาพ:** GraphQL ช่วยลดปัญหา over-fetching และ under-fetching ทำให้ API มีประสิทธิภาพมากยิ่งขึ้น

สรุป

การ **สร้าง RESTful API ด้วย NestJS และ GraphQL สำหรับนักพัฒนาชาวไทย** เป็นแนวทางที่น่าสนใจในการพัฒนา backend ที่ทันสมัยและมีประสิทธิภาพ NestJS ช่วยให้การพัฒนา backend เป็นระเบียบและง่ายต่อการดูแลรักษา ในขณะที่ GraphQL ช่วยให้ API มีประสิทธิภาพมากยิ่งขึ้น หวังว่าบทความนี้จะเป็นประโยชน์สำหรับนักพัฒนาชาวไทยที่กำลังมองหาวิธีการพัฒนา API ที่ทันสมัยและมีประสิทธิภาพ

**Actionable Advice:**

* **เริ่มต้นจากเล็กๆ:** เริ่มต้นด้วยการสร้าง API ง่ายๆ ก่อน แล้วค่อยๆ เพิ่ม features* **ศึกษา document:** อ่าน document ของ NestJS และ GraphQL อย่างละเอียด* **เข้าร่วมชุมชน:** เข้าร่วมชุมชนของ NestJS และ GraphQL เพื่อเรียนรู้จากนักพัฒนาคนอื่นๆ* **ทดสอบ code:** ทดสอบ code อย่างสม่ำเสมอเพื่อให้แน่ใจว่า code ทำงานได้อย่างถูกต้อง

**มีศิริ ดิจิทัล มีความเชี่ยวชาญในการพัฒนา software และ IT consulting ซึ่งรวมถึงการสร้าง RESTful API ด้วย NestJS และ GraphQL หากคุณกำลังมองหา partner ที่มีความเชี่ยวชาญในการพัฒนา software ติดต่อเราวันนี้เพื่อหารือเกี่ยวกับโปรเจกต์ของคุณ**

**Call to Action:**

* **Explore our services:** [Link to company services page]* **Contact us for more information:** ติดต่อเราวันนี้

FAQ

สร้างอีคอมเมิร์ซปลอดภัยด้วย Remix และ Supabase