Back to notes
mastery-backend-nestjs
Featured

NestJS Architecture Mastery: สร้างระบบระดับ Enterprise ให้แข็งแกร่ง

เจาะลึกโครงสร้าง NestJS ตั้งแต่ปัญหาการจัดการโค้ด ไปจนถึง Dependency Injection และตารางเปรียบเทียบความแตกต่างกับ Express

January 30, 20262 min read readNNexis by Seereen

🛑 1. The Problem First: "Dependency Hell" ใน Express

ลองดูเวลาเราเขียน Express แบบไม่มีโครงสร้าง:

HLJS JAVASCRIPT
// ❌ Naive Approach: ทุกอย่างวางรวมกันมั่วซั่ว
const userService = new UserService(new DatabaseRepo(new PostgresDriver()));
app.post("/users", (req, res) => {
  // Logic คัดกรองข้อมูล, เช็ค Auth, คุยกับ DB อยู่ในนี้หมดเลย!
});

ปัญหา: เมื่อโปรเจกต์ใหญ่ขึ้น ไฟล์จะยาวเป็นพันบรรทัด การจะแก้ไขอะไรสักอย่าง (เช่น เปลี่ยน DB) คุณต้องไล่แก้ทั้งโปรเจกต์ และการสร้าง new Service() ซ้อนกะนหลายชั้นแบบนี้จะทำให้การทำ Unit Test กลายเป็นนรก!


💡 2. Real-Life Analogy: เลโก้ชุดสำเร็จรูป vs กล่องสุ่ม

ลองนึกภาพว่าคุณกำลัง "สร้างเมือง".

  • Express: เหมือนคุณมีกล่องสุ่มที่มีตัวเลโก้ทุกแบบปนกันมั่วไปหมด (Schema-less) คุณอยากต่ออะไรก็ได้ แต่พอจะหาชิ้นส่วนที่ต้องการดันหาไม่เจอ
  • NestJS: เหมือนคุณซื้อ "เลโก้ชุดสถานีตำรวจ" หรือ "ชุดโรงพยาบาล".
    • แต่ละชุดมี Module (ป้ายกำกับชัดเจน)
    • มี Controller (เคาน์เตอร์ประชาสัมพันธ์)
    • และมี Service (พนักงานข้างหลัง)
    • ทุกชิ้นส่วนถูกออกแบบมาให้ "เสียบ" เข้าหากันได้พอดี (Dependency Injection)

🚀 3. Execution Journey: มหากาพย์การ Request

เมื่อลูกค้าส่งคำสั่ง POST /users นี่คือเส้นทางของข้อมูล:

🛠 Step-by-step:

  1. Middleware/Guard: ข้อมูลมาถึงหน้าประตู (Check Auth)
  2. Controller: เคาน์เตอร์รับออเดอร์ ข้อมูลถูกตรวจสอบหน้าตา (DTO Validation) แล้วส่งต่อให้คนข้างใน
  3. Service: พนักงานหลังบ้านทำหน้าที่คำนวณเงิน บันทึกลงสมุด (Business Logic & Database)
  4. Module: ผู้จัดการเป็นคนรวบรวมพนักงานทุกคนและเคาน์เตอร์ทั้งหมดมาเข้าหมวดหมู่เดียวกัน
HLJS TYPESCRIPT
// ✅ Best Practice: แยก Logic ออกจาก Controller เสมอ
@Controller("users")
export class UsersController {
  constructor(private readonly usersService: UsersService) {} // 🛠 ฉีด Service เข้ามาใช้ (DI)

  @Post()
  create(@Body() dto: CreateUserDto) {
    return this.usersService.create(dto); // 👈 Controller แค่สั่งงาน ไม่ลงมือทำเอง
  }
}

🪤 4. The Junior Trap: โรค "Controller บวม"

จูเนียร์ส่วนใหญ่มักจะขี้เกียจสร้างไฟล์ Service:

HLJS TYPESCRIPT
// ❌ Junior Trap: เขียน Logic ยาวเหยียดใน Controller
@Post()
create(@Body() dto: CreateUserDto) {
    if (dto.name === 'admin') throw new Error('Bad name');
    const user = await db.save(dto);
    return user;
}

ระวัง: ถ้าวันหนึ่งคุณอยากสร้าง User ผ่านทางอื่น (เช่น Cron Job หรือ Command Line) คุณจะใช้ Logic นี้ไม่ได้เลย เพราะมันติดอยู่กับ HTTP Controller เท่านั้น! ✅ การแก้ไข: ย้ายทุกลอจิกการเช็คและบันทึกไปไว้ใน Service เพื่อให้ส่วนอื่นเรียกใช้ได้เสมอ


⚖️ 5. The Why Matrix: Express vs NestJS

หัวข้อExpress (Minimal)NestJS (Opinonated)
ความเร็วในการเริ่มเร็วมาก เขียน 10 บรรทัดรันได้ช้ากว่า ต้องสร้างโครงสร้าง
การทำงานเป็นทีมต่างคนต่างเขียน ระบบมั่วได้ง่ายทุกคนเขียนเหมือนกัน เข้าใจกันง่าย
Dependency Injectionต้องทำเอง (Manual)มีระบบอัตโนมัติ (Built-in)

🎓 6. Senior Mindset Summary

การเป็น Senior คือการเลิกถามว่า "จะเขียนยังไงให้รันออก" แต่เริ่มถามว่า "จะวางโครงสร้างยังไงให้ทีมงาน 10 คน ทำงานพร้อมกันได้โดยไม่เดินทับรอยกัน" และ NestJS คือคำตอบหนึ่งในนั้นครับ!

Share this note

Mission Accomplished

You've reached the end of this module. Time to apply these senior mindsets to your real-world projects!

Explore more topics

© 2026 My Notes by Seereen