[Dúvida] Qual o melhor jeito de enviar imagens do backend para o frontend sem prejudicar o desempenho?

estou criando uma aplicação java - spring + angular, será algo como um marketplace, então terão várias imagens envolvidas em cada página, eu fiz uma implementação convertendo as imagens em base64 no backend e enviando para o front, onde ele converte o base64 em imagem, renderiza e exibe, até ai tudo funciona, o grande problema é que quando eu adiciono muitos produtos, a pagina demora muito para carregar, creio que por conta da renderização da imagem em base64

então aqui vem o ponto que estou precisando de ajuda

como eu posso enviar as imagens que estão na raiz do meu servidor, para o front, sem atrapalhar tanto o desempenho?

eu sou iniciante em aplicações fullstack e agradeço desde já toda a ajuda!

Você está convertendo um arquivo binário (imagem sla jpg) para TEXTO e convertendo texto em binário novamente?

Pode ter certeza que essa é uma péssima ideia.

Base64 só pode ser usado quando não há nenhuma outra alternativa viável. Como comunicar com um sistema externo legado que você não tem controle nenhum. Evite esse formato ao máximo.

Primeiro passo

Como você está armazenando essa imagem? Qual o real motivo do backend ter que processar isso?

Não há justificativa para o backend ou o frontend sequer tocar na imagem de um sistema seu.

Se a imagem estiver em um sistema de arquivos sirva a imagem direto do servidor WEB (nginx).

Obrigado pelo comentário! Eu estou usando uma pasta na raiz do meu servidor contendo as imagens, e estou enviando essas imagens para o frontend. Como ainda não sei bem como funciona esse processo eu optei pelo base64, mas pelo visto não foi uma boa ideia. Então o Ideal seria ter um gerenciador externo para essas imagens, e armazenar no banco apenas a url da imagem? se sim, qual plataforma eu posso usar para isso? obrigado novamente!
> Então o Ideal seria ter um gerenciador externo para essas imagens Em produção sim. Estude sobre **nginx** Em desenvolvimento no spring pode ser usado a função de arquivos estaticos. Veja [aqui](https://www.baeldung.com/spring-mvc-static-resources) Com essa função você poderá servir a imagem do backend sem precisar converter. poderá acessar algo como `http(s)://endereco-do-backend/url/da/imagem` > e armazenar no banco apenas a url da imagem Sim! Vocé deve salvar o caminho relativo: `/url/da/imagem`. Na hora de exibir deve montar o caminho no spring, enviar a url pronta para o front-end e colocar essa url no img ``
Muito obrigado pelas dicas, vou estudar sobre como eu posso implementar isso, obrigado!
Apenas mais uma dúvida, em produção, o nginx poderia funcionar como gerenciador para as minhas imagens? Assim eu posso focar meus estudos e pesquisas
> o nginx poderia funcionar como gerenciador para as minhas imagens? Não ele e um server! Ele vai ajudar a publicar! Seu projeto! No seu caso o front
O Nginx apenas vai disponibilizar, a sua aplicação deve receber a imagem por upload e salvar na pasta certa. O nginx só vai resolver a url e retornar a imagem.

Como isso é feito em projetos reais?

Enviar imagens para o frontend é um problema que geralmente não resolvemos sozinhos. O mais comum é usar um serviço como o AWS S3.

Nesse tipo de solução o seu banco de dados persiste uma referência da imagem (pode ser um link) que está armazenado no AWS S3.

sequenceDiagram
Front-->>Server: HTTP request
Server-->>Database: Query 
Database-)Server: Link da imagem
Server-)Front: Link da imagem
Front -->> S3: HTTP request 
S3 -) Front: Imagem/jpeg

Esse esquema tem algumas vantagens:

  • Evita a complexidade de ter que manusear imagens no seu backend.
  • Economiza processamento e memória do seu servidor
  • Economiza processamento e memória do seu banco de dados
  • Você pode usar todos os recursos do S3 - Recursos de segurança - Integração automática com CDN, como o AWS CloudFront.

Em resumo:

Não desenvolva seu próprio serviço de imagens em um projeto real. Já trabalhei em um projeto de uma plataforma de ensino. Era tudo armazenado no S3. É seguro, confiável e escalável. Não tem opção melhor.

Sugestão: hospedar a imagem em um servidor de arquivos para isso, como um S3 na AWS por exemplo. Vc grava os dados no seu back e a imagem nesse local de repositório. No back (banco de dados) vc grava a URL da imagem do repositório e não o "arquivo" em si. No front vc faz o upload da imagem e usa um serviço (api) para enviar o binário dessa imagem para o repositório. Assim seu back não guarda dados de arquivo, nem seu banco de dados e na hora o usuário renderizar, ele recebe uma URL que irá carregar a imagem direto para ele, sem passar por sua camada de serviço.

Tenta de alguma forma servir arquivos estáticos, a maiora dos frameworks ja fornecem libraries pra esse tipo de ação, no django é servido praticamente automático, podendo utilizar local ,nao recomendo, ou buckets s3 tanto local utilizando minio em docker.

settings.py

STATIC_URL = "static"
STATIC_ROOT = BASE_DIR / "staticfiles"

MEDIA_URL= "media"
MEDIA_ROOT= BASE_DIR / "media"

urls.py

from django.conf import settings
from.django.conf.urls.static import static
...


urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

sempre retornando /static/... /media/...

Se em uma tapa você quer que o usuário receba um HTML com várias imagens em base64, você irá deixar lento mesmo.

Tem que separar os arquivos com base64 da página, assim o usuário vai ver a página e depois carregar as imagens.

As imagens também precisam ser compactadas e leves, caso o usuário queira ver mais detalhe, que use uma lupa igual faz as grandes lojas e a imagens é carregada por completo.

Acredito que o ideal seria utilizar o S3 ou algum outro serviço parecido. Armazene no banco uma referência, como o link do S3 e envie isso para o front, vai funcionar perfeitamente.