그룹 프로젝트를 오랜만에 실행해 봤는데 `https://countryflagsapi.com/png/brazil` 을 불러오는 중에 에러가 발생했다.
나라의 국기 사진을 api로 불러올 수 있는 사이트이다.
아마도 cors 오류라고 생각이 들었지만 혹시 다른 api로는 될까 싶어서 이번엔 비슷한 사이트인 이곳에서 해보려고 했지만 여기는 나라코드로 분류하기 때문에 내 프로젝트에서 사용하려면 복잡해질 것 같아서 지금 상황에서 해결해야 했다.
CORS?
Cross Origin Resource Sharing, 교차 출처 리소스 공유
http 헤더 기반 메커니즘으로 한 출처에서 실행 중인 웹 어플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. CORS 에러는 브라우저가 내뿜는 것이다.
(보안 상의 이유로, 브라우저는 교차 출처 http 요청을 제한한다. 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 한다.)
참고: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Origin
Origin은 프로토콜(http, https,,), 호스트 이름(www와 같이 기기끼리의 통신 시 각 기기가 서로를 식별하도록 할당한 이름) 및 포트의 조합이다.
같은 origin이라면 same-origin(동일 출처), 다른 origin이라면 cross-origin(교차 출처)이다.
예를 들어 URL이 https://www.example.com:443/foo 인 경우 origin은 https://www.example.com:443 이고 same-origin이고 포트가 생략되어도 상관 없다.
cross-origin은 origin이 정확히 맞아떨어져야 하며 그 외는 모두 cross-origin이다.
- 도메인이 다르거나
- 하위 도메인이 다르거나
- 다른 프로토콜이거나
- 다른 포트 번호이거나
SOP와 CORS의 관계
SOP는 동일 출처 정책이고, CORS는 교차 출처 자원 공유다.
SOP는 다른 origin으로 요청을 보낼 수 없도록 금지하는 브라우저의 기본적인 보안 정책이다. 즉, 동일한 origin으로만 요청을 보낼 수 있도록 하는 것이다. 그러나 몇가지 예외 사항에서는 다른 origin으로 요청을 보내야 하는데 그 때 지켜야 하는 정책이 CORS인 것이다. 원래대로라면 SOP에 의해 막히게 될 요청을 풀어주는 정책이라고 할 수 있다.
여기서 몇 가지 예외 사항이란,
1. <script>태그로 javacript를 실행하는 경우,
2. 이미지를 렌더링하는 경우,
3. <link>태그로 스타일 시트 파일을 불러오는 경우,
4. HTML 문서를 화면에 보여주는 경우를 말한다.
출처: https://www.rfc-editor.org/rfc/rfc6454#section-3.4.2
CORS 해결하기
CORS의 기본적인 동작원리는 단순하다. 브라우저는 다른 origin으로 요청을 보낼 때 origin 헤더에 자신의 origin을 설정하고, 서버로부터 응답을 받으면 Access-Control-Allow-Origin 헤더에 설정된 origin 목록에 요청의 origin 헤더 값이 포함되는 지 검사하는 것 뿐이다. 즉, 응답의Access-Control-Allow-Origin 헤더에 허용되는 origin 또는 *을 설정해주면 된다.
하지만 이 방법은 server에서 해결하는 방법이고 만약 server를 수정할 수 없거나 외부 api를 사용하는 경우엔 클라이언트에서 처리를 해주어야 하는데, 그 방법 중 하나가 프록시 서버를 이용하는 것이었다.
프록시 서버란 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 서버를 가리킨다. 즉 프론트에서 프록시 서버를 거쳐서 출처를 response와 같게 수정하고, server에 접근하도록 하는 것이다. (나중에 강의를 통해서 더 이해하고 싶다.)
React에서 proxy server를 구축하는 방법으로 http-proxy-middleware를 사용했다. 하지만 배포할 땐 적용이 안 되고, 개발할 때만 적용이 된다..
먼저 http-proxy-middleware를 설치한다.
yarn add --dev http-proxy-middleware
setupProxy.js를 src 밑에 세팅한다.
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/png", {
target: "https://countryflagsapi.com",
changeOrigin: true,
}),
);
};
- createProxyMiddleware("/png", {})의 "/png"는 "/png"로 시작하는 endpoint를 가진 api와 모두 매칭시킨다
- target에는 url의 endpoint를 제외한 출처만 명시한다. https://countryflagsapi.com/png/brazil의 경우, endpoint를 제외한 /png를 제외한 https://countryflagsapi.com로 명시한다.
- changeOrigin는 호스트 헤더의 출처를 대상 URL로 변경 하는지 여부입니다. CORS 처리를 위해 출처를 수정해주어야 합니다. 기본값은 false이다.
**endpoint ?
API란 두 시스템, 어플리케이션이 상호작용할 수 있게 하는 프로토콜의 총 집합이라면, endpoint는 API가 서버에서 리소스에 접근할 수 있도록 가능하게 하는 URL이다. 일종의 진입점이다.
api 호출하는 파일
url의 endpoint인 "/png/~"로 호출합니다. proxt를 세팅하면 서버를 재시작해준다.
<ListItemAvatar>
<Avatar
alt="국기"
src={`/png/${data?.country}`}
/>
</ListItemAvatar>
결과
나라 국기 이미지가 잘 출력됨을 알 수 있다.
항상 cors 에러,,cors 에러,, 많이 들어보았지만 이렇게 맞닥뜨린 건 처음같다. 옛날에 공부해 본 적은 있는데 이렇게 실전에서 해결..?하고 나니까 좀 더 이해가 된 느낌이다. 나중에 다시 만나도 반갑게 해결할 수 있겠지?
참고 사이트:
https://www.datoybi.com/http-proxy-middleware/
https://xiubindev.tistory.com/115
'프로젝트 > 엘리스 2차' 카테고리의 다른 글
useEffect called twice in Strict Mode? (0) | 2022.05.19 |
---|