Как организовано взаимодействие между бэкендом и фронтендом в веб-приложении?

«Как организовано взаимодействие между бэкендом и фронтендом в веб-приложении?» — вопрос из категории Сети, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Взаимодействие строится по клиент-серверной модели через HTTP/HTTPS протокол, где фронтенд (клиент) инициирует запросы к API бэкенда (серверу).

Основные паттерны и технологии:

  1. RESTful API (Наиболее распространенный подход):

    • Фронтенд отправляет HTTP-запросы (GET, POST, PUT, DELETE, PATCH) к структурированным эндпоинтам.
    • Данные обмениваются в формате JSON (реже XML).
    • Пример запроса с фронтенда (JavaScript с Fetch API):
      
      // Получение данных (GET)
      const response = await fetch('https://api.example.com/users/123');
      const user = await response.json();

    // Отправка данных (POST) const createResponse = await fetch('https://api.example.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John', email: 'john@example.com' }) });

    *   **Пример обработки на бэкенде (ASP.NET Core):**
    ```csharp
    [ApiController]
    [Route("api/users")]
    public class UsersController : ControllerBase
    {
        [HttpGet("{id}")]
        public async Task<IActionResult> GetUser(int id)
        {
            var user = await _userRepository.GetByIdAsync(id);
            if (user == null) return NotFound(); // Статус 404
            return Ok(user); // Статус 200 + JSON
        }
    
        [HttpPost]
        public async Task<IActionResult> CreateUser([FromBody] UserCreateDto dto)
        {
            // Валидация модели происходит автоматически
            var newUser = await _userService.CreateUserAsync(dto);
            return CreatedAtAction(nameof(GetUser), 
                                   new { id = newUser.Id }, 
                                   newUser); // Статус 201
        }
    }
  2. WebSockets / SignalR (для реального времени):

    • Используется, когда серверу нужно активно "толкать" данные клиенту (чаты, live-уведомления, дашборды).
    • Устанавливается постоянное двустороннее соединение.
  3. GraphQL (альтернатива REST):

    • Фронтенд отправляет один запрос с точным описанием требуемых данных, избегая проблемы over-fetching (лишние данные) или under-fetching (недостаточно данных).

Критически важные аспекты взаимодействия:

  • Безопасность:
    • HTTPS для шифрования трафика.
    • Аутентификация/Авторизация: Чаще через JWT (JSON Web Tokens), передаваемый в заголовке Authorization: Bearer <token>.
    • CORS (Cross-Origin Resource Sharing): Настройка на бэкенде, чтобы разрешить запросы только с доверенных доменов фронтенда.
    • Валидация и санитизация всех входящих данных.
  • Надежность и обработка ошибок:
    • Использование корректных HTTP-статус кодов (200 OK, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error).
    • Стандартизированный формат тела ошибок для фронтенда.
    • Таймауты и повторные попытки (retry logic) на стороне клиента.
  • Производительность:
    • Пагинация, фильтрация и сортировка на стороне сервера для больших наборов данных.
    • Кэширование ответов (HTTP-кэширование с заголовками Cache-Control).