본문 바로가기
Dev/JavaScript

카카오맵 api 좌표와 마커 이동(수정)하기

by vellahw 2023. 3. 22.

 

https://tavi.tistory.com/110

 

다음 우편번호 api와 카카오 맵 api 사용기

프로젝트를 마무리 하고 쫌쫌따리 추가구현 중인 것들이 있는데 그중 하나인 카카오 map api '모임'이 주제인 프로젝트인만큼 모임 장소를 지도로 표시해주는게 좋을 것 같아 시작하게 되었다. 모

tavi.tistory.com

 

저번 글의 카카오 맵 api를 사용한 후 수정폼에서 다음 우편번호 api를 이용해서 주소 검색 시 검색 된 주소로 지도의 좌표와 마커가 이동되도록 구현 했다. 이동은 아니고 새로 map을 만들어서 새로 좌표를 찍어주고 새로 마커를 찍어준 거긴 하다 ㅎ..


 

 

1. DB에 저장 시킨 주소 지도 띄우기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<tr>
    <th class="header"><label for="ADDRESS" >모임 장소</label></th>
    <td class="contents">
        <input type="text" class="form-control" id="ADDRESS" readonly="readonly" name="ADDRESS" value="${modify.ADDRESS}">
        <button type="button" class="searchMap"
                        onclick="kaMap()">주소 검색</button>
        <br/>           
        <input type="text" id="DEADDRESS" placeholder="상세주소 입력" name="DEADDRESS" value="${modify.DEADDRESS}">
        <div id="map" style="width:500px; height:400px; margin-top: 10px;"></div>
        <input type="hidden" name="WII" value="${modify.WII}" id="WII"> 
         <input type="hidden" name="KYUNG" value="${modify.KYUNG}" id="KYUNG"> 
         <input type="hidden" name="MAP_IDX" value="${modify.MAP_IDX}"> 
    </td>
</tr> 
cs

 

다음 우편번호 api를 이용해 검색 완료된 주소와 사용자가 직접 입력한 상세주소, 카카오맵 api를 이용해 생성된 위도, 경도를 DB에 저장 시켜놨고 위 코드에서 보이듯 각각의 value는 수정 폼 페이지에 저장 되어 있다.

각각의 value를 스크립트에서 변수에 담아 사용 했다.

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
var latitude = document.getElementById("WII").value;
var logitude = document.getElementById("KYUNG").value; //경도
var address = document.getElementById("ADDRESS").value; //주소
var detatil_address = document.getElementById("DEADDRESS").value; //상세주소
 
//지도 없을 때     
if(wii == undefined || wii == null) {
    document.getElementById("map").style.display = 'none';
}
    
if(wii != null){
    var container = document.getElementById('map');
    var options = { //지도를 생성할 때 필요한 기본 옵션
        center: new kakao.maps.LatLng(latitude, logitude),
        level: 3 //지도의 레벨(확대, 축소 정도)
    };
 
    var map = new kakao.maps.Map(container, options); 
 
    var markerPosition  = new kakao.maps.LatLng(latitude, logitude); 
 
    var marker = new kakao.maps.Marker({
          position: markerPosition
    });
        
    marker.setMap(map);
        
    /*====== undefined 공백으로 바꿔주기====== */
    function defaultCheckString (checkStr, defaultStr){
        if(checkStr == undefined || checkStr == null){
            return defaultStr;
        }
        return checkStr;
    }
    
    var infowindow = new kakao.maps.InfoWindow({
        content'<div style="width:150px;text-align:center;padding:6px 0;">'+address+'<br>'+defaultCheckString(deteail_address, '')+'</div>'
    });
    
    infowindow.open(map, marker);
}
cs

 

주소와 상세주소는 infowindow 사용을 위해서 변수로 선언해준 것이다.

중간에 있는 defaultCheckString() 함수는 사용자가 상세주소를 입력하지 않았을 시 화면에서 undefined로 떴기 때문에 공백으로 처리해준 것이다!

DB에 저장된 map이 없을 경우엔 지도를 띄우지 않게끔 저장된 위도 변수를 이용해 조건문으로 스크립트를 나누어 작성 했다.

띄우기 완!

등록폼에서 썼던 스크립트 그대로 가져와서 위도, 경도만 저장해주고 (infowindow 쓸거면 주소까지) 활용하면 되는거라 지도 띄우기는 아주 간단쓰~

 

2. 다음 우편번호 api로 검색된 주소로 좌표와 마커 이동

이거도 등록폼에서 썼던 스크립트 그대로 가져와서 조금만 수정 해주면 된다.

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* 다음 주소검색 및 마커 표시 */
var geocoder = new kakao.maps.services.Geocoder();
 
/* 주소 검색 onclick */
function kaMap() {
   var width = 500//팝업의 너비
   var height = 600//팝업의 높이
   new daum.Postcode({
       width: width, 
       height: height,
   
       oncomplete: function(data) {
           var addr = ''// 주소 변수
           var extraAddr = ''// 참고항목 변수
           //사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
           if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
               addr = data.roadAddress;
           } else { // 사용자가 지번 주소를 선택했을 경우(J)
               addr = data.jibunAddress;
           }
           // 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
           if(data.userSelectedType === 'R'){
               // 법정동명이 있을 경우 추가한다. (법정리는 제외)
               // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
               if(data.bname !== '' && /[동||가]$/g.test(data.bname)){
                   extraAddr += data.bname;
               }
               // 건물명이 있고, 공동주택일 경우 추가한다.
               if(data.buildingName !== '' && data.apartment === 'Y'){
                   extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
               }
               // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
               if(extraAddr !== ''){
                   extraAddr = ' (' + extraAddr + ')';
               }
               // 조합된 참고항목을 해당 필드에 넣음
           
           } else {
           }
           
           // 우편번호와 주소 정보를 해당 필드에 넣음
           document.getElementById("ADDRESS").value = addr;
           //상세주소 입력 폼으로 포커스 이동
           document.getElementById("DEADDRESS").focus();
 
           // 주소 검색 후 좌표 이동 + 마커 표시
           geocoder.addressSearch(addr, function(result, status) {
           
             // 정상적으로 검색이 완료됐으면 
             if (status === kakao.maps.services.Status.OK) {
             
              //위도, 경도 저장
              var letlng = new kakao.maps.LatLng(result[0].y, result[0].x);
              var wii = result[0].y; //위도
              var kyung = result[0].x; //경도
              
              //hidden input value 바꿔주기
              $("input[name=WII]").val(wii); 
              $("input[name=KYUNG]").val(kyung);
              $("#DEADDRESS").val(''); //공백으로 바꿔줌
              
              function panTo() {
                // 이동할 위도 경도 위치를 생성
                var moveLatLon = new kakao.maps.LatLng(wii, kyung);
                
                // 지도 중심을 부드럽게 이동시킴
                map.panTo(moveLatLon);            
              }        
                
              //지도 새로 생성하기
              var container = document.getElementById('map'); 
              var options = { 
                 center: new kakao.maps.LatLng(wii, kyung), 
                 level: 3 
              };
            
              var map = new kakao.maps.Map(container, options); 
 
              // 결과값으로 받은 위치를 마커로 표시
              var marker = new kakao.maps.Marker({
                  map: map,
                  position: letlng
              });
         
              // 인포윈도우로 장소에 대한 설명을 표시
              var infowindow = new kakao.maps.InfoWindow({
                  content'<div style="width:150px;text-align:center;padding:6px 0;">'+addr+'</div>'
              });
              infowindow.open(map, marker);
         
              // 지도의 중심을 결과값으로 받은 위치로 이동
              map.setCenter(letlng);
            } 
         }); 
       }
   }).open({
    //팝업 가운데 정렬
    left: (window.screen.width / 2- (width / 2),
    top: (window.screen.height / 2- (height / 2),
    //팝업창 타이틀 지정
    popupTitle: '모임 장소 검색하기'
   });
}
cs

 

검색이 완료 되면 상세주소 입력칸을 공백으로 바꿔주고 카카오맵에서 제공하는 panTo() 함수를 사용해서 새로 검색한 주소의 좌표로 지도를 부드럽게 이동시키도록 해주었다.

 

완성~~

 

3. DB 연동: 지도의 수정과 삭제

지도 수정시의 문제는 사용자가 지도 등록을 하지 않았는데 모임을 수정하며 새로 등록 했을 시엔 insert를 시켜주어야 한다는 것이다.

지도 수정 쿼리를 작성했고 DAO에도 추가 해주었다.

1
2
3
4
5
6
7
8
9
10
11
<!-- 모임장소 수정 -->
<update id="moimMapModify" parameterType="hashmap">
    <![CDATA[
      UPDATE MOIM SET
      WII= #{WII},
      KYUNG = #{KYUNG},
      ADDRESS= #{ADDRESS}, 
      DEADDRESS = #{DEADDRESS, jdbcType=VARCHAR}
      WHERE MO_IDX = #{MO_IDX}
    ]]>
</update>
cs

 

1
2
3
4
// 모임 지도 수정
public void moimMapModify(Map<String, Object> map) throws Exception {
    update("moim.moimMapModify", map);
}
cs

 

그리고 서비스 클래스에서 지도 수정 혹은 insert 처리를 해주었다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 모임 수정
@Override
public void moimModify(Map<String, Object> map, HttpServletRequest request, HttpSession session) throws Exception {
 
    Map<String, Object> dMap = moimDao.moimDetail(map, session);
 
    try {
        if (dMap.get("MAP_IDX"!= null) {
            moimDao.moimMapModify(map); //지도 수정
        } else if (dMap.get("MAP_IDX"== null) {
            moimDao.moimMapInsert(map); //지도 insert
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
 
    moimDao.moimModify(map);
 
    List<Map<String, Object>> list = fileUtils.fileInsert(map, request);
 
    for (int i = 0, size = list.size(); i < size; i++) {
        moimDao.moimImg(list.get(i));
    }
}
cs

디테일 처리 메소드를 받아와 거기서 MAP_IDX(지도 시퀀스)가 있으면 수정 처리를, 있으면 insert가 되게끔 작성했다.

이렇게 수정은 완료~~

 

 

삭제는 게시글(=모임)이 삭제 되면 무조건 같이 삭제 되게끔 트리거를 생성해서 처리했다.

모임 삭제는 완전히 삭제 시키는 것이 아니라 삭제 유무 컬럼을 통해 update 시켜주는 것이고 map 자체는 완전히 delete 시켜야 했기 때문에 코드를 어떻게 작성해야하나 고민이 많았는데 문득 떠오른 트리거로 간단하게 해결할 수 있었다 ㅎㅎ..

 

 

 

댓글