ОНОЛ 07

API Дизайн ба RESTful Үйлчилгээ

ЛЕКЦ 07: API ДИЗАЙН БА RESTFUL ҮЙЛЧИЛГЭЭ (API Design & RESTful Services)

Хичээлийн зорилго: API-ийн ойлголт, REST архитектурын зарчмууд, HTTP протокол, RESTful API дизайн, Spring Boot ашиглан API хөгжүүлэх, аюулгүй байдал, баримт бичиг зэргийг Java жишээнүүдтэйгээр эзэмшүүлэх.

Хамрах хүрээ: API тодорхойлолт, REST зарчмууд, HTTP методууд, Status Code, URI дизайн, Request/Response, JSON, Spring Boot REST Controller, DTO Pattern, Validation, Exception Handling, Authentication/Authorization, API Versioning, Documentation (OpenAPI/Swagger), HATEOAS, Rate Limiting.



ХЭСЭГ 1: ОНОЛЫН СУУРЬ (Theory & Foundations)

1.1 API гэж юу вэ?

API (Application Programming Interface) — Програм хоорондын харилцааны гэрээ (contract). Нэг програм нөгөө програмтай мэдээлэл солилцох, функц дуудах боломжийг олгоно.

💡 Зүйрлэл: Зоогийн газрын цэс (меню) шиг — та гал тогооны өрөөнд ороод хоол хийхгүй. ЦЭСНЭЭС сонгоод, зөөгч (API) дамжуулж, хоолоо авна. API = Цэс + Зөөгч.

API-ийн төрлүүд:

#ТөрөлТайлбарЖишээ
1Web API (REST)HTTP-ээр дамжуулан ажилладагGitHub API, Google Maps API
2Library APIСангийн функцүүдJava Collections API
3OS APIҮйлдлийн системийн интерфейсWindows API, POSIX
4Database APIМэдээллийн сантай харилцахJDBC, JPA
5GraphQLQuery-д суурилсанGitHub GraphQL API
6gRPCӨндөр гүйцэтгэлтэй RPCGoogle-ийн дотоод үйлчилгээ

API яагаад чухал вэ?

┌──────────────┐     API      ┌──────────────┐
│   Frontend   │◄────────────►│   Backend    │
│  (React,     │   HTTP/JSON  │  (Spring     │
│   Mobile)    │              │   Boot)      │
└──────────────┘              └──────┬───────┘
                                     │ API
                              ┌──────▼───────┐
                              │  Database    │
                              │  (PostgreSQL)│
                              └──────────────┘

┌──────────────┐     API      ┌──────────────┐
│  Гадаад      │◄────────────►│  Манай       │
│  Систем      │              │  Систем      │
│  (Банк,      │              │              │
│   SMS)       │              │              │
└──────────────┘              └──────────────┘
  • Frontend ↔ Backend хоорондын гүүр
  • Мобайл апп ↔ Сервер хоорондын гүүр
  • Гадаад систем (төлбөр, SMS, газрын зураг) ашиглах
  • Microservice архитектурт үйлчилгээ хоорондын харилцаа

1.2 REST гэж юу вэ?

REST (Representational State Transfer) — Roy Fielding 2000 онд докторын дипломын ажилдаа тодорхойлсон архитектурын хэв маяг (architectural style). Web-ийн стандарт протокол (HTTP) дээр суурилсан.

💡 Зүйрлэл: Шуудангийн систем шиг — Хаяг (URL) + Үйлдэл (GET/POST) + Агуулга (JSON) = Мэдээлэл солилцох.

REST-ийн 6 зарчим:

#ЗарчимАнглиТайлбар
1Клиент-СерверClient-ServerКлиент ба сервер тусдаа, бие даасан
2ТөлөвгүйStatelessСервер клиентийн төлөв хадгалахгүй — хүсэлт бүр бие даасан
3Кэшлэх боломжтойCacheableХариу кэшлэгдэж болно (хурд нэмэх)
4Нэгдмэл интерфейсUniform InterfaceURL, HTTP метод, JSON — нэгдсэн дүрмээр
5Давхарт системLayered SystemКлиент завсрын давхарга (load balancer, proxy) мэдэхгүй
6Код дуудахCode on Demand (заавал биш)Сервер клиент руу код (JS) илгээж болно

Stateless (Төлөвгүй) — Яагаад чухал вэ?

// ❌ STATEFUL — Сервер хэрэглэгчийн төлөв хадгална
Хүсэлт 1: "Нэвтрэх" → Сервер: session["user"] = "Бат"
Хүсэлт 2: "Захиалга" → Сервер: session["user"]-аас "Бат" гэж олно
⚠️ Асуудал: Сервер 2 руу шилжвэл session алга!

// ✅ STATELESS — Хүсэлт бүрт бүх мэдээлэл агуулагдана
Хүсэлт 1: "Нэвтрэх" → Сервер: JWT Token буцаана
Хүсэлт 2: "Захиалга" + Token → Сервер: Token-аас "Бат" гэж мэднэ
✅ Аль ч сервер руу очсон ажиллана (scale хялбар)

1.3 HTTP протокол

1.3.1 HTTP методууд (Verbs)

МетодЗорилгоИдемпотентАюулгүйCRUD
GETНөөц авах (уншиx)✅ Тийм✅ ТиймRead
POSTШинэ нөөц үүсгэх❌ Үгүй❌ ҮгүйCreate
PUTНөөц бүхлээр нь солих✅ Тийм❌ ҮгүйUpdate (бүхэлд)
PATCHНөөцийн зарим хэсгийг өөрчлөх❌ Үгүй❌ ҮгүйUpdate (хэсэг)
DELETEНөөц устгах✅ Тийм❌ ҮгүйDelete

Идемпотент = Олон удаа дуудсан ч үр дүн ижил.

  • GET /students/1 → Хэдэн удаа дуудсан ч ижил оюутан буцна.
  • DELETE /students/1 → Нэг удаа устгана, дахин дуудвал "олдсонгүй" (үр дүн ижил — устгагдсан).
  • POST /students → Дуудах бүрт ШИНЭ оюутан үүснэ (идемпотент БИШ).

1.3.2 HTTP Status Code (Хариуны код)

КодБүлэгТайлбарЖишээ
200✅ SuccessАмжилттайGET хариу
201✅ CreatedШинэ нөөц үүссэнPOST амжилттай
204✅ No ContentАмжилттай, хариу хоосонDELETE амжилттай
400❌ Bad RequestБуруу хүсэлтValidation алдаа
401❌ UnauthorizedНэвтрэлт шаардлагатайToken байхгүй
403❌ ForbiddenХандах эрхгүйЭрх хүрэлцэхгүй
404❌ Not FoundНөөц олдсонгүйID буруу
405❌ Method Not AllowedМетод зөвшөөрөгдөхгүйGET-ийн оронд PUT
409❌ ConflictЗөрчилДавхардсан бүртгэл
422❌ Unprocessable EntityБоловсруулж чадахгүйЛогик алдаа
429❌ Too Many RequestsХэт олон хүсэлтRate limit
500💥 Internal Server ErrorСерверийн дотоод алдааBug, crash
502💥 Bad GatewayGateway алдааBackend унтарсан
503💥 Service UnavailableҮйлчилгээ боломжгүйЗасвартай
Бүлэглэлт:
1xx = Мэдээлэл (Informational)
2xx = Амжилттай (Success)        ← Бүгд сайн
3xx = Чиглүүлэлт (Redirection)
4xx = Клиентийн алдаа (Client Error) ← Хэрэглэгч буруу
5xx = Серверийн алдаа (Server Error) ← Сервер буруу

1.3.3 HTTP Headers

HeaderТөрөлТайлбар
Content-TypeRequest/ResponseАгуулгын формат: application/json
AcceptRequestКлиент хүссэн формат: application/json
AuthorizationRequestНэвтрэлтийн мэдээлэл: Bearer <token>
Cache-ControlResponseКэш тохиргоо: no-cache, max-age=3600
LocationResponseШинэ нөөцийн URL (201 Created-д)
X-Request-IdCustomХүсэлтийн давтагдашгүй ID (tracking)

1.4 RESTful URI дизайн

1.4.1 Нөөц (Resource) төвтэй дизайн

🔑 REST-ийн гол зарчим: URI нь НӨӨЦ (noun)-ийг илэрхийлнэ, ҮЙЛДЭЛ (verb)-ийг БИШ. Үйлдлийг HTTP метод илэрхийлнэ.

// ❌ БУРУУ — URI-д үйлдэл (verb) байна
GET /getStudents
GET /getAllStudents
POST /createStudent
PUT /updateStudent/1
DELETE /deleteStudent/1

// ✅ ЗӨӨВ — URI нь нөөцийг илэрхийлж, HTTP метод нь үйлдлийг
GET    /students          → Бүх оюутан авах
GET    /students/1        → ID=1 оюутан авах
POST   /students          → Шинэ оюутан үүсгэх
PUT    /students/1        → ID=1 оюутныг бүхэлд нь шинэчлэх
PATCH  /students/1        → ID=1 оюутны зарим хэсгийг өөрчлөх
DELETE /students/1        → ID=1 оюутныг устгах

1.4.2 URI дизайны дүрмүүд

#ДүрэмЗөвБуруу
1Олон тоо ашиглах/students/student
2Жижиг үсэг/students/Students
3Зураас (-) ашиглах/course-enrollments/courseEnrollments
4Төгсгөлд / байхгүй/students/students/
5Файлын өргөтгөлгүй/students/students.json
6Шатлалтай/students/1/courses/getStudentCourses?id=1
7Үйлдэл (verb) байхгүйPOST /studentsPOST /createStudent

1.4.3 Шатлалтай нөөц (Nested Resources)

// Оюутны хичээлүүд
GET /students/1/courses              → ID=1 оюутны бүх хичээл
GET /students/1/courses/5            → ID=1 оюутны 5-р хичээл
POST /students/1/courses             → ID=1 оюутанд хичээл нэмэх

// Хичээлийн оюутнууд
GET /courses/5/students              → 5-р хичээлийн бүх оюутан

// Гүнзгий шатлал (2-оос илүү зайлсхий)
GET /universities/1/departments/3/students  → Хэт гүнзгий ❌
GET /departments/3/students                 → Илүү энгийн ✅

1.4.4 Шүүлт, Эрэмбэ, Хуудаслалт (Filtering, Sorting, Pagination)

// Шүүлтүүр (Filter) — Query Parameter ашиглах
GET /students?status=active                  → Идэвхтэй оюутнууд
GET /students?gpa_min=3.5&status=active      → GPA >= 3.5 + идэвхтэй

// Эрэмбэ (Sort)
GET /students?sort=name&order=asc            → Нэрээр А→Я
GET /students?sort=gpa&order=desc            → GPA-аар буурах

// Хуудаслалт (Pagination)
GET /students?page=1&size=20                 → 1-р хуудас, 20 бичлэг
GET /students?page=2&size=20                 → 2-р хуудас

// Бүгд хамтдаа
GET /students?status=active&sort=gpa&order=desc&page=1&size=10

1.5 Request & Response формат

1.5.1 JSON формат

JSON (JavaScript Object Notation) — API-ийн хамгийн түгээмэл өгөгдлийн формат.

// Нэг оюутан (Response)
{
    "id": 1,
    "name": "Батболд",
    "email": "batbold@example.com",
    "gpa": 3.75,
    "status": "ACTIVE",
    "enrolledAt": "2024-09-01"
}

// Олон оюутан (Хуудаслалттай Response)
{
    "content": [
        {"id": 1, "name": "Батболд", "gpa": 3.75},
        {"id": 2, "name": "Сарангэрэл", "gpa": 3.90}
    ],
    "page": 1,
    "size": 20,
    "totalElements": 150,
    "totalPages": 8
}

1.5.2 Request Body (POST/PUT)

// POST /students — Шинэ оюутан үүсгэх
{
    "name": "Батболд",
    "email": "batbold@example.com",
    "gpa": 3.75
}

// PUT /students/1 — Оюутныг бүхэлд нь шинэчлэх
{
    "name": "Батболд Дорж",
    "email": "batbold.dorj@example.com",
    "gpa": 3.80
}

// PATCH /students/1 — Зөвхөн email шинэчлэх
{
    "email": "new.email@example.com"
}

1.5.3 Алдааны Response (Error Response)

// 400 Bad Request
{
    "status": 400,
    "error": "Bad Request",
    "message": "Validation алдаа",
    "details": [
        {"field": "email", "message": "Имэйл формат буруу"},
        {"field": "name", "message": "Нэр хоосон байж болохгүй"}
    ],
    "timestamp": "2024-09-15T10:30:00",
    "path": "/api/v1/students"
}

// 404 Not Found
{
    "status": 404,
    "error": "Not Found",
    "message": "ID=999 оюутан олдсонгүй",
    "timestamp": "2024-09-15T10:30:00",
    "path": "/api/v1/students/999"
}

1.6 Spring Boot REST API хөгжүүлэлт

1.6.1 Давхарт архитектур (Layered Architecture)

┌────────────────────────────────────────────┐
│            Client (Browser, Mobile)        │
└──────────────────┬─────────────────────────┘
                   │ HTTP Request/Response
┌──────────────────▼─────────────────────────┐
│        Controller Layer (REST API)         │
│   @RestController — Хүсэлт хүлээн авах    │
└──────────────────┬─────────────────────────┘
                   │ DTO ↔ Entity
┌──────────────────▼─────────────────────────┐
│          Service Layer (Бизнес логик)      │
│   @Service — Бизнес дүрэм, логик          │
└──────────────────┬─────────────────────────┘
                   │ Entity
┌──────────────────▼─────────────────────────┐
│        Repository Layer (Мэдээллийн сан)   │
│   @Repository / JpaRepository              │
└──────────────────┬─────────────────────────┘
                   │ SQL
┌──────────────────▼─────────────────────────┐
│              Database (PostgreSQL)          │
└────────────────────────────────────────────┘

1.6.2 Entity (Мэдээллийн сангийн хүснэгт)

@Entity
@Table(name = "students")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private Double gpa;

    @Enumerated(EnumType.STRING)
    private StudentStatus status = StudentStatus.ACTIVE;

    @Column(name = "enrolled_at")
    private LocalDate enrolledAt;

    // Constructor, Getter, Setter
}

public enum StudentStatus {
    ACTIVE, INACTIVE, GRADUATED, SUSPENDED
}

1.6.3 DTO (Data Transfer Object)

🔑 DTO яагаад хэрэгтэй? Entity-г шууд API-аар буцаахгүй — нууц мэдээлэл (password), шаардлагагүй талбар (internal ID) задрах эрсдэлтэй.

// Request DTO — Клиентээс ирэх
public record StudentCreateRequest(
    @NotBlank(message = "Нэр хоосон байж болохгүй")
    String name,

    @Email(message = "Имэйл формат буруу")
    @NotBlank(message = "Имэйл хоосон байж болохгүй")
    String email,

    @Min(value = 0, message = "GPA 0-аас бага байж болохгүй")
    @Max(value = 4, message = "GPA 4-аас их байж болохгүй")
    Double gpa
) {}

// Response DTO — Клиент руу буцах
public record StudentResponse(
    Long id,
    String name,
    String email,
    Double gpa,
    String status,
    LocalDate enrolledAt
) {
    public static StudentResponse from(Student student) {
        return new StudentResponse(
            student.getId(),
            student.getName(),
            student.getEmail(),
            student.getGpa(),
            student.getStatus().name(),
            student.getEnrolledAt()
        );
    }
}

1.6.4 Repository

public interface StudentRepository extends JpaRepository<Student, Long> {

    Optional<Student> findByEmail(String email);

    List<Student> findByStatus(StudentStatus status);

    @Query("SELECT s FROM Student s WHERE s.gpa >= :minGpa")
    List<Student> findByMinGpa(@Param("minGpa") Double minGpa);

    boolean existsByEmail(String email);
}

1.6.5 Service

@Service
@RequiredArgsConstructor
public class StudentService {

    private final StudentRepository repository;

    public List<StudentResponse> findAll() {
        return repository.findAll().stream()
            .map(StudentResponse::from)
            .toList();
    }

    public StudentResponse findById(Long id) {
        Student student = repository.findById(id)
            .orElseThrow(() -> new StudentNotFoundException(
                "ID=" + id + " оюутан олдсонгүй"
            ));
        return StudentResponse.from(student);
    }

    @Transactional
    public StudentResponse create(StudentCreateRequest request) {
        if (repository.existsByEmail(request.email())) {
            throw new DuplicateEmailException(
                "'" + request.email() + "' имэйл бүртгэлтэй байна"
            );
        }

        Student student = new Student();
        student.setName(request.name());
        student.setEmail(request.email());
        student.setGpa(request.gpa());
        student.setEnrolledAt(LocalDate.now());

        Student saved = repository.save(student);
        return StudentResponse.from(saved);
    }

    @Transactional
    public StudentResponse update(Long id, StudentCreateRequest request) {
        Student student = repository.findById(id)
            .orElseThrow(() -> new StudentNotFoundException(
                "ID=" + id + " оюутан олдсонгүй"
            ));

        student.setName(request.name());
        student.setEmail(request.email());
        student.setGpa(request.gpa());

        Student saved = repository.save(student);
        return StudentResponse.from(saved);
    }

    @Transactional
    public void delete(Long id) {
        if (!repository.existsById(id)) {
            throw new StudentNotFoundException(
                "ID=" + id + " оюутан олдсонгүй"
            );
        }
        repository.deleteById(id);
    }
}

1.6.6 Controller

@RestController
@RequestMapping("/api/v1/students")
@RequiredArgsConstructor
public class StudentController {

    private final StudentService studentService;

    @GetMapping
    public ResponseEntity<List<StudentResponse>> findAll() {
        return ResponseEntity.ok(studentService.findAll());
    }

    @GetMapping("/{id}")
    public ResponseEntity<StudentResponse> findById(@PathVariable Long id) {
        return ResponseEntity.ok(studentService.findById(id));
    }

    @PostMapping
    public ResponseEntity<StudentResponse> create(
            @Valid @RequestBody StudentCreateRequest request) {
        StudentResponse created = studentService.create(request);
        URI location = URI.create("/api/v1/students/" + created.id());
        return ResponseEntity.created(location).body(created);
    }

    @PutMapping("/{id}")
    public ResponseEntity<StudentResponse> update(
            @PathVariable Long id,
            @Valid @RequestBody StudentCreateRequest request) {
        return ResponseEntity.ok(studentService.update(id, request));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable Long id) {
        studentService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

1.6.7 Global Exception Handler

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(StudentNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(StudentNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            HttpStatus.NOT_FOUND.value(),
            "Not Found",
            ex.getMessage(),
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }

    @ExceptionHandler(DuplicateEmailException.class)
    public ResponseEntity<ErrorResponse> handleDuplicate(DuplicateEmailException ex) {
        ErrorResponse error = new ErrorResponse(
            HttpStatus.CONFLICT.value(),
            "Conflict",
            ex.getMessage(),
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(
            MethodArgumentNotValidException ex) {
        List<String> details = ex.getBindingResult().getFieldErrors().stream()
            .map(e -> e.getField() + ": " + e.getDefaultMessage())
            .toList();

        ErrorResponse error = new ErrorResponse(
            HttpStatus.BAD_REQUEST.value(),
            "Validation Error",
            "Оролтын өгөгдөл буруу",
            LocalDateTime.now(),
            details
        );
        return ResponseEntity.badRequest().body(error);
    }
}

public record ErrorResponse(
    int status,
    String error,
    String message,
    LocalDateTime timestamp,
    List<String> details
) {
    public ErrorResponse(int status, String error, String message,
                         LocalDateTime timestamp) {
        this(status, error, message, timestamp, null);
    }
}

1.7 API хувилбар (Versioning)

Яагаад API хувилбар хэрэгтэй вэ?

API өөрчлөгдөхөд хуучин клиентүүд ЭВДРЭХГҮЙ байх → Хувилбараар удирдах.

#АргаЖишээДавуу талСул тал
1URI Path/api/v1/studentsЭнгийн, тодорхойURI өөрчлөгдөнө
2Query Param/api/students?version=1Уян хатанМартаж болно
3HeaderAccept: application/vnd.api.v1+jsonURI цэвэрХүндрэлтэй
4Media TypeContent-Type: application/vnd.api.v1+jsonСтандартНарийн

Зөвлөмж: URI Path (/api/v1/...) нь хамгийн энгийн, түгээмэл, ойлгомжтой → Эхлэгчдэд тохиромжтой.


1.8 Authentication & Authorization

1.8.1 Ялгаа

ОйлголтТайлбарЗүйрлэл
Authentication (AuthN)Хэн бэ? НэвтрэлтПаспорт шалгах
Authorization (AuthZ)Юу хийж болох вэ? ЭрхVIP билет шалгах

1.8.2 JWT (JSON Web Token)

┌─────────┐   1. Login (username, password)    ┌─────────┐
│         │ ──────────────────────────────────► │         │
│ Client  │   2. JWT Token                      │ Server  │
│         │ ◄────────────────────────────────── │         │
│         │   3. Request + Authorization:       │         │
│         │      Bearer <token>                 │         │
│         │ ──────────────────────────────────► │         │
│         │   4. Response (200 OK)              │         │
│         │ ◄────────────────────────────────── │         │
└─────────┘                                     └─────────┘

JWT бүтэц:

Header.Payload.Signature

// Header
{
    "alg": "HS256",
    "typ": "JWT"
}

// Payload (Claims)
{
    "sub": "batbold@example.com",
    "name": "Батболд",
    "role": "STUDENT",
    "iat": 1694736000,
    "exp": 1694822400
}

// Signature
HMACSHA256(base64(header) + "." + base64(payload), secret)

1.8.3 API Key vs OAuth 2.0 vs JWT

АргаТохиромжтойТайлбар
API KeyЭнгийн интеграциНэг түлхүүр — хялбар, гэхдээ хязгаарлагдмал
JWTStateless authToken-д мэдээлэл агуулагдана, session-гүй
OAuth 2.0Гуравдагч этгээдийн нэвтрэлт"Google-ээр нэвтрэх" зэрэг

1.9 API Баримт бичиг (Documentation)

OpenAPI / Swagger

OpenAPI — API-ийн тодорхойлолтын стандарт формат (YAML/JSON). Swagger UI — OpenAPI-с автоматаар интерактив баримт бичиг үүсгэнэ.

# openapi.yaml жишээ (хялбаршуулсан)
openapi: 3.0.3
info:
  title: Student API
  version: 1.0.0
paths:
  /api/v1/students:
    get:
      summary: Бүх оюутан авах
      responses:
        '200':
          description: Амжилттай
    post:
      summary: Шинэ оюутан үүсгэх
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StudentCreateRequest'
      responses:
        '201':
          description: Үүсгэгдсэн

Spring Boot + Swagger тохиргоо:

// build.gradle
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'

// application.yml
springdoc:
  api-docs:
    path: /api-docs
  swagger-ui:
    path: /swagger-ui.html

// Controller дээр annotation
@Operation(summary = "Бүх оюутан авах", description = "Бүх оюутны жагсаалт")
@ApiResponse(responseCode = "200", description = "Амжилттай")
@GetMapping
public ResponseEntity<List<StudentResponse>> findAll() { ... }

Swagger UI: http://localhost:8080/swagger-ui.html — Браузераас API-г шууд туршиж болно.


1.10 REST API шилдэг туршлагууд (Best Practices)

#ЗарчимТайлбар
1Нөөц төвтэй URI/students (noun), /createStudent биш (verb)
2HTTP метод зөв ашиглахGET = Унших, POST = Үүсгэх, PUT = Шинэчлэх, DELETE = Устгах
3Status Code зөв буцаах200, 201, 204, 400, 404, 500 — Зорилгод тохирсон
4Хувилбар ашиглах/api/v1/students
5Validation хийх@Valid, @NotBlank, @Email
6Нэгдмэл алдааны форматErrorResponse DTO
7ХуудаслалтОлон бичлэгт page, size parameter
8DTO ашиглахEntity шууд буцаахгүй
9HTTPS ашиглахМэдээлэл шифрлэгдэнэ
10Rate LimitingХэт олон хүсэлтээс хамгаалах
11Баримт бичигSwagger / OpenAPI
12IdempotencyPUT, DELETE идемпотент байх

1.11 REST vs GraphQL vs gRPC

ШинжRESTGraphQLgRPC
ПротоколHTTP/JSONHTTP/JSONHTTP/2 + Protobuf
ХүсэлтОлон endpointНэг endpoint, queryService method
Over-fetchingБайж болноБайхгүй (хэрэгтэйгээ сонгоно)Байхгүй
Under-fetchingБайж болноБайхгүйБайхгүй
СуралцахадХялбарДундХүнд
ХурдСайнСайнХамгийн хурдан
ТохиромжтойCRUD API, вэбУян хатан query, mobileMicroservice, real-time

Over-fetching = Хэрэгцээнээс илүү мэдээлэл ирэх (жишээ: зөвхөн нэр хэрэгтэй, бүх талбар ирэх). Under-fetching = Нэг хүсэлтээр хүрэлцэхгүй, нэмэлт хүсэлт шаардлагатай.


1.12 HATEOAS

HATEOAS (Hypermedia As The Engine Of Application State) — REST-ийн дээд түвшний зарчим. Response дотор дараагийн боломжит үйлдлүүдийн холбоос агуулна.

// HATEOAS Response жишээ
{
    "id": 1,
    "name": "Батболд",
    "email": "batbold@example.com",
    "gpa": 3.75,
    "_links": {
        "self": {"href": "/api/v1/students/1"},
        "courses": {"href": "/api/v1/students/1/courses"},
        "update": {"href": "/api/v1/students/1", "method": "PUT"},
        "delete": {"href": "/api/v1/students/1", "method": "DELETE"}
    }
}

💡 Зүйрлэл: Вэб хуудас дахь "Дараах", "Өмнөх", "Засах", "Устгах" товчлуурууд шиг — API-ийн хариунд дараа юу хийж болохыг заасан холбоосууд.



ХЭСЭГ 2: ТҮЛХҮҮР ҮГ БА МЭРГЭЖЛИЙН НЭР ТОМЬЁО (Keywords & Glossary)

#Англи нэр томьёоМонгол утгаДэлгэрэнгүй тайлбар
1APIПрограмын интерфейсApplication Programming Interface — Програм хоорондын харилцааны гэрээ.
2RESTТөлөөлөлт шилжүүлэлтRepresentational State Transfer — HTTP дээр суурилсан архитектурын хэв маяг.
3RESTfulREST зарчимтайREST зарчмуудыг баримталсан API.
4HTTPГипертекст дамжуулах протоколHyperText Transfer Protocol — Web-ийн суурь протокол.
5HTTPSАюулгүй HTTPHTTP + TLS/SSL шифрлэлт.
6EndpointТөгсгөлийн цэгAPI-ийн тодорхой URL + HTTP метод хослол.
7URI / URLНөөцийн хаягUniform Resource Identifier — Нөөцийн байршил.
8HTTP MethodHTTP аргаGET, POST, PUT, PATCH, DELETE — Үйлдлийн төрөл.
9Status CodeХариуны код200, 404, 500 зэрэг — Хүсэлтийн үр дүнгийн код.
10JSONJSON форматJavaScript Object Notation — Өгөгдлийн формат.
11RequestХүсэлтКлиентээс сервер рүү илгээх мэдээлэл.
12ResponseХариуСерверээс клиент рүү буцах мэдээлэл.
13Request BodyХүсэлтийн биеPOST/PUT хүсэлтийн JSON өгөгдөл.
14HeaderТолгойHTTP хүсэлт/хариуны нэмэлт мэдээлэл.
15Query ParameterАсуулгын параметрURL-д ?key=value хэлбэрээр дамжуулах.
16Path VariableЗам хувьсагчURL-д /students/{id} хэлбэрээр дамжуулах.
17StatelessТөлөвгүйСервер клиентийн төлөв хадгалахгүй.
18IdempotentИдемпотентОлон удаа дуудсан ч үр дүн ижил.
19CRUDCRUD үйлдлүүдCreate, Read, Update, Delete — Суурь үйлдлүүд.
20DTOМэдээлэл дамжуулах объектData Transfer Object — API-ийн хүсэлт/хариуны объект.
21EntityНэгжМэдээллийн сангийн хүснэгтийг илэрхийлэх Java класс.
22RepositoryМэдээллийн агуулахМэдээллийн сантай харилцах давхарга.
23ServiceҮйлчилгээний давхаргаБизнес логик хариуцах давхарга.
24ControllerХянагчHTTP хүсэлт хүлээн авах, хариу буцаах давхарга.
25JWTJSON Web TokenStateless нэвтрэлтийн токен.
26AuthenticationНэвтрэлтХэн бэ? — Хэрэглэгчийг таних.
27AuthorizationЭрх зүйЮу хийж болох вэ? — Хандах эрх шалгах.
28OAuth 2.0OAuth протоколГуравдагч этгээдээр нэвтрэх стандарт.
29API KeyAPI түлхүүрAPI-д хандах нууц түлхүүр.
30Rate LimitingХурд хязгаарлалтХэт олон хүсэлтээс хамгаалах механизм.
31PaginationХуудаслалтОлон бичлэгийг хуудас хуудсаар буцаах.
32FilteringШүүлтБичлэгийг нөхцөлөөр шүүх.
33SortingЭрэмбэлэлтБичлэгийг талбараар эрэмбэлэх.
34Swagger / OpenAPIAPI баримт бичигAPI-ийн интерактив баримт бичгийн стандарт.
35HATEOASГипермедиаHypermedia As The Engine Of Application State.
36GraphQLГрафQLQuery-д суурилсан API хэл.
37gRPCgRPCGoogle-ийн өндөр хурдтай RPC framework.
38PayloadАчааХүсэлт/хариуны гол өгөгдөл.
39ValidationБаталгаажуулалтОролтын өгөгдлийг шалгах.
40SerializationЦуваачлалОбъектыг JSON/XML формат руу хөрвүүлэх.