스프링과 리액트를 사용하여 진행할 때 발생한 문제이다.
스프링의 Rest API를 사용하다 보면 실제 실행 시 에러가 발생한다.
이는 스프링과 리액트의 포트, 호스트, 프로토콜이 같아야 Same-Origin-Policy 정책을 만족시키는데 실제로 다르기 때문에 서버에서 CORS를 이용한다.
CORS (Cross-Origin Resource Sharing) 정책
교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다.
프로토콜(Scheme), 포트, 호스트 3가지가 같으면 같은 출처로 구분한다.
웹 클라이언트 애플리케이션이 리소스를 요청할 때 HTTP 프로토콜을 사용하여 요청하며, 헤더의 origin 필드에 요청을 보내는 리소스를 보낸다.
서버는 요청 응답에 대해 Access-Control-Allow-Origin 값에 접근 허용 리소스를 전달한다.
브라우저는 요청을 보낸 리소스와 응답을 받은 값을 비교하여 유효성을 확인한다.
React
- proxy-middleware와 axios 설치npm install http-proxy-middleware --save
npm install axios --save
Spring
- WebConfig 작성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("/**")
.allowedOrigins("http://localhost:3000");
}
}
React
- proxy.js 작성const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/',
createProxyMiddleware({
target: 'http://localhost:8080',
changeOrigin: true,
})
);
};
Spring
- 테스트 코드 작성package com.example.bookshelf.TestControllers;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/home")
public String getHome(){
return "Hello World!";
}
}
React
- 테스트 코드 작성import './App.css';
import React, {useEffect, useState} from 'react';
import axios from 'axios';
function App() {
const [hello, setHello] = useState('')
useEffect(() => {
axios.get("/home")
.then(response => setHello(response.data))
.catch(error => console.log(error))
}, []);
return (
<div>
백엔드에서 가져온 데이터입니다 : {hello}
</div>
);
}
export default App;