Home > Blog > tech

NestJS คืออะไร? Enterprise-grade Node.js Framework สำหรับ Backend ขนาดใหญ่ 2026

nestjs enterprise nodejs framework guide
NestJS Enterprise Node.js Framework Guide 2026
2026-04-11 | tech | 3500 words

ในโลกของ Backend Development ด้วย Node.js เรามี Framework มากมายให้เลือกใช้ ตั้งแต่ Express ที่เรียบง่ายไปจนถึง Fastify ที่เน้นประสิทธิภาพ แต่เมื่อโปรเจกต์เติบโตขึ้นจนกลายเป็นระบบขนาดใหญ่ที่มีทีมพัฒนาหลายสิบคน ปัญหาเรื่องโครงสร้าง Code ที่ไม่เป็นระเบียบ การจัดการ Dependency ที่ซับซ้อน และการบำรุงรักษาที่ยากลำบากก็ตามมา NestJS คือ Framework ที่ถูกสร้างมาเพื่อแก้ปัญหาเหล่านี้โดยเฉพาะ

บทความนี้จะพาคุณเจาะลึกทุกแง่มุมของ NestJS ตั้งแต่แนวคิดพื้นฐาน โครงสร้างโปรเจกต์ ไปจนถึงการสร้าง Microservices และ GraphQL API พร้อมตัวอย่าง Code ที่ใช้ได้จริงในปี 2026

NestJS คืออะไร?

NestJS คือ Progressive Node.js Framework สำหรับสร้าง Server-side Application ที่มีประสิทธิภาพสูง ปรับขยายได้ง่าย และบำรุงรักษาได้ยาวนาน สร้างขึ้นโดย Kamil Mysliwiec และได้รับแรงบันดาลใจจาก Angular ทำให้มีโครงสร้างที่ชัดเจนและเป็นระบบ

คุณสมบัติเด่นของ NestJS ได้แก่:

NestJS vs Express vs Fastify vs Hono — เปรียบเทียบ Framework

คุณสมบัติNestJSExpressFastifyHono
TypeScript SupportBuilt-in (first-class)ต้องตั้งค่าเองมี PluginBuilt-in
Architecture PatternOpinionated (MVC+DI)UnopinionatedPlugin-basedMinimal
Learning Curveสูง (แต่คุ้มค่า)ต่ำมากปานกลางต่ำ
Performance (req/s)ดี (ใช้ Fastify ได้)ปานกลางสูงมากสูงมาก
ScalabilityEnterprise-gradeต้องจัดการเองดีดี
MicroservicesBuilt-in supportไม่มีไม่มีไม่มี
GraphQLModule สำเร็จรูปต้องติดตั้งเองต้องติดตั้งเองต้องติดตั้งเอง
TestingBuilt-in test utilitiesต้องจัดการเองมี Pluginต้องจัดการเอง
เหมาะกับEnterprise/ระบบใหญ่ระบบเล็ก/เรียนรู้API ประสิทธิภาพสูงEdge/Serverless
เลือก Framework ไหนดี? ถ้าโปรเจกต์เล็ก ทีม 1-3 คน ใช้ Express หรือ Hono ก็พอ แต่ถ้าโปรเจกต์ใหญ่ ทีมหลายคน ต้องการโครงสร้างที่ชัดเจนและ Maintainable ในระยะยาว NestJS คือตัวเลือกที่ดีที่สุด

การติดตั้งและเริ่มต้นโปรเจกต์ NestJS

ติดตั้ง NestJS CLI

# ติดตั้ง NestJS CLI แบบ Global
npm install -g @nestjs/cli

# สร้างโปรเจกต์ใหม่
nest new my-enterprise-api

# เลือก Package Manager (npm, yarn, pnpm)
# CLI จะสร้างโครงสร้างโปรเจกต์ให้อัตโนมัติ

# รันโปรเจกต์
cd my-enterprise-api
npm run start:dev    # Development mode (hot-reload)
npm run start:prod   # Production mode

NestJS CLI Commands ที่ใช้บ่อย

# สร้าง Module
nest generate module users
nest g mo users          # ย่อ

# สร้าง Controller
nest generate controller users
nest g co users

# สร้าง Service
nest generate service users
nest g s users

# สร้าง Resource (Module + Controller + Service + DTO + Entity)
nest g resource products

# สร้าง Guard, Pipe, Interceptor, Filter
nest g guard auth
nest g pipe validation
nest g interceptor logging
nest g filter http-exception

โครงสร้างโปรเจกต์ NestJS

NestJS ใช้โครงสร้างแบบ Modular Architecture ที่แบ่ง Code เป็นส่วนๆ ชัดเจน แต่ละส่วนมีหน้าที่เฉพาะ ทำให้ทีมขนาดใหญ่ทำงานร่วมกันได้โดยไม่ชนกัน

src/
├── app.module.ts          # Root Module — รวมทุก Module เข้าด้วยกัน
├── app.controller.ts      # Root Controller
├── app.service.ts         # Root Service
├── main.ts                # Entry point — Bootstrap แอป
│
├── users/                 # Feature Module
│   ├── users.module.ts    # Module definition
│   ├── users.controller.ts # HTTP routes
│   ├── users.service.ts   # Business logic
│   ├── dto/               # Data Transfer Objects
│   │   ├── create-user.dto.ts
│   │   └── update-user.dto.ts
│   ├── entities/          # Database entities
│   │   └── user.entity.ts
│   └── users.controller.spec.ts  # Unit tests
│
├── auth/                  # Auth Module
│   ├── auth.module.ts
│   ├── auth.controller.ts
│   ├── auth.service.ts
│   ├── guards/
│   │   └── jwt-auth.guard.ts
│   └── strategies/
│       └── jwt.strategy.ts
│
├── common/                # Shared utilities
│   ├── filters/
│   ├── interceptors/
│   ├── pipes/
│   └── decorators/
│
└── config/                # Configuration
    └── database.config.ts

Modules — หัวใจของ NestJS

Module คือหน่วยพื้นฐานที่ใช้จัดกลุ่ม Code ที่เกี่ยวข้องกันเข้าด้วยกัน ทุก NestJS Application ต้องมีอย่างน้อยหนึ่ง Module คือ Root Module (AppModule)

// users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';

@Module({
  imports: [TypeOrmModule.forFeature([User])],  // นำเข้า Module อื่น
  controllers: [UsersController],                // Controller ของ Module นี้
  providers: [UsersService],                     // Service / Provider
  exports: [UsersService],                       // ส่งออกให้ Module อื่นใช้
})
export class UsersModule {}

Controllers — รับ HTTP Request

Controller ทำหน้าที่รับ HTTP Request จาก Client และส่งต่อให้ Service ประมวลผล โดยใช้ Decorators กำหนด Route, Method และ Parameters

// users.controller.ts
import { Controller, Get, Post, Put, Delete, Param, Body, Query, HttpCode, HttpStatus } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Controller('users')  // prefix: /users
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  @HttpCode(HttpStatus.CREATED)
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll(@Query('page') page: number = 1, @Query('limit') limit: number = 10) {
    return this.usersService.findAll(page, limit);
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(id);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(id, updateUserDto);
  }

  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  remove(@Param('id') id: string) {
    return this.usersService.remove(id);
  }
}

Services — Business Logic

Service เป็นที่รวม Business Logic ทั้งหมด แยกออกจาก Controller เพื่อให้สามารถ Reuse และทดสอบได้ง่าย

// users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  async create(createUserDto: CreateUserDto): Promise<User> {
    const user = this.usersRepository.create(createUserDto);
    return this.usersRepository.save(user);
  }

  async findAll(page: number, limit: number) {
    const [items, total] = await this.usersRepository.findAndCount({
      skip: (page - 1) * limit,
      take: limit,
      order: { createdAt: 'DESC' },
    });
    return { items, total, page, lastPage: Math.ceil(total / limit) };
  }

  async findOne(id: string): Promise<User> {
    const user = await this.usersRepository.findOne({ where: { id } });
    if (!user) throw new NotFoundException(`User #${id} not found`);
    return user;
  }

  async update(id: string, updateUserDto: any): Promise<User> {
    await this.usersRepository.update(id, updateUserDto);
    return this.findOne(id);
  }

  async remove(id: string): Promise<void> {
    const result = await this.usersRepository.delete(id);
    if (result.affected === 0) throw new NotFoundException(`User #${id} not found`);
  }
}

Dependency Injection (DI) — ระบบหัวใจของ NestJS

Dependency Injection คือ Design Pattern ที่ NestJS ใช้เป็นแกนหลัก แทนที่จะสร้าง Instance ของ Class ด้วยตัวเอง (new MyService()) เราให้ NestJS Container จัดการสร้างและส่ง Dependencies ให้อัตโนมัติ ข้อดีคือ Code เป็น Loosely Coupled ทดสอบง่าย เปลี่ยน Implementation ได้โดยไม่แก้ Code ที่ใช้งาน

// Custom Provider — ใช้เปลี่ยน Implementation ได้
@Module({
  providers: [
    {
      provide: 'PAYMENT_SERVICE',
      useClass: process.env.NODE_ENV === 'production'
        ? StripePaymentService
        : MockPaymentService,
    },
    {
      provide: 'CONFIG',
      useValue: { apiKey: process.env.API_KEY, timeout: 5000 },
    },
    {
      provide: 'ASYNC_CONNECTION',
      useFactory: async (configService: ConfigService) => {
        const dbConfig = configService.get('database');
        return createConnection(dbConfig);
      },
      inject: [ConfigService],
    },
  ],
})
export class PaymentModule {}

Decorators — ฟีเจอร์ที่ทำให้ NestJS สวยงาม

NestJS ใช้ Decorators อย่างหนักเพื่อกำหนดพฤติกรรมของ Class, Method และ Parameter โดยไม่ต้องเขียน Boilerplate Code มากมาย Decorator ที่สำคัญมีหลายกลุ่ม เช่น @Controller, @Get, @Post สำหรับ Routing และ @Injectable สำหรับ DI

// Custom Decorator — สร้าง Decorator เอง
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const CurrentUser = createParamDecorator(
  (data: string, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    const user = request.user;
    return data ? user?.[data] : user;
  },
);

// ใช้งาน
@Get('profile')
getProfile(@CurrentUser() user: User) {
  return user;
}

@Get('email')
getEmail(@CurrentUser('email') email: string) {
  return { email };
}

Pipes — Validation และ Transformation

Pipes ใน NestJS ทำหน้าที่สองอย่าง: Validation (ตรวจสอบข้อมูล) และ Transformation (แปลงข้อมูล) ทำงานก่อนที่ข้อมูลจะถึง Controller Method ทำให้มั่นใจได้ว่าข้อมูลที่เข้ามาถูกต้องเสมอ

// DTO พร้อม Validation ด้วย class-validator
import { IsEmail, IsString, MinLength, IsOptional, IsEnum } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;

  @IsEmail()
  email: string;

  @IsString()
  @MinLength(8)
  password: string;

  @IsOptional()
  @IsEnum(['admin', 'user', 'moderator'])
  role?: string;
}

// เปิดใช้ Global Validation Pipe ใน main.ts
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe({
    whitelist: true,          // ตัด Property ที่ไม่ได้กำหนดใน DTO ออก
    forbidNonWhitelisted: true, // ถ้ามี Property แปลกๆ ให้ Error
    transform: true,          // แปลง Type อัตโนมัติ
  }));
  await app.listen(3000);
}

Guards — Authentication และ Authorization

Guards เป็นกลไกสำหรับควบคุมการเข้าถึง Route โดยตรวจสอบว่า Request มีสิทธิ์เข้าถึงหรือไม่ ใช้สำหรับ Authentication (ตรวจว่า Login หรือยัง) และ Authorization (ตรวจว่ามีสิทธิ์หรือไม่)

// JWT Auth Guard
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const token = request.headers.authorization?.split(' ')[1];
    if (!token) return false;
    try {
      const payload = await this.jwtService.verifyAsync(token);
      request.user = payload;
      return true;
    } catch {
      return false;
    }
  }
}

// Roles Guard
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!requiredRoles) return true;
    const { user } = context.switchToHttp().getRequest();
    return requiredRoles.some(role => user.roles?.includes(role));
  }
}

// ใช้งาน
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Delete(':id')
removeUser(@Param('id') id: string) {
  return this.usersService.remove(id);
}

Interceptors — จัดการ Request/Response

Interceptors สามารถแทรกตัวเข้าไปก่อนและหลังการทำงานของ Controller Method ใช้สำหรับ Logging, Caching, Response Transformation หรือ Error Handling

// Logging Interceptor — จับเวลาทุก Request
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const method = request.method;
    const url = request.url;
    const now = Date.now();

    return next.handle().pipe(
      tap(() => console.log(`${method} ${url} - ${Date.now() - now}ms`)),
    );
  }
}

// Transform Interceptor — ห่อ Response ในรูปแบบมาตรฐาน
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map(data => ({ success: true, data, timestamp: new Date().toISOString() })),
    );
  }
}

Exception Filters — จัดการ Error อย่างเป็นระบบ

Exception Filters จับ Error ที่เกิดขึ้นในแอป และแปลงเป็น HTTP Response ที่เหมาะสม ทำให้ Client ได้รับ Error Message ที่สม่ำเสมอ

// Custom Exception Filter
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();

    const status = exception instanceof HttpException
      ? exception.getStatus()
      : HttpStatus.INTERNAL_SERVER_ERROR;

    const message = exception instanceof HttpException
      ? exception.getResponse()
      : 'Internal server error';

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message,
    });
  }
}

Middleware — จัดการ Request ก่อนถึง Route

Middleware ใน NestJS ทำงานเหมือน Express Middleware ทำงานก่อนที่ Request จะถึง Guard, Interceptor หรือ Controller เหมาะสำหรับ CORS, Logging, Rate Limiting หรือ Request Parsing

// Custom Middleware
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl}`);
    next();
  }
}

// ลงทะเบียนใน Module
@Module({ /* ... */ })
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*');  // ใช้กับทุก Route
  }
}

Database Integration — TypeORM, Prisma, Sequelize

NestJS รองรับ ORM หลายตัว โดยมี Official Module สำเร็จรูปให้ใช้ สามารถเลือกใช้ได้ตามความถนัดและความต้องการของโปรเจกต์

TypeORM (แนะนำสำหรับ NestJS)

// Entity
@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @CreateDateColumn()
  createdAt: Date;

  @OneToMany(() => Post, post => post.author)
  posts: Post[];
}

// app.module.ts
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'admin',
      password: 'secret',
      database: 'myapp',
      entities: [User, Post],
      synchronize: false, // อย่าใช้ true ใน Production
    }),
  ],
})

Prisma Integration

// prisma.service.ts
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}

// ใช้งานใน Service
@Injectable()
export class UsersService {
  constructor(private prisma: PrismaService) {}

  async findAll() {
    return this.prisma.user.findMany({
      include: { posts: true },
    });
  }
}

Swagger/OpenAPI — Auto-generate API Documentation

NestJS มี Module สำหรับสร้างเอกสาร API อัตโนมัติด้วย Swagger/OpenAPI ช่วยให้ทีม Frontend และทีมอื่นเข้าใจ API ได้ง่ายโดยไม่ต้องเขียนเอกสารแยก

// main.ts — ตั้งค่า Swagger
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

const config = new DocumentBuilder()
  .setTitle('My Enterprise API')
  .setDescription('API Documentation')
  .setVersion('1.0')
  .addBearerAuth()
  .addTag('users')
  .addTag('products')
  .build();

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api/docs', app, document);
// เข้าถึงได้ที่ http://localhost:3000/api/docs

// ใส่ Decorator ใน DTO เพื่อสร้างเอกสาร
import { ApiProperty } from '@nestjs/swagger';

export class CreateUserDto {
  @ApiProperty({ example: 'John Doe', description: 'ชื่อผู้ใช้' })
  name: string;

  @ApiProperty({ example: 'john@example.com' })
  email: string;
}

GraphQL กับ NestJS

NestJS รองรับ GraphQL แบบ First-class ทั้ง Code-first และ Schema-first approach สามารถสร้าง GraphQL API ที่มีโครงสร้างชัดเจนและทรงพลังได้อย่างง่ายดาย

// Code-first approach
// users.resolver.ts
@Resolver(() => User)
export class UsersResolver {
  constructor(private usersService: UsersService) {}

  @Query(() => [User])
  async users() {
    return this.usersService.findAll();
  }

  @Query(() => User)
  async user(@Args('id') id: string) {
    return this.usersService.findOne(id);
  }

  @Mutation(() => User)
  async createUser(@Args('input') input: CreateUserInput) {
    return this.usersService.create(input);
  }

  @ResolveField(() => [Post])
  async posts(@Parent() user: User) {
    return this.postsService.findByUserId(user.id);
  }
}

WebSocket กับ NestJS

NestJS มี Module สำหรับ WebSocket ที่ทำงานร่วมกับ Socket.IO หรือ WS ได้ ใช้สำหรับ Real-time Communication เช่น Chat, Notifications, Live Dashboard

// chat.gateway.ts
@WebSocketGateway({ cors: true })
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  handleConnection(client: Socket) {
    console.log(`Client connected: ${client.id}`);
  }

  handleDisconnect(client: Socket) {
    console.log(`Client disconnected: ${client.id}`);
  }

  @SubscribeMessage('sendMessage')
  handleMessage(client: Socket, payload: { room: string; message: string }) {
    this.server.to(payload.room).emit('newMessage', {
      sender: client.id,
      message: payload.message,
      timestamp: new Date(),
    });
  }

  @SubscribeMessage('joinRoom')
  handleJoinRoom(client: Socket, room: string) {
    client.join(room);
    client.emit('joinedRoom', room);
  }
}

Microservices กับ NestJS

หนึ่งในจุดเด่นของ NestJS คือ Built-in Microservices Support รองรับ Transport Layer หลายแบบ ทำให้สร้างระบบ Microservices ได้ง่ายโดยไม่ต้องพึ่ง Library ภายนอก

TransportUse Caseข้อดี
TCPService-to-service ภายในง่าย ไม่ต้องพึ่ง Broker
RedisPub/Sub, Event-drivenเร็ว ใช้ Redis เป็น Broker
NATSCloud-native messagingเบา ประสิทธิภาพสูง
KafkaEvent streaming ขนาดใหญ่ทนทาน ไม่ตกหล่น
gRPCHigh-performance RPCBinary protocol เร็วมาก
RabbitMQMessage queue ทั่วไปReliable, flexible routing
// Microservice Server (TCP)
// main.ts
const app = await NestFactory.createMicroservice(AppModule, {
  transport: Transport.TCP,
  options: { host: '0.0.0.0', port: 3001 },
});
await app.listen();

// Message Pattern
@Controller()
export class OrdersController {
  @MessagePattern('get_order')
  getOrder(data: { id: string }) {
    return this.ordersService.findOne(data.id);
  }

  @EventPattern('order_created')
  handleOrderCreated(data: any) {
    // Fire-and-forget event
    this.notificationService.notify(data);
  }
}

// Client — เรียกใช้ Microservice อื่น
@Injectable()
export class ApiGatewayService {
  constructor(@Inject('ORDERS_SERVICE') private ordersClient: ClientProxy) {}

  async getOrder(id: string) {
    return this.ordersClient.send('get_order', { id }).toPromise();
  }
}

CQRS Module — Command Query Responsibility Segregation

NestJS มี CQRS Module ให้ใช้สำหรับแอปที่ซับซ้อน โดยแยก Command (เปลี่ยนแปลงข้อมูล) ออกจาก Query (อ่านข้อมูล) ทำให้ระบบ Scale ได้ดีขึ้น แต่ละส่วนปรับแต่งได้อิสระ เหมาะกับระบบที่มี Read/Write ratio ต่างกันมาก เช่น ระบบ E-commerce ที่อ่านสินค้าเยอะแต่สั่งซื้อน้อยกว่า

// Command
export class CreateOrderCommand {
  constructor(
    public readonly userId: string,
    public readonly items: OrderItem[],
  ) {}
}

// Command Handler
@CommandHandler(CreateOrderCommand)
export class CreateOrderHandler implements ICommandHandler<CreateOrderCommand> {
  async execute(command: CreateOrderCommand) {
    // Create order logic
    // Publish event
    this.eventBus.publish(new OrderCreatedEvent(order.id));
  }
}

Testing ใน NestJS

NestJS มี Testing Utilities ที่ทรงพลังสำหรับทั้ง Unit Test และ E2E Test ใช้ Jest เป็น Test Runner หลัก พร้อมเครื่องมือสำหรับ Mock Dependencies อย่างง่ายดาย

Unit Test

// users.service.spec.ts
describe('UsersService', () => {
  let service: UsersService;
  let repository: Repository<User>;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [
        UsersService,
        {
          provide: getRepositoryToken(User),
          useValue: {
            find: jest.fn(),
            findOne: jest.fn(),
            create: jest.fn(),
            save: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get(UsersService);
    repository = module.get(getRepositoryToken(User));
  });

  it('should find a user by id', async () => {
    const mockUser = { id: '1', name: 'Test', email: 'test@test.com' };
    jest.spyOn(repository, 'findOne').mockResolvedValue(mockUser as User);
    const result = await service.findOne('1');
    expect(result).toEqual(mockUser);
  });
});

E2E Test

// test/users.e2e-spec.ts
describe('Users (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();
    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/users (POST)', () => {
    return request(app.getHttpServer())
      .post('/users')
      .send({ name: 'Test', email: 'test@test.com', password: '12345678' })
      .expect(201)
      .expect(res => {
        expect(res.body.name).toBe('Test');
      });
  });

  afterAll(async () => {
    await app.close();
  });
});

Deployment — Docker และ Kubernetes

# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/main.js"]
# docker-compose.yml
version: '3.8'
services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://admin:secret@db:5432/myapp
      - JWT_SECRET=your-secret-key
    depends_on:
      - db
      - redis
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data
  redis:
    image: redis:7-alpine
volumes:
  pgdata:

Monorepo Support

NestJS CLI รองรับ Monorepo Mode ให้จัดการหลาย Application และ Library ในโปรเจกต์เดียว เหมาะกับ Microservices Architecture ที่ต้องการแชร์ Code ระหว่าง Service

# สร้าง Monorepo
nest new my-workspace --monorepo

# เพิ่ม Application
nest generate app orders-service
nest generate app notifications-service

# เพิ่ม Library (shared code)
nest generate library common
nest generate library database

# Build แต่ละ App
nest build orders-service
nest build notifications-service

เมื่อไหร่ควรเลือก NestJS?

NestJS ไม่ใช่ Framework สำหรับทุกโปรเจกต์ การเลือกใช้ควรพิจารณาจากขนาดและความซับซ้อนของระบบ จำนวนคนในทีม และแผนระยะยาวของโปรเจกต์ ถ้าโปรเจกต์เป็น Prototype หรือ MVP ขนาดเล็ก Express หรือ Hono อาจเหมาะกว่าเพราะเริ่มต้นเร็ว แต่ถ้าเป็นระบบที่ต้องบำรุงรักษาหลายปี มีทีมหลายคน ต้องการโครงสร้างที่ชัดเจน NestJS คือคำตอบ

สรุป

NestJS เป็น Framework ที่ทรงพลังสำหรับ Enterprise Backend Development บน Node.js ด้วยโครงสร้างที่ได้รับแรงบันดาลใจจาก Angular ระบบ Dependency Injection ที่แข็งแกร่ง และ Ecosystem ที่ครอบคลุมทั้ง REST API, GraphQL, WebSocket, Microservices และ CQRS ทำให้เป็น Framework ที่เหมาะสมที่สุดสำหรับระบบ Backend ขนาดใหญ่ที่ต้องการความเป็นระเบียบ Scalable และ Maintainable ในระยะยาว

ในปี 2026 NestJS ยังคงเป็นตัวเลือกอันดับหนึ่งสำหรับองค์กรที่ต้องการสร้าง Backend ด้วย Node.js อย่างมืออาชีพ เริ่มต้นด้วย CLI สร้างโปรเจกต์แรก ลองสร้าง CRUD API ด้วย Module Controller Service แล้วคุณจะเข้าใจว่าทำไม NestJS ถึงได้รับความนิยมมากขนาดนี้


Back to Blog | iCafe Forex | SiamLanCard | Siam2R