본문 바로가기

Issue

Google Map API을 다루다 생긴 문제들(geolocation, CORS에러)

전역 후 일단 개인적인 공부도하고~ 알바도하고~ 다 해보는 와중..
고등학생 때부터 종종했었던 외주를 다시 시작하며 다시 웹사이트를 만들게되었다.

 

간단한 웹 개발을 도와드리는 외주를 맡게 되었다.
그 과정에서 "Map API"의 사용을 돕게 되었는데,,

1) 첫번째 이슈

 - 어떤 종류의 Map API를 사용해야할까 ?
구글 Maps API, 카카오맵 API, 네이버지도 API와 같은 여러 API가 존재했는데, API를 이용해 주변 음식점들에 대한 검색과 정보들을 가져와야 했기에 구글 Maps API는 제외하고, 카카오맵 API를 원하셔서 카카오맵 API로 도와드리게되었다.


카카오맵은 도메인을 입력하여 해당 도메인에서만 사용할 수 있는 특정 Key값을 받아서 사용해야하기 때문에, 일단 간단하게 페이지를 만들어 카카오맵이 보여지는지 확인하기위해 호스팅을 진행한뒤 카카오맵을 페이지에 띄워봤다.

스포가 있지만 결국 Google Maps API로 진행하게 되었고 완성된 사이트에 같은 이슈로 임의로 에러를 띄워봤습니다.

사진에서 주목해야될 부분은 저 주의 요함이라고 적혀있는 부분이다.
ssl 인증서를 사용하지 않고 호스팅을 해두었다보니, HTTP를 사용해 접속하게 되어 주의요함 이라는 경고 문구가 뜨게 되었다.


페이지의 코드는 JavaScript의 Geolocation API를 이용해 사용자의 위도와 경도값을 가져온 뒤 사용자의 현위치에 해당하는 지도를 띄우는게 목적이었는데, 보안적인 문제로 인해 HTTP환경에서 크롬50버전부터는 Geolocation API를 사용하지 못하게 해두었다는 것이다.

여기서 잠깐
왜 HTTP환경에서는 보안적인 문제점이 있나요 ?

 - HTTP는 Hypertext Transfer Protocol의 약자로 HTML을 전송하기 위한 통신규약을 의미한다.
 - HTTPS에서 S는 Over Secure Socket Layer의 약자이다. 한마디로 보안을 강화한 HTTP. 라고 이해하면 편하다.
일반적으로 HTTP는 암호화되지 않은 방법으로 데이터를 전송하기 때문에 서버와 클라이언트가 주고 받는 메시지가 쉽게 노출될 수 있다.
로그인을 하거나 사용자가 결제를 진행할 때 서버로 비밀번호를 전송하면 그 정보가 쉽게 노출될 수 있다는 것이다. 그 과정을 보안한 것이 HTTPS다.

때문에 기존 임시로 해둔 호스팅 환경에서 SSL인증서를 발급받아야 했는데.. 뭐 이래저래 복잡하셨는지
결론은 외주를 맡기신분께서 Google Maps API를 이용하여 로컬에서 작업을 진행하는걸로 했다.

2) 두번째 이슈

 - CORS 에러
Google Maps API를 이용하여 나름 순조롭게 진행이 되는 것 같았다.
Geolocation API로 사용자의 현위치를 지도에 띄워주는 작업, 반경범위를 설정하여 해당 지도 근처의 음식점을 찾아 구글지도에 마커로 위치를 표시해주는 작업까지.
마지막으로 Google의 Places API를 이용해 주변 음식점들에 해당하는 정보들을 불러와 페이지에 표시해주는 작업만 남겨두고 있었다.

Javascript의 Ajax기능을 이용해 해당 데이터들을 JSON형태로 가져와 출력을 시켜보았는데..

주변 음식점 추천에 해당하는 부분에 list형식으로 주변음식점들의 데이터를 출력하려 하였지만 내용이 텅텅 비어있는 모습이다. (아래는 구글지도)

 

처음엔 JavaScript의 innerText를 사용해 데이터를 넣어두었던 부분이 문제가 있는줄 알았지만, Ajax를 이용해 가져온 데이터를 콘솔로그에 찍어보니 아무것도 나오지 않았다.
그때서야 크롬 콘솔로그를 확인해보니

에러코드를 확인해보면 blocked by CORS policy..? No 'Access-Control-Allow-Origin'..? 라고 적힌 에러가 있음을 알 수 있었다.

주변음식점들의 대한 정보가 나오지 않는 이유는 에러로 애초에 Places API를 이용해 데이터를 가져오지도 못했다는 사실을 깨달았다.
음... 일단 이래저래 여러 삽질들을 해봤는데, 결론은 단순히 CORS 정책을 위반하여 에러가 난다. 라는 결론에 도달했다.

 

그리하여 알아본 CORS 정책이란 뭔가하니..

CORS에대한 설명과 이미지 자료는 모두 https://developer.mozilla.org/ko/docs/Web/HTTP/CORS 에서 참고하였습니다!

CORS는 Corss-Origin Resource Sharing의 약자로 추가 HTTP 헤더를 사용하여, 서로 다른 출처에 대한 한정된 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제라고 합니다. 이때 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행하게 되는데, 보안상의 이유로 브라우저는 스크립트에서 시작한 교차 출처 HTTP 요청을 제한한다고 합니다.
(예를들어, Javascript의 XMLHttprequest와 같은 것들에 대해 제한한다고 합니다)

즉, 이 API를 사용하는 웹 애플리케이션은 자신의 출처와 동일한 리소스만 불러올 수 있으며, 다른 출처의 리소르르 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 한다고 합니다.

 


이렇게 CORS에 대해서 알게되어 이 상황을 해결할 방법에 대해 생각했습니다.

1. HTTP 응답 헤더인 Access-Control-Allow-Origin를 설정하기
-> 구글의 Places API에서 제공하는 API를 사용하고 있기때문에 내가 서버를 제어할 수 없었다.

2. 내가 서버를 구축하여 클라이언트->서버 요청이 아닌, 서버->서버 요청으로 헤더를 추가해 CORS정책을 적용되지 않게해보자.
( 설명에 따르면 CORS는 브라우저의 스크립트에서 시작된 통신에 제한을 하는 것 이므로 서버 간 통신에는 적용되지 않는다는 것을 알 수 있다. )
-> 시간이 부족하여 서버구축을 하여 작업을 도와드릴 수 없었고, 당장의 로컬환경에서 해결할 방법을 찾아야 했다.

=> 그래서 방법을 쭉 찾다보니, 프록시 서버를 이용하는 방법을 알아보게 되었습니다.
프록시 서버를 이용하면, 클라이언트-프록시서버-API서버 의 방식으로 프록시서버의 중계를 통해 통신을 하게되는데. 나는 https://cors-anywhere.herokuapp.com/corsdemo 라는 프록시 서버를 사용했다.
이 서버를 사용하면 HTTP 응답 헤더에 Access-Control-Allow-Origin을 설정해 응답해주기 때문에 CORS 에러를 해결할 수 있다.

 

function search_restaurant() {
      var xhr = new XMLHttpRequest();
      xhr.open(
    	'GET',
    	`https://cors-anywhere.herokuapp.com/https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat}%2C${lng}&radius=1500&type=restaurant&key=API_KEY`,
    	 true);
      xhr.send();

      xhr.onload = () => {
          if (xhr.status == 200) {
            const restaurant_data = JSON.parse(xhr.response);
        ..생략..

외부 프록시 서버의 사용 방법은 해당 링크에 접속해 임시 엑세스를 요청한 뒤 요청해야하는 API의 주소 앞에 프록시 서버 URL을 붙여 통신을 요청하면 된다!

 

 

마지막으로 주변음식점의 데이터가 출력된 화면이다!

데이터중 랜덤 3개의 값에 해당하는 음식점의 이름과 주소를 가져와 출력해주는 모습이다!

 

 

3) 마무리하며..

요청한 작업의 기간이 짧아 시간이 많이 없고 php를 이용해 작업하다보니 얼렁뚱땅 넘어간 느낌이 있지만!
앞으로 React를 사용해 Google Map 출력과 직접 서버를 구축해 작업해보기도 하겠다!!