บทที่ 6 Back-end Development

สไลด์บทเรียน

วัตถุประสงค์

  1. อธิบายบทบาทของ Back-end Development ในระบบ web application ได้
  2. สร้าง REST API ฝั่ง server ด้วย Node.js/Express หรือ Node-RED ได้
  3. เข้าใจการทำงานของ Routing, Middleware, Controller และ Service Layer ได้
  4. จัดการ Error Handling และ HTTP Response ได้เหมาะสม
  5. ใช้ Environment Variables เพื่อแยกค่าตั้งค่าระหว่าง development และ production ได้

ภาพรวมบทเรียน

บทที่ 5 เน้นการออกแบบ REST API ส่วนบทนี้จะลงมือมองฝั่ง server ว่า API ทำงานอย่างไรตั้งแต่รับ request ตรวจสอบข้อมูล ประมวลผล business logic ติดต่อแหล่งข้อมูล และส่ง response กลับไปยัง client เช่น Angular app หรือ Postman

คำสำคัญของบทเรียน


1. บทบาทของ Back-end ใน Web Application

Back-end ทำหน้าที่รับ request จาก client แล้วประมวลผลตามกฎของระบบ เช่น ตรวจสอบข้อมูลสินค้า ตรวจสิทธิ์ผู้ใช้ คำนวณยอดรวม ติดต่อฐานข้อมูล และส่ง response กลับไปในรูปแบบ JSON

%%{init: {'theme': 'base', 'themeVariables': {
  'background': '#282828',
  'primaryColor': '#3c3836',
  'primaryTextColor': '#fbf1c7',
  'primaryBorderColor': '#fabd2f',
  'lineColor': '#83a598',
  'secondaryColor': '#504945',
  'tertiaryColor': '#665c54',
  'fontFamily': 'Arial'
}}}%%
flowchart LR
  A[Client
Angular/Postman] --> B[HTTP Request
คำขอ] B --> C[Route
เลือก endpoint] C --> D[Middleware
ตรวจและเตรียมข้อมูล] D --> E[Controller
จัดการคำสั่ง] E --> F[Service
Business Logic] F --> G[Data Source
Database/API/File] G --> F F --> H[HTTP Response
JSON/Status Code] H --> A
ส่วน หน้าที่
Route รับ URL และ HTTP method
Middleware ทำงานก่อนถึง controller เช่น logging หรือ validation
Controller รับ request และกำหนด response
Service เก็บ business logic
Data Access ติดต่อ database หรือแหล่งข้อมูล
Error Handler จัดรูปแบบ error response

2. Node.js และ Express

Node.js ทำให้ JavaScript ทำงานฝั่ง server ได้ ส่วน Express ช่วยสร้าง web server และ REST API ได้ง่ายขึ้น โดยมีโครงสร้างหลักคือ app, route, middleware และ handler function

# สร้างโปรเจกต์ backend
mkdir product-api
cd product-api
npm init -y

# ติดตั้ง Express
npm install express

# เปิด server
node server.js
// server.js
const express = require('express');

const app = express();
const port = 3000;

// middleware สำหรับอ่าน JSON request body
app.use(express.json());

app.get('/api/health', (req, res) => {
  res.json({ status: 'ok' });
});

app.listen(port, () => {
  console.log(`API server running on port ${port}`);
});

3. Routing: จับคู่ Endpoint กับการทำงาน

Routing คือการกำหนดว่าเมื่อ client เรียก URL และ HTTP method ใด server ต้องเรียก function ใดเพื่อประมวลผล เช่น GET /api/products ใช้อ่านรายการสินค้า และ POST /api/products ใช้สร้างสินค้าใหม่

const products = [
  { id: 1, name: 'Keyboard', price: 850 },
  { id: 2, name: 'Mouse', price: 420 }
];

app.get('/api/products', (req, res) => {
  res.json(products);
});

app.get('/api/products/:id', (req, res) => {
  const id = Number(req.params.id);
  const product = products.find((item) => item.id === id);

  if (!product) {
    return res.status(404).json({
      error: { code: 'PRODUCT_NOT_FOUND', message: 'ไม่พบสินค้า' }
    });
  }

  res.json(product);
});
Method Route หน้าที่
GET /api/products อ่านรายการสินค้า
GET /api/products/:id อ่านสินค้ารายการเดียว
POST /api/products เพิ่มสินค้า
PUT /api/products/:id แก้ไขสินค้าทั้งรายการ
PATCH /api/products/:id แก้ไขบาง field
DELETE /api/products/:id ลบสินค้า

4. Middleware: จุดตรวจระหว่างทาง

Middleware คือ function ที่ทำงานระหว่างการรับ request และการส่ง response ใช้สำหรับงานที่ต้องทำซ้ำหลาย endpoint เช่น logging, validation, authentication, parsing JSON และ error handling

%%{init: {'theme': 'base', 'themeVariables': {
  'background': '#282828',
  'primaryColor': '#3c3836',
  'primaryTextColor': '#fbf1c7',
  'primaryBorderColor': '#fabd2f',
  'lineColor': '#b8bb26',
  'secondaryColor': '#504945',
  'tertiaryColor': '#665c54',
  'fontFamily': 'Arial'
}}}%%
flowchart LR
  A[Request
คำขอ] --> B[Logger
บันทึก] B --> C[JSON Parser
อ่าน body] C --> D[Validation
ตรวจข้อมูล] D --> E[Route Handler
ทำงานหลัก] E --> F[Response
ผลลัพธ์]
// middleware สำหรับ logging
function requestLogger(req, res, next) {
  console.log(`${req.method} ${req.url}`);
  next();
}

app.use(requestLogger);
Middleware ใช้ทำอะไร
express.json() อ่าน JSON body
Logger บันทึก method และ URL
Validation ตรวจว่าข้อมูลครบและถูกต้อง
Authentication ตรวจ token หรือ session
Error Handler รวมรูปแบบ error response

5. การตรวจสอบข้อมูลและสร้าง Resource

ก่อนบันทึกข้อมูลใหม่ server ควรตรวจสอบ request body เพื่อป้องกันข้อมูลไม่ครบหรือผิดชนิด หากข้อมูลผิดควรส่ง status code 400 Bad Request พร้อม error message ที่ front-end นำไปแสดงต่อได้

app.post('/api/products', (req, res) => {
  const { name, price } = req.body;

  if (!name) {
    return res.status(400).json({
      error: {
        code: 'PRODUCT_NAME_REQUIRED',
        message: 'กรุณาระบุชื่อสินค้า',
        field: 'name'
      }
    });
  }

  if (typeof price !== 'number' || price <= 0) {
    return res.status(400).json({
      error: {
        code: 'PRODUCT_PRICE_INVALID',
        message: 'ราคาสินค้าต้องเป็นตัวเลขมากกว่า 0',
        field: 'price'
      }
    });
  }

  const product = {
    id: products.length + 1,
    name,
    price
  };

  products.push(product);
  res.status(201).json(product);
});

6. Controller และ Service Layer

เมื่อระบบใหญ่ขึ้น ไม่ควรเขียน logic ทั้งหมดไว้ใน route handler เพราะจะอ่านยากและทดสอบยาก ควรแบ่งเป็น Controller สำหรับรับ request/response และ Service สำหรับ business logic

// product.service.js
const products = [
  { id: 1, name: 'Keyboard', price: 850 }
];

function findAllProducts() {
  return products;
}

function createProduct(data) {
  const product = {
    id: products.length + 1,
    name: data.name,
    price: data.price
  };

  products.push(product);
  return product;
}

module.exports = { findAllProducts, createProduct };
// product.controller.js
const productService = require('./product.service');

function getProducts(req, res) {
  const products = productService.findAllProducts();
  res.json(products);
}

function createProduct(req, res) {
  const product = productService.createProduct(req.body);
  res.status(201).json(product);
}

module.exports = { getProducts, createProduct };

7. Error Handling ที่ดี

Error Handling ที่ดีช่วยให้ client เข้าใจปัญหาและช่วยให้นักพัฒนาตรวจสอบระบบได้ง่าย ควรแยกข้อความสำหรับผู้ใช้กับรายละเอียดเชิงเทคนิคออกจากกัน โดยเฉพาะใน production

// middleware สำหรับจัดการ error รวม
function errorHandler(error, req, res, next) {
  console.error(error);

  res.status(error.status || 500).json({
    error: {
      code: error.code || 'INTERNAL_SERVER_ERROR',
      message: error.message || 'เกิดข้อผิดพลาดในระบบ'
    }
  });
}

app.use(errorHandler);

รูปแบบ Error Response ที่แนะนำ

{
  "error": {
    "code": "PRODUCT_NOT_FOUND",
    "message": "ไม่พบสินค้า",
    "field": null
  }
}
Status Code ใช้เมื่อ
400 request body หรือ parameter ไม่ถูกต้อง
401 ยังไม่ได้ยืนยันตัวตน
403 ไม่มีสิทธิ์เข้าถึง
404 ไม่พบ resource
409 ข้อมูลซ้ำหรือขัดแย้ง
500 server error

8. Environment Variables

Environment Variables ใช้เก็บค่าตั้งค่าที่ไม่ควร hard-code ใน source code เช่น port, database URL, secret key และ API key ช่วยให้ใช้ config ต่างกันระหว่าง development, testing และ production ได้

PORT=3000
DATABASE_URL=postgres://user:password@localhost:5432/appdb
JWT_SECRET=change-this-secret
NODE_ENV=development
const express = require('express');

const app = express();
const port = process.env.PORT || 3000;

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
ตัวแปร ใช้เก็บ
PORT port ของ server
DATABASE_URL connection string ของฐานข้อมูล
JWT_SECRET secret สำหรับ token
NODE_ENV environment เช่น development/production
API_BASE_URL URL ของบริการอื่นที่ต้องเรียก

9. Node-RED สำหรับสร้าง API แบบ Visual Flow

Node-RED เป็นเครื่องมือแบบ flow-based programming ที่ใช้สร้าง HTTP endpoint ได้โดยลาก node มาต่อกัน เหมาะกับงาน prototype, integration และระบบที่ต้องเชื่อมต่อบริการหลายชนิด

%%{init: {'theme': 'base', 'themeVariables': {
  'background': '#282828',
  'primaryColor': '#3c3836',
  'primaryTextColor': '#fbf1c7',
  'primaryBorderColor': '#fabd2f',
  'lineColor': '#d3869b',
  'secondaryColor': '#504945',
  'tertiaryColor': '#665c54',
  'fontFamily': 'Arial'
}}}%%
flowchart LR
  A[HTTP In
รับ endpoint] --> B[Function
เตรียมข้อมูล] B --> C[Database/API Node
เชื่อมข้อมูล] C --> D[HTTP Response
ส่งผลลัพธ์]
Node หน้าที่
HTTP In สร้าง endpoint เช่น GET /products
Function เขียน JavaScript เพื่อจัดการข้อมูล
Change เปลี่ยนค่าใน message
Database Node เชื่อมต่อฐานข้อมูล
HTTP Response ส่ง response กลับ client

10. การประมาณเวลาประมวลผลฝั่ง Back-end

เวลาตอบสนองของ API เกิดจากหลายส่วน เช่น network, middleware, business logic และ database query การเข้าใจส่วนประกอบนี้ช่วยให้ debug และปรับ performance ได้ตรงจุด

T=M+L+D+R

11. Mini Project: Product API

ในบทนี้ให้สร้าง API สำหรับ resource products โดยใช้ Node.js/Express หรือ Node-RED และทดสอบด้วย Postman

product-api/
  server.js
  routes/
    product.routes.js
  controllers/
    product.controller.js
  services/
    product.service.js
  middlewares/
    error-handler.js
  .env

ขอบเขต API

Endpoint หน้าที่
GET /api/products อ่านรายการสินค้า
GET /api/products/:id อ่านสินค้ารายการเดียว
POST /api/products เพิ่มสินค้า
PUT /api/products/:id แก้ไขสินค้า
DELETE /api/products/:id ลบสินค้า
GET /api/health ตรวจสถานะ server

Checklist ก่อนส่งงานบทที่ 6

รายการตรวจ คำถามที่ต้องตอบ
Routing มี endpoint สำหรับ resource อย่างน้อย 1 ชุดหรือไม่
Middleware ใช้ middleware สำหรับ JSON/logging/validation หรือไม่
Validation ตรวจข้อมูลก่อนสร้างหรือแก้ไขหรือไม่
Error Handling error response มี status code และ message ชัดเจนหรือไม่
Environment แยกค่า port หรือ config ด้วย environment variables หรือไม่
Testing ทดสอบ endpoint ด้วย Postman แล้วหรือไม่
Structure แยก route/controller/service อ่านง่ายหรือไม่

กิจกรรม

สร้าง API สำหรับระบบ Product API โดยเลือกใช้ Node.js/Express หรือ Node-RED:

  1. มี endpoint อย่างน้อย 1 resource
  2. รองรับ GET และ POST เป็นอย่างน้อย
  3. ตรวจสอบข้อมูลก่อนสร้าง resource
  4. ส่ง status code และ JSON response ให้เหมาะสม
  5. มี error response เมื่อข้อมูลไม่ถูกต้องหรือไม่พบ resource
  6. ทดสอบด้วย Postman พร้อมบันทึกผลลัพธ์

คำถามทบทวน

  1. Back-end ทำหน้าที่อะไรใน web application
  2. Route และ middleware ต่างกันอย่างไร
  3. ทำไมควรแยก controller และ service layer
  4. Environment variables เหมาะกับการเก็บค่าใด
  5. Error handling ที่ดีควรตอบกลับ client อย่างไร

กลับรายวิชา