본문 바로가기
프로젝트/코드스테이츠 - 4주프로젝트

지도 페이지 미리 작업중: tourAPI와 카카오맵 연동시킴,4주 프로젝트 + 6, 코드스테이츠 +130

by 안뇽! 2021. 11. 28.
반응형

그동안 SR을 하며 시간날때마다 관광지 tourAPI와 카카오맵을 연동하는 방법을 연구했다.

 


카카오맵과 TourAPI를 이용한 지도

클릭한 지점 반경 10km의 관광지들을 표시, 2주프로젝트때 사용했던 검색기능 유지

 

1. 로딩화면

로딩

2. 지도에 클릭들을 해봄

지점 클릭시 반경 10km 관광지 표시, 마커에 mouseover, mouseout 이벤트핸들러 등록, 2주프로젝트때 사용했던 검색기능 유지


설명

1. App.js에서 geolocation함수를 이용하여 사용자 위치 획득, 리덕스로 lon, lat에 좌표저장

좌표를 받아오기 전에 <MapTwo /> 컨테이너를 렌더링하면 아래 화면에서 진행이 되지 않으므로, 좌표획득하기 전까지는 <Loading /> 컨테이너가 렌더링되도록 한다.

 

2. 좌표 반경 10km의 관광지 좌표를 kakaoMap에 전달

pickPoint에는 클릭한 지점의 좌표가 할당되고 초기값은 App.js에서 획득한 사용자의 좌표이다.

tourAPI를 통해 pickPoint반경 10km에 있는 관광지들의 정보를 placeList에 담아 카카오맵으로 전달한다.

const MapTwo = () => {
  
  const {lat,lon,region,city, add} = useSelector((state=>state.locationReducer),shallowEqual)
  const [centerPosition,setCenterPosition] = useState([lat,lon])
  
  //클릭한 좌표중심 업데이트하여 새로운 좌표 중심반경 10km 재검색해야함  
  //클릭하면 그 지점으로 좌표중심 업데이트
  //pickPoint의 초기값은 사용자 위치
  const [pickPoint,setPickPoint] = useState([lat,lon])
  
useEffect(() => {// * 지도의 한 점 클릭시 그 클릭한 점의 좌표 반경 10km의 관광지들의 좌표 전송
   
	axios.get(`http://api.visitkorea.or.kr/openapi/service/rest/KorService/locationBasedList?ServiceKey=${process.env.REACT_APP_TOUR_API_KEY}`,
    {
    params:{
     ...생략
      //! contentTypeId : 12:관광지,14:문화시설,15:행사,25:여행코스,28:레포츠,32:숙박,38:쇼핑,39:식당, 
      contentTypeId:12,
      ...생략
      //*좌표는 위의 pickPoint를 사용한다.
      mapX:pickPoint[1],
      mapY:pickPoint[0],
      }
    }
    ,{'content-type': 'application/json'}).then(res=>{
      let list = (res.data.response.body.items.item)
      list=list.map(el=>{
        return [Number(el.mapy),Number(el.mapx),el.title]        
      })

      setPlaceList(list) // 반경 10km에 있는 관광지들의 정보를 placeList에 저장한다.
      
    })
    .catch(err=>console.log(err))
  // }
},[pickPoint])//pickPoint가 바뀔때마다 실행(지도 클릭시마다)

 

3. 위에서 전달받은 관광지들의 정보를 지도에 표시

위에서 전달받은 placeList에는 관광지들의 이름,좌표가 있다.

placeList안에 들어있는 관광지들의 좌표를 카카오맵에 표시하고, 관광지이름은 infowindow에 표시한다.

infowindow에는 mouseover, mouseout 이벤트핸들러를 등록해준다.

useEffect(()=>{ // * 위의 useEffect에서 받아온 좌표들을 지도에 노란색 마커로 표시

    
    const container = document.getElementById("map") //지도를 담을 영역의 DOM 레퍼런스
    const options = {
      //지도를 생성할 때 필요한 기본 옵션
      center: new kakao.maps.LatLng(pickPoint[0],pickPoint[1]), //지도의 중심좌표를 마커로 변경
      level: 9 //지도의 레벨(확대, 축소 정도)
    }
    const map = new kakao.maps.Map(container, options) //지도 생성 및 객체 리턴

    let markerCenter = new kakao.maps.Marker({ 
      // 지도 중심좌표에 마커를 생성. 이건 내 위치
      position: map.getCenter(),
      map: map,
    });
    // !마커 여러개찍기
    let positions = []
    
    // 반복문을 사용하여 위에서 전달받은 모든 관광지정보들에 마커,info를 달아준다.
    for(let i = 0;i<placeList.length;i++){
      positions.push(
      {   
          content:placeList[i][2],
          latlng: new kakao.maps.LatLng(placeList[i][0], placeList[i][1])
      })
    }
    
    const imageSrc = "https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png"; 
    for (let i = 0; i < positions.length; i ++) {
      
      // 마커 이미지의 이미지 크기 입니다
      const imageSize = new kakao.maps.Size(24, 35); 
      
      // 마커 이미지를 생성합니다    
      const markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize); 
      // console.log(positions[i].latlng)
      // 마커를 생성합니다
      let marker = new kakao.maps.Marker({
          map: map, // 마커를 표시할 지도
          position: positions[i].latlng, 
          image : markerImage // 마커 이미지 : 내 위치랑 구별되게 관광지의 마커는 이미지 추가해준다.
        })// 마커를 표시할 위치
      
      //관광지마커의 infowindow
      // console.log(positions[i])
      let iwContent = `<div style="padding:5px;">${positions[i].content}<br></div>`,
      iwPosition = new kakao.maps.LatLng(positions[i][0],positions[i][1]);
      let infowindow = new kakao.maps.InfoWindow({
        position : iwPosition, 
        content : iwContent,
        // removable : iwRemoveable 
      });
      kakao.maps.event.addListener(marker, 'mouseover', function(){
        infowindow.open(map,marker)
      })
      kakao.maps.event.addListener(marker, 'mouseout', function(){
        infowindow.close();
      })
  
  }
  
  

  //내위치 마커의 infowindow
  let iwContentCenter = '<div style="padding:5px;">내 위치 <br></div>', // 인포윈도우에 표출될 내용으로 HTML 문자열이나 document element가 가능합니다
  iwPositionCenter = new kakao.maps.LatLng(lat,lon); //인포윈도우 표시 위치입니다
  // 인포윈도우를 생성합니다
  let infowindowCenter = new kakao.maps.InfoWindow({
    position : iwPositionCenter, 
    content : iwContentCenter,
    // removable : iwRemoveable 
  });
  // iwRemoveable = true; // removeable 속성을 ture 로 설정하면 인포윈도우를 닫을 수 있는 x버튼이 표시됩니다
        
    // marker.setMap(map);




// 중심좌표 마커에 클릭이벤트를 등록합니다
kakao.maps.event.addListener(markerCenter, 'click', function() {
  // 마커 위에 인포윈도우를 표시합니다
  infowindowCenter.open(map, markerCenter); 
  
});
kakao.maps.event.addListener(map, 'click', function(mouseEvent) {        
    
//* 내위치마커에 infowindow 생성
infowindowCenter.open(map, markerCenter);  
// ? 클릭한 위도, 경도 정보를 가져옵니다 
let latlng = mouseEvent.latLng; 
console.log(latlng.Ma, latlng.La)
setPickPoint([latlng.Ma, latlng.La])
//?  마커 위치를 클릭한 위치로 옮깁니다
markerCenter.setPosition(latlng);

//*?infowindow 마커위에 생성
infowindowCenter.setPosition(latlng)

console.log('도착')

// setCenterPosition([latlng.getLat(),latlng.getLng()])

...생략..

    setMap(map)
    setPending(false)
}, [kakao.maps,placeList,pickPoint])

 


 

 

그리고 배포를 연습삼아 해봤는데, ec2를 하지 않고 리액트 파일만 s3로 올려서 그런지 위치권한 획득이 되질 않는다..

 

그건 후순위로 미뤄두자..

 

 

계속 로딩중인 날씨앱.. 왜 위치권한 획득이 되질 않는걸까.. 

http://toy-weather.s3-website.ap-northeast-2.amazonaws.com/

반응형