front-end/react

[React] CRA + Typescript Proxy 구축

hojung 2022. 6. 22.
728x90
반응형

1. Proxy란?

프록시란 대리라는 의미로 네트워크 기술에서 대리 응답을 해주는 개념이다. 

보안 상이 문제로 직접 통신을 주고 받을 수 업는 사이에서 프록시를 이용해서 중계를 해준다. 

 

그렇다면 proxy는 왜 사용하는 것일까?

  • 캐쉬를 이용해 더 빠른 통신을 가능하게 한다. 
  • 차단된 사이트를 IP우회하여 접속이 가능하게 한다. 
  • 보안 문제를 해결해준다. 
  • 개발을 하면서 발생하는 CORS(Cross-Origin Resource Sharing)문제를 해결할 수 있다.

2. CORS(Cross Origin Resource Sharing)

일반적으로 브라우저에서는 보안 문제로 인해 동일 출처 정책을 따른다. 두 URL의 프로토콜, 호스트, 포트가 모두 같아야 동일한 출처로 볼 수 있는데 이 경우에서는 

express.js로 만든 서버와 cra+typescript 로 만든 리액트 app을 통신시키기 위해 필요하다. 

 

앞서 두 URL의 포트 번호까지 같아야 동일한 출처로 인정한다고 하는데 express와 react는 각각 다른 port에서 열리므로 동일한 출처로 볼 수 없다. 나는 react application은 3000번 포트 express app은 5000번 포트에서 열리도록 설정해주었다. 

이러한 이유로 두 어플리케이션 간의 통신은 CORS정책을 만족하지 못한다. 

 

이러한 CORS정책 위반 문제를 해결하려면 백엔드 서비스 쪽에서 응답 헤더에 필요한 값들을 담아서 전달해주어야 한다. 

만약 서버로 부터 적절한 응답 헤더를 받지 못한다면 브라우저에서 CORS를 위반했다는 에러 메시지가 출력된다. 

 

따라서 CRA에서는 쉽게 proxy설정을 해줄 수 있다. 


3. http-proxy-middleware

처음에 이 문제를 해결하려고 했을 때  http-proxy-middleware라이브러리를 통해 해결하려고 했었다. 

하지만 ES6문제와 타입스크립트에서 호환이 잘 되지 않는 문제로 인해 다른 방법을 찾았다. 


4. package.json수정

CRA를 통해 React app을 만든 경우에 굉장히 쉬웠다. 

 

다음과 같이 package.json에 다음과 같이 "proxy": 속성을 추가해주면 된다. 나는 express앱을 localhost5000번을 통해 열 것이므로 다음과 같은 설정을 추가해주었다. 

{
	///...////
    ///.....
    
    "proxy": "http://localhost:5000/
    ///....
    ///...
}

5. Axios 를 이용한 테스트

이제 두개의 다른 포트가 잘 통신을 하는지 테스트를 해 볼 것이다.

1. 클라이언트

npm i axios --save

다음과 같이 axios를 설치하고 import를 해준다. 

axios요청을 보내는 다음과 같은 코드를 작성하였다. 나는 useEffect훅 안에 코드를 작성해서 페이지가 처음 로드 될 때만 axios요청을 보내는 방향으로 하였다. post요청을 보냈고 /api/test주소로 보냈다. 이렇게 하면 아까 package.json에 proxy설정을 해주었기 때문에 리액트 app을 서버와 다른 포트에서 열었지만 잘 통신을 할 것이다. 

 

그리고 요청이 성공했다면 alert창으로 요청 성공이라고 띄울 것이고 실패했다면 요청 실패라는 문장을 보여줄 것이다. 

 

2. 서버

express로 만든 서버에서는 다음과 같이 /api/test라는 url로 post요청이 들어오면

success라는 속성을 true로 만들어서 보낼 것이다.  

 

3. 결과

 

다음과 같이 react 어플리케이션에서 /api/test로 요청을 보내자 요청 성공이라는 alert창이 뜨는 것을 확인할 수 있었다. 

 

네트워크 탭을 살펴보면 다음과 같은 결과가 나온다. Express에서 온 응답이라는 정보와 정책에서 Cross-origin을 따르고 있는 정보또한 확인할 수 있다. 

또한 응답에는 아까 보내주었던 Success:true라는 json 객체가 들어있는 것을 확인할 수 있었다.

728x90
반응형

댓글