“Naquela época, um arquivo só bastava…”
O PHP com que eu trabalhava na faculdade era realmente confortável. Em um único arquivo index.php, dava para colocar as tags HTML, abrir <?php ?> no meio e escrever ali mesmo o código de consulta ao banco de dados. Não existia uma separação clara entre frontend e backend. Bastava declarar uma variável e você podia usá-la em qualquer parte do HTML, e praticamente não havia erros causados por comunicação de dados.
Mas quando, na prática, mudei para uma stack com Vue.js no frontend e Spring Boot no backend, o inferno começou.
“Eu subi o servidor Spring localmente, a tela do Vue também está funcionando, então por que os dados não chegam?”
O console das ferramentas de desenvolvedor do Chrome estava coberto de mensagens de erro em vermelho vivo.
Access to XMLHttpRequest at ... has been blocked by CORS policy
Afinal, o que é esse tal de CORS que insiste em bloquear meus dados? E por que abandonamos aquele jeito antigo e confortável, em que um único arquivo resolvia tudo, para separar de propósito frontend e backend?

Quem deve cozinhar? (SSR vs CSR)
Para entender essa mudança, primeiro é preciso entender quem prepara o “prato” chamado página web, ou seja, o HTML. É exatamente aí que está a diferença entre SSR (Server Side Rendering) e CSR (Client Side Rendering).
1. SSR: uma marmita pronta (PHP, JSP)
2. CSR: um meal kit entregue em casa (React, Vue)
[Tip] CSR e SPA não são exatamente a mesma coisa
Os dois termos costumam ser usados como se fossem sinônimos, mas, tecnicamente, não são.
Normalmente usamos CSR para construir uma SPA. Em outras palavras: como queremos evitar o piscar causado pelo recarregamento completo da página usando uma única página (SPA), escolhemos uma abordagem em que o próprio navegador redesenha as partes necessárias (CSR).
Usamos Vue.js ou React por causa da experiência do usuário. Para fazer um site se comportar com a fluidez de um app de smartphone, transferimos o ato de “cozinhar” do servidor para o navegador.

CORS, o segurança que barra os visitantes indesejados
Quando frontend (Vue) e backend (Spring) se separam, na prática passamos a ter “duas casas”.
E é aí que o problema aparece. Por razões de segurança, o navegador segue uma regra básica: “não confie com facilidade em recursos vindos de outra Origin”. Isso é a SOP, a Same Origin Policy.
Pense nisso. Eu estou logado no Naver, e um site criado por um hacker envia escondido uma requisição para o servidor do Naver dizendo: “me entregue os dados pessoais deste usuário”. Se o navegador não bloqueasse isso, todas as minhas informações ficariam expostas.
Por isso, o navegador bloqueia por padrão requisições quando a origem, ou seja, domínio ou porta, é diferente. Mas, para desenvolvimento, nós deliberadamente separamos as portas. Só queremos usar nossos próprios dados, e mesmo assim o navegador, como um segurança, responde: “Sua porta não bate. Entrada proibida.” Essa é a verdadeira natureza de um erro de CORS, isto é, Cross-Origin Resource Sharing.
[Code Verification] Emitindo um passe de entrada
A forma de resolver isso é, na verdade, simples. O servidor, ou seja, o backend, só precisa escrever um passe para o navegador, o segurança, dizendo: “Essa pessoa é um convidado que eu mesmo convidei. Pode deixar entrar.”
No Spring Boot, esse passe pode ser emitido com um único arquivo de configuração.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 1. Para todas as rotas da API
.allowedOrigins("http://localhost:8080") // 2. Permitir requisicoes desta origem
.allowedMethods("GET", "POST", "PUT", "DELETE") // 3. Permitir esses tipos de requisicao
.allowCredentials(true); // 4. Cookies e credenciais podem ser incluidos
}
}
Análise:
O ponto de atenção é o seguinte: por preguiça, não abra tudo com allowedOrigins("*"). Isso seria o mesmo que deixar a porta de casa escancarada com uma placa dizendo: “Ladrões, sejam bem-vindos”.
Conselho prático: quando usar o quê?
Então CSR, ou seja, Vue ou React, é sempre a resposta certa? Não. Na prática, a escolha depende do objetivo.
Fechando: cruzando a fronteira
A antiga “grande família sob o mesmo teto” da era do PHP era confortável, mas, quanto mais tudo se tornava complexo, mais difícil ficava administrar. O modelo atual, com “duas famílias separadas” entre frontend e backend, é mais incômodo por causa de comunicação e CORS, mas permite que cada lado se concentre melhor no seu papel.
Então, da próxima vez que você topar com um erro de CORS, tente não reagir só com irritação. O navegador não está te perseguindo; ele apenas está fazendo uma inspeção rigorosa para proteger a sua casa, isto é, o seu servidor.
Agora o caminho entre frontend e backend está aberto. Os dados podem ir e vir. Mas onde, afinal, esses dados ficam armazenados no servidor? Antigamente bastava disparar uma query e buscar o que fosse necessário. No Spring, porém, coisas como JPA e Entity dão a impressão de que escrever SQL diretamente já não é mais permitido.
Na próxima vez, vamos ver como a “forma de manual” de projetar bancos de dados, a normalização, pode na prática acabar atrapalhando e por que o JPA tenta tanto esconder o SQL de você.