2023. 8. 6. 21:44ㆍ_Web/React
문제상황
Access to XMLHttpRequest at 'http://localhost:8080/booking/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
정리
0. 응답 패킷에 Access-Control-Allow-Origin 이 있는지 확인하기
1. package.json이나 setupProxy.js가 작동해서 3000포트가 아닌 것을 네트워크-요청URL에서 확인하기 => domain이 같아서 localhost:3000에서 데이터를 가져올 수 있는 경우가 있다. 이러면 백엔드에서 데이터를 가져오지 못하므로 수정해야한다.
2. 서버에 해당하는 ex)/api로 호출하는 방법인지 확인하기
3. 리액트 캐시가 남아있는지 확인하고 npm install 다시 설치하기
4. 서버에 cors로 프론트 허용하기 (아래 코드 참고)
아래 영상이 CORS(콜스라고 읽는다)가 왜 필요한지에 대해 자세히 정리해놨다.
https://www.youtube.com/watch?v=bW31xiNB8Nc
짧게 정리하자면 주소가 다른 웹사이트에서 정보를 요청할때 막는 것을 SOP라고 하고 이를 허용하는 것이 CORS라고 한다. 이는 '프론트에서' 발생하지만 벡엔드에서 해결해야 한다. 이 문제는 포스트맨에서도 발견되지 않고, 크롬과 같은 브라우저에서 발생하는 보안정책이다. 토큰, 세션, 캐시와 같은 곳에서 발생하는 인증정보 탈취문제를 예방하기 위해서 사용하기에 따라서 백엔드에서 프론트를 CORS(Cross-Origin Resource Sharing) 허용해줘야한다.
- * 와일드카드 사용시 누구나 사용가능
- CORS를 허용해주는 주소를 허용해야함
- Origin 이라는 header를 추가해야함 이게 서버의 답장 헤더에 담긴 Access-Control-Allow-Origin에 있으면 허용
아래처럼 addCorsMappings를 사용하면 스프링부트에서 허용해준다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedOrigins("*");
}
}
리액트 코드
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState([]);
useEffect(() => {
// Replace with your Spring Boot API URL
const apiUrl = 'https://your-spring-boot-api.com/api';
axios.get(apiUrl)
.then(response => {
setData(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
}, []);
return (
<div>
{data}
</div>
);
}
export default App;
GET 302가 뜨면 cors는 일단 해결한 셈이다.
문제 해결 과정
카카오 로그인을 이용한 REST API를 사용하는 도중 해당 오류가 발생했다.
구글링 끝에 백엔드 쪽에서 Access-Control-Allow-Origin 헤더가 없어서 header 설정을 했고 프론트 쪽에서는 proxy 설정을 했다 된줄 알았다. 아래 사진을 보면 개발자도구-네트워크-패킷의 헤더를 볼 수 있다.
<백엔드 스프링>
<프론트 리액트>
package.json 에 추가
아래는 사용한 코드이다.
으로 서버가 연결된 것을 확인했다.
그러나 서버에서 Booking과 같이 값을 가져오는데 문제가 생겼는데
윗 코드를 사용해서 해결했다.
문제가 되는 코드는 아래 코드이다
왜 apiRoot를 만들어서 axios.create를 사용하면 CORS가 발생하는 걸까? 무슨 차이점이 있던걸까?
개발자도구 - 네트워크를 통해서 헤더를 뜯어봤다. 문제가 발생하는 경우는 헤더가 없다. 아무래도 apiRoot는 create로 URL을 생성하였기 때문에 헤더를 달아줘야한다.
그러나 proxy를 통한 axios.get(URL,);은 헤더가 포함되어 있다.
둘의 차이를 보자면 요청 URL에 차이가 있다. 3000/booking에 요청하면 값을 받을 수 있지만, 8080/booking에 요청하면 값을 받을 수 없다. 3000?
따라서 apiRoot를 3000으로 수정하면 URL을 불러올 수 있다. 궁금점이 생겨서 proxy를 해제하고 8080의 apiRoot를 적용해보기로했다. 여기서부터 뭔가 이상함을 느낄 수 있었다.
프론트 입장에선 proxy가 있든 말든 요청 URL만 잘 맞추면 되는 거였다. CORS 오류가 스프링 8080서버와 리액트 3000 포트번호가 달라서 발생하는 문제인데 이게 된다고..? 껐다 키니까 안 된다. 다시 proxy 설정을 하니 적용이 되었다. proxy가 된 줄 알았다
요청 URL 주소 잘 확인하자.
그런데 이게 왜 되는건지? 싶은데 아래 블로그가 상황이 똑같다. 3000에 요청해도 되네요?? 왜요??
https://study-easy-coding.tistory.com/146
이는 SOP (Same-Origin Policy)라고 부르며, 프런트엔드와 백엔드가 같은 도메인이에서 실행되는 경우에만 적용된다.고 한다... 따라서 8080으로 요청을 받아야 한다. 아직도 CORS가 막혀있는거다.
따라서
npm install http-proxy-middleware --save
로 proxy 라이브러리를 설치해서 setProxy.js 를 작성하기로했다. -> setupProxy.js 로 작성해야한다.
위를 사용하려면 /api/hello 로 불러와야한다. 경로에 /api가 있다면 8080으로 호출하는 코드이다.
생각해보니 벡엔드 쪽은 /api/hello로 구현해두어서 연결이 성공했던건가? -> 알고보니 백엔드에서 해당 코드만 cors를 허용해주었다.
상대경로와 절대경로에 대해서 찾아봤다
이것도 해당이 안되었다. 아무래도 Proxy 자체가 작동하지 않는다.
아래 블로그를 참고해서 코드를 입력해서 cache랑 모두 삭제하고 다시 설치했다.
# rm -r package-lock.json
# rm -r node_modules
# npm install
npm install 오류는
npm install react-paypal-express-checkout --save --legacy-peer-deps
으로 해결했다.
https://velog.io/@eunnbi/Project-cra-proxy-setting
그런데 다시 깔아봐도 똑같았기에 아예 새 창을 만들어서 프록시가 작동하는지 부터 확인했다. 설마설마 했는데 setupProxy.js 였다.
그래도 http://localhost:3000/api 로 호출하길래 찾아봤다.
위 블로그는 ts를 사용해서,,, 좀 안맞은거 같지만 ws option을 사용하는 걸 보고, 아래 블로그로 넘어갔다.
https://maeryo88.tistory.com/339
멀티프록시 사용
yarn add http-proxy-middleware
도 안된다........ 도대체 뭐지
공식문서
https://www.npmjs.com/package/http-proxy-middleware
프록시 관련 새로운 문제 발생
[HPM] Error occurred while proxying request localhost:3000/local to http://localhost:4000/ [ECONNREFUSED] (https://nodejs
npm install concurrently --save
터미널 분리를 위해 이건 서버를 다시 키면 오류가 수정된다고 한다. 아무래도 터미널 분리 문제이다.
이건 4000에 만들어둔 서버가 없기에 발생하는거 같다는 무슨 바로 8080 proxy 오류가 발생했다.
setupProxy.js를 없애보니
아 백엔드 서버를 안 열고 켜서 그런거였다. 머쓱,, 은 무슨 그대로다
/node_modules/react-scripts/config/webpackDevServer.config.js 에서
바꿔 봤지만 그대로다.
이 블로그에선 해당 문제는 서버에서 발생한다고 해서 서버로 넘어갔다. npm run dev 명령어가 뭐지?
https://velog.io/@aksel26/HPM-Error-occurred-while-trying-to-proxy-request
아무래도 npm run 을 하는 방법인거 같다. script를 통해서 할 수 있다.
https://godnr149.tistory.com/169
npm run build -> 서버 실행 -> 리액트 실행하니까 없어졌지만 proxy는 설정되지 않았다.
https://www.youtube.com/watch?v=N4yUiQiTvwU
yarn add cors 사용하기
yarn add cors
해결중 ....
아래 블로그 참고
https://snowdeer.github.io/openshift/2020/06/13/react-for-cors-using-proxy/
'_Web > React' 카테고리의 다른 글
[React] 수도 없이 호출하는 API, 깔끔한 관리법 알아보기 (0) | 2023.08.17 |
---|---|
[React] proxy 적용 안됨, localhost:3000에 api가 호출되는 경우가 맞았다? (0) | 2023.08.08 |
[React] ERROR in ./node_modules/body-parser/lib/read.js 19:11-26 등 많은 오류들 문제 해결 (0) | 2023.08.04 |
React window 새로고침(F5) Refresh로 반영,반응 안됨 해결 (0) | 2023.02.09 |
[Setting] visual studio code setting (0) | 2023.02.04 |