성장과정(dev)/Frontend(feat. Vue, Next.js)

[ react ] Axios 호출, Proxy를 이용하여 크로스브라우징 문제(CORS 이슈) 해결하기

lowellSunny 2020. 11. 6. 17:41

* npm 라이브러리 설치

$ npm install axios --save

 

* server와 client port번호 분리 ( server는 5000, client는 3000번 )

server쪽 index.js에서 listener에 포트번호설정

const port = 5000           //포트번호

...


// api 추가
app.get('/api/hello', (req, res) => {
    res.send("안녕하세요 !")
})



app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
})

 

* frontend에서 server 호출

- axios를 호출하는 컴포넌트 전체소스

import React, {useEffect} from 'react'
import axios from 'axios'

function LandingPage () {

    useEffect( () => {
        axios.get( 'http://localhost:5000/api/hello' )
            .then( response => console.log ( response.data ) )
    }, [] )

    return (
        <div>
            LandingPage

        </div>

    )
}

export default LandingPage

* 위와같이 호출 시 같은 서버에서 호출하는 것이 아니므로 에러발생

 

* 에러원인

CORS( Cross-Origin Resource Sharing ) policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

> 각 서버를 origin이라고 명시

 

* 해결방안 4가지

1. 개발자도구 이용

2. JSONP 라는 방식으로 모든 request를 get으로 변경하여 요청을 보냄

3. 서버에서 해당 client의 요청을 허용한다는 정의 & Client에서 허가를 받기위한 특정 파라미터를 보낸다

4. Proxy 사용

 

 

* 4번방법 Proxy를 사용하여 크로스브라우징 문제 해결하기

참고) create-react-app.dev/docs/proxying-api-requests-in-development/

1. $ npm install http-proxy-middleware --save

2. 참고문서대로 내용입력

 - front 경로의 src 아래에 setupProxy.js 파일생성

 - 접근하려는 서버 포트에 대해 proxy 정의( 예제는 node 서버가 5000번 )

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
    app.use(
        '/api',
        createProxyMiddleware({
            target: 'http://localhost:5000',
            changeOrigin: true,
        })
    );
};

4. 노드서버를 호출하는 곳에서 axios.get( 'http://locathost:5000/api/hello' )라고 정의되어있던 부분을 axios.get( '/api/hello' ) 로 변경

5. npm run start

6. 성공!

 

* location.href 사용법

기존에 자바스크립트에서 location.href = "/login";

이렇게 사용했다면

react에서는 props.history.push( "/login" )

ex) 로그아웃 시

function LandingPage ( props ) {

    useEffect( () => {
        axios.get( '/api/hello' )
            .then( response => console.log ( response.data ) )
    }, [] )

    const onClickHandler = () => {
        axios.get("/api/users/logout" )
            .then( response => {
                if( response.data.success ) {
                    props.history.push( "login" )
                }
                else {
                    alert( '로그아웃에 실패하였습니다.' )
                }
            })
    }

    return (
        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center',
        width: '100%', height: '100vh'}}>
            <h2>시작 페이지</h2>

            <button onClick={onClickHandler}>로그아웃</button>
        </div>


    )
}

 

 

 

 

 

 

프록시 관련 추가설명 =======================================================

 

* Proxy란?

유저와 인터넷 사이의 중계서버

 

* 사용자와 인터넷 사이에서 proxy server의 역할?

 - 요청을 하는 사용자의 ip를 proxy에서 변경할 수 있으므로 인터넷에서 접근하는 사람의 ip를 모르게 한다.

 - 방화벽 기능

 - 필터기능

 - 프록시서버의 자체저장공간(캐시, 공유데이터)이 존재하기 때문에 인터넷까지 가지 않아도 static같은 데이터를 가져올 수 있다.

 

* 사용이유?

- 사용자에 대한 인터넷 사용제어

- 캐쉬를 이용하여 빠른 인터넷 이용 제공

- 보안 제공 (ip관련)