개인 프로젝트/예약 시스템 개발하기

예약 시스템 개발하기 03. axios 통신과 CORS 정책

going.yoon 2022. 2. 2. 12:46

화면단과 서버간의 통신을 위하여 axios 통신을 구현해 보았다.

 

먼저 아래의 명령어를 통해 axios 라이브러리를 설치해준다.

$vue add axios

 

Main.js에 다음과 같이 axios 설정을 해준다.

 

import Vue from 'vue'
import './plugins/axios' //####이부분
import App from './App.vue' //####이부분
import router from './router'
import vuetify from './plugins/vuetify'
//import axios from 'axios'

Vue.prototype.$http = axios //####이부분


new Vue({
    el: '#app',
    router,
    vuetify,
    axios, //####이부분
    render: h => h(App)
})

 

해당 라이브러리를 설치하고 나면 plugins 디렉토리 아래에 axios.js라는 환경설정 파일이 생성되는데,

config 부분에 다음과 같이 내용을 추가해주었다.

baseURL은 api 통신을 할 백엔드 서버의 URL을 적어주면 된다.

let config = {
  baseURL : 'http://localhost:44000',
  headers: {
    post : {
      'Access-Control-Allow-Origin': '*',
      'Content-Type': 'application/json;charset=utf-8'
    }
  },
  axios : axios
};

 

그리고 뷰 파일에서 axios 통신이 필요한 메소드를 다음과 같이 적어주면 되는데,

baseURL을 http://localhost:44000 으로, url을 '/api/meta/get'으로 설정해주었으니

 http://localhost:44000/api/meta/get으로 요청 url이 생성되어 날라갈 것이다.

methods : {
        getMetaItems : function () {
            this.axios.post('/api/meta/get')
            .then(res=>{
                console.log(res);
                alert(res)
            }).catch(err=>{
                console.log(err);
            });
        }
    }

 

번외의 이야기지만 api에서 구현된 리스트를 보기 위해서 swagger를 사용했다. swagger는 Rest API에서 사용하는 오픈소스 프레임워크로, 쉽게 말하자면 프로젝트에서 사용하는 URL을 화면에서 볼 수 있게해주는 프레임워크이다.

 

localhost:44000/swagger-ui.html에 접속하면 controller 의 리스트들이 보이고 내가 사용하고자 하는 meta-controller를 클릭해보면 , 각각의 HTML method 별 url 을 조회할 수 있다.

 

swagger 에서 조회되는 url이 /meta/get이어도 화면에서 호출하는 url이 /api/meta/get인 이유는 application.yml 설정파일에서

context-path를 /api로 설정해주었기 때문이다.

server:
  port: 44000
  forward-headers-strategy: native
  servlet:
    context-path: /api

 

 

이러한 과정들을 거치고 화면에서 axios 비동기 통신 함수를 호출해주었다.

그리고 이러한 오류가 발생했다.

 

Access to XMLHttpRequest at 'http://localhost:44000/api/meta/get' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

 

 

개발하는 프로젝트의 구조는 아래처럼 프론트엔드와 백엔드의 서버를 분리하여 설계되었고, 로컬 환경에서는 포트를 다르게 사용하고 있었다. 저 위의 에러는 쉽게 말해서 포트 번호가 다르기 때문에 CORS 정책에 위반된다는 소리였다.

 

 

  *****프론트 엔드 서버******                                                                       ******* 백엔드 서버 ***********

  **     localhost:8100    ****             <------ axios 통신 --------->         ** localhost:44000   ********

  **************************                                                                       ******************************

 

 

 

어렵게 말해서는 CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유) 정책이란, 

서로 다른 자원에서 HTTP 통신을 할 때, 자원의 출처를 Header 값에 넣어주어 자신의 출처를 공유하는 정책을 말한다.

그리고 이 CORS에서는 XMLHttpRequest와 Fetch API 통신에 대해서 다른 출신의 자원들의 통신을 규제하고 있다.

그리고 Origin을 구성하는 scheme(protocol), host(domain), port 중 하나라도 다르면 다른 자원이라고 정의한다. 

 

 

https://          gocandoit.tistory.com            :8080

-----------              ----------------------------------                ----------

 scheme                      host(domain)                                   port

 

 

 

CORS 에 대한 자세한 설명은 여길 읽어보면 자세하게 설명되어있다.

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

 

교차 출처 리소스 공유 (CORS) - HTTP | MDN

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라

developer.mozilla.org

 

https://evan-moon.github.io/2020/05/21/about-cors/

 

CORS는 왜 이렇게 우리를 힘들게 하는걸까?

이번 포스팅에서는 웹 개발자라면 한번쯤은 얻어맞아 봤을 법한 정책에 대한 이야기를 해보려고 한다. 사실 웹 개발을 하다보면 CORS 정책 위반으로 인해 에러가 발생하는 상황은 굉장히 흔해서

evan-moon.github.io

 

 

해결방법

: axios.js 에서 Header에 OPTION으로 백엔드 서버의 url을 넣어준다.

let config = {
  OPTIONS : 'http://localhost:44000', ###이부분
  headers: {
    'Access-Control-Allow-Origin': '*',
    post : {
      'Content-Type': 'application/json;charset=utf-8'
    }
  },
  axios : axios
};

 

또 이 부분을 수정하고 난 뒤, proxy error가 났었는데 그 부분은 vue.config.js파일 내 proxy 부분을 변경해주면 된다.

            "/api": {
                target: "http://localhost:44000", ###이부분
                ws: true,
                changeOrigin: true
            },

 

 

통신 완료 후 console.log로 찍은 response 값이 잘 출력되었다.