Client‐Server - netfoor/AmplifyWorkshop-RetailStore GitHub Wiki

Arquitectura Client-Server en Next.js: Llamadas Directas vs. API Routes

📌 Introducción

En aplicaciones full-stack (como las construidas con Next.js), existen dos patrones para manejar datos:

  1. Llamadas directas desde el cliente (Frontend → Backend).
  2. Rutas de API intermedias (Frontend → API Route → Backend).

Este documento explica cuándo y por qué usar cada uno, basado en buenas prácticas de AWS y Next.js.


🔍 Comparación Detallada

1. Llamada Directa desde el Cliente

// Ejemplo: Frontend accede directamente a DynamoDB
const { data } = await client.models.Product.list({ limit: 5 });

Ventajas

  • Rápido de implementar: Ideal para prototipos.
  • Menos código: Amplify maneja la conexión.

Desventajas

  • Seguridad limitada: Credenciales temporales expuestas en el cliente.
  • Acoplamiento fuerte: Cambios en el esquema de DB afectan al frontend.
  • Poca flexibilidad: Difícil añadir lógica intermedia (ej: filtrar datos).

2. API Route + Fetch

// Ejemplo: Frontend llama a una ruta de API
const res = await fetch('/api/products');
const data = await res.json();

Ventajas

  • Seguridad: El servidor valida permisos y filtra datos.
  • Flexibilidad: Modificas la lógica sin cambiar el frontend.
  • Performance: Caching, batching, y optimizaciones en el servidor.
  • Escalabilidad: Puedes migrar a microservicios fácilmente.

❌ **Desventajas

  • Más código: Requiere definir rutas de API.
  • Latencia adicional: Un hop más en la red.

🛠 ¿Cuándo Usar Cada Enfoque?

Criterio Llamada Directa (Cliente) API Route (Servidor)
Tipo de App Prototipos/MVP Apps empresariales
Seguridad Requerida Baja (datos públicos) Alta (datos privados)
Flexibilidad Limitada Alta (transformaciones en servidor)
Mantenibilidad Frágil ante cambios Robustecida

📂 Ejemplo Práctico

Estructura de Archivos

src/
├── app/
│   ├── api/
│   │   └── products/
│   │       └── route.ts   # API Route (Server)
├── components/
│   └── ProductList.tsx    # Componente (Client)

1. API Route (app/api/products/route.ts)

import { NextResponse } from 'next/server';
import { cookiesClient } from '@/utils/server-utils';

export async function GET() {
  try {
    const { data, errors } = await cookiesClient.models.Product.list({ limit: 5 });
    if (errors) throw new Error('Error fetching products');
    return NextResponse.json(data);
  } catch (error) {
    return NextResponse.json({ error: 'Server error' }, { status: 500 });
  }
}

2. Componente Frontend (ProductList.tsx)

'use client';
import { useState, useEffect } from 'react';

export default function ProductList() {
  const [products, setProducts] = useState([]);

  useEffect(() => {
    const fetchProducts = async () => {
      const res = await fetch('/api/products');
      const data = await res.json();
      setProducts(data);
    };
    fetchProducts();
  }, []);

  return <div>{/* Renderizar productos */}</div>;
}

🔗 Flujo de Datos

sequenceDiagram
    participant Client
    participant APIRoute
    participant DynamoDB

    Client->>APIRoute: GET /api/products
    APIRoute->>DynamoDB: client.models.Product.list()
    DynamoDB-->>APIRoute: { data }
    APIRoute-->>Client: Response.json(data)
Loading

🌟 Mejores Prácticas

  1. Usa API Routes para:

    • Autenticación/autorización.
    • Acceso a bases de datos.
    • Procesamiento pesado (ej: generación de PDFs).
  2. Usa llamadas directas solo para:

    • Datos públicos no sensibles.
    • Prototipos rápidos.
  3. Documenta tus APIs:

    • Usa Swagger o OpenAPI para rutas complejas.

📚 Recursos Adicionales


### 🔥 **Conclusión**
Elegir entre llamadas directas y API Routes depende de la **seguridad**, **escalabilidad** y **flexibilidad** que necesites. Para apps profesionales, **siempre prefiere API Routes**. 
⚠️ **GitHub.com Fallback** ⚠️