211121_개발자 준비하기(50일차) - CORS, Momentum 완성 with Open API

22643 단어 diarydiary

배운 것(끄적끄적)


CORS(교차 출처 리소스 공유)

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 기존의 출처에서 다른 출처로 리소스를 요청할 때 권한을 부여하도록 하는 정책이다.

ex) https://www.naver.com에서 fetch를 사용하여https://google.com 경로 내의 json을 요청하는 경우 등

CORS는 SOP(Same-Origin Policy)라는 동일 출처 정책의 예외 정책이라고 볼 수 있다. SOP은 같은 출처에서만 리소스를 공유할 수 있는 정책인데 웹이라는 환경에서 다른 출처에서 리소스를 가져오는 경우는 흔한 일이라 'CORS 정책을 지킨 리소스 요청' 을 예외적으로 허용해주기로 했다. (TMI: CORS가 2009년, SOP이 2011년으로 CORS가 더 먼저 등장했다.)

동작 방식

  • 단순 요청(Simple requests)
  • Preflight requests

단순요청

다음 조건을 충족한 경우 사용

  • 다음 중 하나의 메서드(GET, HEAD, POST)
  • 유저 에이전트가 자동으로 설정 한 헤더 (예를들어, Connection, User-Agent(en-US), Fetch에 정의된 "forbidden header name", "CORS-safelisted request-header"로 정의한 헤더
  • 다음 중 하나의 Content Type(application/x-www-form-urlencoded, multipart/form-data, text/plain)

Preflight requests

Prefight Request 가장 먼저 HTTP Request 메소드 중 하나인 OPTION 메소드

를 Cross-Origin으로 보내고(Preflight), 응답 받은 헤더 정보를 통해서

메인 요청(실제로 보내야하는 요청)을 보낼 수 있는지 판단하는 방식

이다. Authorization와 같은 유저 정보와 관련된 헤더는 브라우저로 하여금 Preflight Request 방식으로 요청하도록 유도한다.

Todo-List 완성시키기 with OPEN API

현재 날씨까지만 Todo-list에 넣어주면 css를 제외한 기능은 완성이다!

현재 내 위치를 자동으로 불러오기 위해 검색을 통해 navigator.geolocation를 가지고 나의 위도, 경도를 찾아낼 수 있다는 사실을 알아냈다.

const navi = navigator.geolocation.getCurrentPosition(async function (position) {
    let lat = position.coords.latitude;
    let lon = position.coords.longitude;

위에서 얻은 위도와 경도 그리고 이번 주에 배운 fetch를 통해 API 정보를 얻어냈다.


fetch(`api.openweathermap.org/data/2.5/find?lat=${lat}&lon=${lon}&appid=${API_KEY}`)
      .then((respone) => {
        if (response.ok) {
          return reponse.json();
        } else if (response.status === 404) {
          return Promise.reject("error 404");
        } else {
          return Promise.reject("some other error: " + response.status);
        }
      })
      .then((data) => console.log("data is" + data))
      .catch((error) => console.log("error is" + error));
    console.log(`lat = ${lat}, lon = ${lon}`);
  });
}

여기서 console.을 찍어보면 data가 이렇게 나오는데 list안에 있는 배열들의 순서가 아마도 위도와 경도 정확도에 따라 매겨주는 것 같았다. 0번이 내가 사는 안산시와 맞기에 그렇게 추측을 했고, 배열의 [0] index를 가져와

온도와 습도를 가져왔다.

const myCity = weatherObj.list[0];
    const temperVal = myCity.main.temp;
    const humidityVal = myCity.main.humidity;

    temperHumi.textContent = "현재 온도 : " + temperVal + "도 / " + "현재 습도 : " + humidityVal + "%";
  });

잘되나 싶었는데 온도 정보가 이상하게 나온다! 그래서 찾아보니 온도 단위가 Kelvin(?)온도란다. 처음들어본 용어긴한데 찾아보니 절대온로라고 한다.

절대온도(kelvin)는 온도의 SI 단위이다. 켈빈은 절대 온도를 측정하기 때문에, 0 K은 절대 영도(이상 기체의 부피가 0이 되는 온도)이며, 섭씨 0도는 273.15 K에 해당한다. 상대온도의 단위로는 섭씨도와 같다. 켈빈 경의 이름을 땄으며, 기호는 K다. (위키백과, 켈빈)

알고보니 홈페이지에 친절하게 온도에 대해 units을 사용하여 단위를 바꿀 수 있다고 나와있었다!

그래서 바꿔주었더니 짠!! 제대로 나온다~ 이제 남은 건 CSS로 더 이쁘게 꾸미는 일만 남았다!

제곱근 값 구하기 알고리즘

짬내서 못 푼 알고리즘들을 틈틈이 풀다가 제곱근 값을 구하는 알고리즘이 흥미로워 한 번 풀어보기로 했다.

수포자라서 그런지 처음 풀어보려고 시도했을 때는 제곱근 값을 어떻게 구하는 지 도저히 떠오르지가 않아 Reference를 확인 해 보니, 배열로 자리 수만큼의 수를 할당하고 num num < 9 < num + [자릿수] num + [자릿수] 를 반복하면서 해당 수를 구하는 신박한 방법을 알게 되었다.

그렇게 힌트를 얻고나서 스스로 풀어보려고 했을 때 막히는 부분이 존재했다. 참고로 문제에서는 소수점이 있을 경우, 세자리수에서 반올림하여 두자리까지만 구한다.

function computeSquareRoot(num) {

  // 결과값을 할당할 변수를 선언한다.
  // 소수점 세자리까지 더 해줄 숫자가 포함된 배열을 선언한다. (e.g. 1, 0.1, 0.01, 0.001)
  // result * result값을 squre result로 선언하고 할당한다.
  // for문을 만들어주고 arr.length만큼 돈다.
  // for문 안에 result * result가 num보다 작을 동안 while문을 돌면서
  // 만약 result * result 값이 num과 같다면 result을 리턴하고
  // num보다 작으면 result에 arr[i] 값을 더 해준다.
  // num보다 크면 while문을 종료한다.
  // 반복하면서 result의 제곱이 num과 같을 때 result를 리턴한다.

  let result = 0;
  let arr = [1, 0.1, 0.01, 0.001];

// 제곱근인지 알 수 있으려면 result의 제곱이 num과 같아야한다.
    for(let i = 0; i < arr.length; i ++) {

      if(result * result === num) { 
        if(Number.isInteger(result)) {
          return result  
        } else {
        return result.toFixed(2);
        }
      }

      // 2 < 5 < 3
      while(result * (result + arr[i]) < num) { // result의 제곱이 num보다 작을동안 반복하면서
            result = result + arr[i] // result값에 result + arr[i]를 더해준다.
        } 
      }
    return result;
}

위처럼 풀었을 때, 다 풀었다 싶었는데 아차! 소수점 계산이 정확히되질 않았다.

이를 해결하기 위해 이리저리 찾아본 결과,

<해결법>

  1. 반복하여 넣어주는 return에 toFixed를 이용하여 해소하여준다. (자바스크립트 계산오류로 인해 소수점끼리 계산할 경우, 저런식의 오류값처럼 나온다고한다.
  2. .toFixed()는 반환값을 String으로 리턴해주기에, 그 변수를 number형태로 계속 사용하고싶다면 parseFloat으로 인해 return값을 다시 변환해주어야한다.

결과

function computeSquareRoot(num) {

  let result = 0;
  let arr = [1, 0.1, 0.01, 0.001];

    for(let i = 0; i < arr.length; i ++) {

      if(result * result === num) { 
        if(Number.isInteger(result)) {
          return result  
        } else {
        return result.toFixed(2);
        }
      }

    
      while(result * (result + arr[i]) < num) { // result * [] + arr[i]가 num보다 작을동안 반복하면서
        if(i >= 1) {
          const length = arr[i].toString().split(".")[1].length; 
          result = parseFloat((result + arr[i]).toFixed(length)) // result값에 result + arr[i]를 더해준다.
        } else {
          result = result + arr[i]
        } 
      }
    }
    return result;
}

return 할 때 복잡하게 더 해주는 arr[i]의 자릿수만큼 계속 toFixed를 해주느라 코드양이 좀 더 추가되었다.

문제는 제대로 풀어졌지만, 레퍼런스 코드는 훨씬 더 적은 양의 코딩으로도 문제를 해결하더라! 그래도 하나하나 차근히 풀어봤다는 것에 나에게 박수를..!

Reference

느낀점


수업하면서 배웠던 내용을 주말을 활용해 실습을 통해 복습하면서 API를 구체적으로 어떻게 활용하는 지 알게되었다. 이런저런 핑계로 주말에 복습하는 걸 미루고 있었는데 그럴수록 복습해야할 것들이 계속 쌓이는 게 내심 불편했었다. 이번에 복습함으로서 내용들을 다시 이해한 것도 좋지만 그러한 마음 속의 짐을 스스로 조금 덜 수 있어서 더욱 좋은 시간이 되었던 것 같다. 이번 일을 계기로 주말에 일정한 시간은 복습하는 시간으로 할당하는데 박차를 가할 수 있을 것 같다.

좋은 웹페이지 즐겨찾기