250x250
Notice
Recent Posts
Recent Comments
관리 메뉴

탁월함은 어떻게 나오는가?

[네트워크] API 통신: strict-origin-when-cross-origin 대처 방법 및 크롬(Chrome)의 기본 레퍼러 정책 변화에 대해서 본문

[Snow-ball]프로그래밍(컴퓨터)/네트워크

[네트워크] API 통신: strict-origin-when-cross-origin 대처 방법 및 크롬(Chrome)의 기본 레퍼러 정책 변화에 대해서

Snow-ball 2022. 7. 9. 18:24
반응형

프론트 : 리액트, 백 : 노드js 를 사용하고 있다.

 

본인은 공공데이타 포탈에서 api를 테스트 하고 적용을 하고 있었다. 포스트맨(postman)에서 url 을 테스트할 때는 아무런 이상이 없었다. 하지만, 프론트(localhost:3000)에서 백(localhost:8080)으로 axios 데이터 송신을 했더니 안되는 것이였다. 

 

물론, 이전에 이미 proxy를 사용해서 백(localhost:8080)을 허용시켜 놓았음에도 불구하고 말이다. 자세히 봐보니 stict-origin-when-cross-orin 이라는 에러가 발생했다는 것을 알았다.

 

결국 흔한 CORS error임에 어떤식의 에러인지는 알았지만, 많은 미사여구가 붙어있는거 보니 뭔가 다른것이라는 직감을 얻었다. 

 

검색으로 얻은 결과는 결론적으로는 크롬(Chrome)의 기본 레퍼러 정책 변화에 따른것이였다.

3가지로 요약하자면,

1. 크롬은 85 버전 (2020.07 출시)부터 strict-origin-when-cross-origin 정책의 기본값을 enable로 설정하기 시작했다. 이 영향으로 referer의 origin 이 다른 경우, url path, parameter를 수집할 수 없는 경우가 발생한다.

2. 웹사이트에 referer 정책을 meta 태그로 설정해둔 경우, 이와 같은 문제는 발생하지 않는다. 크롬에서는 웹사이트에 referer 정책이 선언되어 있지 않은 경우에만 브라우저의 referer 정책을 따른다.

3. 각 브라우저의 referer 정책 설정은 chrome://flags/#reduced-referrer-granularity 에서 확인할 수 있다.

 

 

 

referer header에는 http 요청이 호출된 origin 이나 웹페이지 url이 담겨있다. 사이트에서 호출하는 request의 referer는 사이트에서 설정한 Referrer-Policy header 정책에 따라 달라진다.

 

브라우저는 웹사이트에 referer 정책이 없는 경우, 브라우저에 설정된 기본 정책을 사용한다. 2020년 중순까지는 브라우저들 사이에서 기본 정책은 no-referrer-when-downgrade 였다. 그러나 많은 브라우저들이 점점 개인 프라이버시를 강화하는 방향으로 기본 정책들을 변경하고 있다. 그렇기 때문에 크롬은 85버전부터 기본 정책이 no-referrer-when-downgrade에서 strict-origin-when-cross-origin으로 변경되었다.

 

그래서 나는 이 방향성이 더욱 강해지고 빨라지면 빨라졌지, 느려지지 않을 것이라는 생각이 들었다.

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

결국은 stict-origin-when-cross-origin은 프라이버시에 대해서 더욱 강력한 조치를 취하기 때문에 생긴것이다.그렇기때문에 cross-origin 요청인 경우에는 referer에 origin 값만 전다한다. 그래서 url path, query string에 포함된 정보의 유출의 가능성을 막아줘버린다.

 

즉 , 위의 사진처럼 https://site-one.example/stuff/detail?tag=red 의 url이 https://site-one.exampl/로 로 보내지게 되는 것이다.

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

검색하면서 찾은 해결 방법

 

- 웹 페이지에 referer 메타 태그를 추가하면, 브라우저 레퍼러 정책을 따르지 않는다.

1
<meta name="referrer" content="no-referrer-when-downgrade" />
cs

 

하지만, 나는 장기적으로 결국 구글을 포함한 여러 회사에서 파라미터 방식을 지양할 것이라는 생각을 지울 수 없었다. 그렇기 때문에 정책이 GET방식보다 POST 방식을 지향하게 만들것이라고 판단해서 다른 고민을 해보았다.

 

내가 생각해낸 결론은 나의 프론트(localhost:3000)와 백(localhost:8080)이 통신하는 데이터 자체를 POST방식으로 공공데이터 API를 사용할때만 GET방식으로 사용하면 좋겠다라는 결론을 내렸다.

 

밑에 코드는 내가 해결한 방안의 일부 코드를 첨부했다.

 

 

 

 

내가 생각해낸 해결 방법

1. 포스트(POST) 방식으로 데이터 통신을 위한 코드

1
2
3
app
  .route("localhost의 url")
  .post();
cs
 
   

 

2. 포스트(POST) 방식으로 받은 데이터를 겟(GET)방식으로 통신하는 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
exports.cityAndProvince = (req, res) => {
 
  const ENCODE_SERVICE_KEY = process.env.PUBLIC_DATA_ENCODE;
  const { sidoCode: sidoCd, startDate: strtYymm, endDate: endYymm } = req.body;
 
  const url = `http://해당url?serviceKey=${ENCODE_SERVICE_KEY}&strtYymm=${strtYymm}&endYymm=${endYymm}&sidoCd=${sidoCd}`;
 
  request({ uri: url, method: "GET" }, (err, response, body) => {
    if (err) {
      console.log(`시도별 수출입실적 조회 ERROR : ${err}`);
      throw err;
    }
    try {
      parseString(body, (err, result) => {
        if (err) {
          console.error(`시도별 수출입실적 조회 parseSring error : ${err}`);
          res.json({
            result: {
              errorMsg: result,
            },
          });
          return;
        }
 
        res.json({
          result: {
            resultMsg: result.response.header[0].resultMsg[0],
            cmtrBlncAmt:
              result.response.body[0].items[0].item[0].cmtrBlncAmt[0], 
            expCnt: result.response.body[0].items[0].item[0].expCnt[0],
            expUsdAmt: result.response.body[0].items[0].item[0].expUsdAmt[0], 
            impCnt: result.response.body[0].items[0].item[0].impCnt[0], 
            impUsdAmt: result.response.body[0].items[0].item[0].impUsdAmt[0], 
            priodTitle: result.response.body[0].items[0].item[0].priodTitle[0],
            cmtrBlncAmt2:
              result.response.body[0].items[0].item[1].cmtrBlncAmt[0], 
            expCnt2: result.response.body[0].items[0].item[1].expCnt[0], 
            expUsdAmt2: result.response.body[0].items[0].item[1].expUsdAmt[0], 
            impCnt2: result.response.body[0].items[0].item[1].impCnt[0],
            impUsdAmt2: result.response.body[0].items[0].item[1].impUsdAmt[0],
            priodTitle2: result.response.body[0].items[0].item[1].priodTitle[0], 
            sidoNm2: result.response.body[0].items[0].item[1].sidoNm[0],
          },
        });
      });
    } catch (err) {
      res.json({
        result: {
          resultMsg: result.response.header[0].resultMsg[0],
        },
      });
      throw new Error("request pasing error : ", err);
    }
  });
};
 
cs

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

결론 : 포스트(POST)방식으로 받아서 다시 겟(GET)방식으로 사용하는 방법에 대한 이야기를 들어본적은 없다. 그렇게 사용할 일이 없어서 그럴 수도 있지만,  더 좋은 방법이 있을 수도 있을 수도, 아니면 생각을 못해본 방법일 수도 있지만, 이방식으로 해결함으로써 프라이버시에 대한 stict-origin-when-cross-origin 에러는 더이상 발생하지 않고 더욱 강력하게 변경된다하더라도 문제가 생기지 않을 것 같다. 하지만, 이 방법에 대해서 좀 더 세련되게 해결할 방법이 있지 않을까? 라는 고민을 해봐야 할 것 같다.

 

그래도 나름대로 새로운 방식으로 해결을 했더니 기분은 좋다.

 

 

 

 

 

 

 

 

 

베타존 : 네이버쇼핑 스마트스토어

나를 꾸미다 - 인테리어소품 베타존

smartstore.naver.com

 

반응형
Comments