CORS Access-Control-Allow-Origin 해결

Lee InnJie·2022년 6월 12일
0

목록 보기
5/8

스프링과 리액트를 사용하여 진행할 때 발생한 문제이다.
스프링의 Rest API를 사용하다 보면 실제 실행 시 에러가 발생한다.
이는 스프링과 리액트의 포트, 호스트, 프로토콜이 같아야 Same-Origin-Policy 정책을 만족시키는데 실제로 다르기 때문에 서버에서 CORS를 이용한다.

CORS란?

CORS (Cross-Origin Resource Sharing) 정책
교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다.

출처 구분

프로토콜(Scheme), 포트, 호스트 3가지가 같으면 같은 출처로 구분한다.

동작 방식

  1. 웹 클라이언트 애플리케이션이 리소스를 요청할 때 HTTP 프로토콜을 사용하여 요청하며, 헤더의 origin 필드에 요청을 보내는 리소스를 보낸다.

  2. 서버는 요청 응답에 대해 Access-Control-Allow-Origin 값에 접근 허용 리소스를 전달한다.

  3. 브라우저는 요청을 보낸 리소스와 응답을 받은 값을 비교하여 유효성을 확인한다.


Spring과 React의 통신 구현

  1. Spring과 React 프로젝트 생성
  2. React - proxy-middleware와 axios 설치
    npm install http-proxy-middleware --save
    npm install axios --save
  3. 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");
    }
}
  1. React - proxy.js 작성
const {createProxyMiddleware} = require('http-proxy-middleware');

module.exports = function (app) {
    app.use(
        '/',
        createProxyMiddleware({
            target: 'http://localhost:8080',
            changeOrigin: true,
        })
    );
};
  1. 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!";
    }
}
  1. 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;
  1. 실행 결과 확인
profile
⌒_⌒

0개의 댓글