개발자의 끄적끄적

[javascript/api] 다음 카카오 지도 API 연동 [펌] 본문

개발/javascript & jquery

[javascript/api] 다음 카카오 지도 API 연동 [펌]

효벨 2020. 5. 22. 08:54
728x90
반응형

[javascript/api] 다음 카카오 지도 API 연동 [펌]

 

 

 다음지도 API에서 자동으로 알아낸 후, 좌표값의 정보가 담긴 Scaffold 게시글을 등록하면 메인 홈페이지 등에 보여지는 지도에 모든 좌표가 보여지게 하는 원리의 지도를 소개하고자 합니다.

 

 

 

  Chapter  다음 카카오 지도 API 준비단계

 

https://developers.kakao.com/apps "


1. 다음 카카오 개발자센터[클릭]로 가서 로그인 혹은 회원가입을 진행합니다.
처음 시작하시는 분이라면 좌측메뉴에 보이는 '앱 만들기' 버튼을 클릭해서 새로운 앱을 만들어주세요.

 

2. 자신의 앱에 들어간 후, 좌측메뉴에 보이는 메뉴에서 설정 - 일반 에 가신 뒤,

Javascript API Key를 획득합니다.

 

3. 이어서 바로 아래에 보이는 '플랫폼' 탭에서 새 플랫폼(웹)을 추가한 후,

다음 카카오 MAP을 도입하기 위한 홈페이지 URL을 등록합니다.

 

4. 이제 모든 준비가 끝났습니다. 다음 Chapter로 이동해주세요.

 

 

  Chapter 2  다음 카카오 지도 API 구현

1. Scaffold를 만들어줍니다.

1

rails g scaffold posts title content:text lat lng

· title : 제목              · content : 내용

· lat : 지도 X축          · lng : 지도 Y축

 

2.  /app/views/layouts/application.html.erb  에 다음 내용을 작성해주세요.

(추가된 코드는 하늘색 글씨로 표시)

1

2

3

4

5

6

7

8

...

 

<%stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>

<%javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

    

<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=(Javascript API 키 코드)"></script>

    

...

 

여기에서 javascript API 키를 입력할 때 Chapter 1 과정으로 얻어냈던 javascript API키를 입력해야 하는 점, 잊지 말아주세요.

예시로 작성된 코드는 다음과 같습니다.

1

<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=f8f194d9cef123asdgk24krljwr32q23"></script>

 

 참고  개발자 도구(F12)를 통해 보면은 API 키가 그대로 노출되긴 하나, 이 부분은 걱정 안하셔도 됩니다.

Chapter 1의 3번 과정에서 등록된 URL 외에 해당 API Key를 사용하면 서버에서 사용 제한을 걸어둡니다.

 

3.  /app/views/posts/_form.html.erb  에 다음 내용을 작성해주세요.

(추가된 코드는 연두색 글씨로 표시)

 

지도에 마우스를 클릭하면 마커가 찍히게 되고, 자동으로 X축, Y축 input form에 입력이 됩니다.

 

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

<%= form_with(model: post, local: truedo |form| %>

  <if post.errors.any? %>

    <div id="error_explanation">

      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

 

      <ul>

      <% post.errors.full_messages.each do |message| %>

        <li><%= message %></li>

      <end %>

      </ul>

    </div>

  <end %>

  

  <div id="map" style="width:100%;height:350px;"></div>

  <p><em>지도를 클릭해서 좌표를 얻어내세요!</em></p>

 

  <div class="field">

    <%= form.label :title %>

    <%= form.text_field :title, id: :post_title %>

  </div>

 

  <div class="field">

    <%= form.label :content %>

    <%= form.text_area :content, id: :post_content %>

  </div>

  

  <div class="field">

    <%= form.label :"지도 X축" %>

    <%= form.text_area :lat, id: :lat, readonly: "readonly", rows: 1 %>

  </div>

  

  <div class="field">

    <%= form.label :"지도 Y축" %>

    <%= form.text_area :lng, id: :lng, readonly: "readonly", rows: 1  %>

  </div>

  

 

  <div class="actions">

    <%= form.submit %>

  </div>

<end %>

 

<script>

var mapContainer = document.getElementById('map'), // 지도를 표시할 div 

    mapOption = { 

        <if @post.lat == nil %>

            center: new daum.maps.LatLng(37.86890322758033127.74428448833586), // 최초 글 작성 시 지도의 중심좌표

        <else %>

            center: new daum.maps.LatLng(<%= @post.lat %><%= @post.lng %>), // 수정 시 보여지는 위치

        <end %>

        level: 2 // 지도의 확대 레벨

    };

 

var map = new daum.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

 

// 지도를 클릭한 위치에 표출할 마커입니다

var marker = new daum.maps.Marker({ 

    // 지도 중심좌표에 마커를 생성합니다 

    position: map.getCenter() 

}); 

// 지도에 마커를 표시합니다

marker.setMap(map);

 

// 지도에 클릭 이벤트를 등록합니다

// 지도를 클릭하면 마지막 파라미터로 넘어온 함수를 호출합니다

daum.maps.event.addListener(map, 'click', function(mouseEvent) {        

    

    // 클릭한 위도, 경도 정보를 가져옵니다 

    var latlng = mouseEvent.latLng; 

    

    // 마커 위치를 클릭한 위치로 옮깁니다

    marker.setPosition(latlng);

    

    // X축 좌표값을 얻어냄 

    var map_x = document.getElementById('lat'); 

    map_x.innerHTML = latlng.getLat();

    

    // Y축 좌표값을 얻어냄

    var map_y = document.getElementById('lng'); 

    map_y.innerHTML = latlng.getLng();

    

});

</script>

 

이번 과정에서 코드좀 짚고 넘어가보겠습니다.

 

1)  _form.html.erb  의 지도 API 예시는 다음 예시를 활용했습니다.

· 클릭한 위치에 마커 표시하기 [클릭]

 

2) 지도를 띄우는 태그입니다.

14

<div id="map" style="width:100%;height:350px;"></div>

 

3) Javascript 코드에서 지도에 마우스를 클릭하면 X축과 Y축을 알아냅니다.

74

75

76

77

78

79

80

// X축 좌표값을 얻어냄 

var map_x = document.getElementById('lat'); 

map_x.innerHTML = latlng.getLat();

    

// Y축 좌표값을 얻어냄

var map_y = document.getElementById('lng'); 

map_y.innerHTML = latlng.getLng();

 

4) Javascrpit 코드로 부터 알아낸 지도의 X축과 Y축을 input 태그에 입력시키고, 후에 DB에 저장됩니다.

readonly: "readonly" 속성 때문에 직접적인 태그에 글 작성은 막혀있습니다.

27

28

29

30

31

32

33

34

35

<div class="field">

    <%= form.label :"지도 X축" %>

    <%= form.text_area :lat, id: :lat, readonly: "readonly", rows: 1 %>

</div>

  

<div class="field">

    <%= form.label :"지도 Y축" %>

    <%= form.text_area :lng, id: :lng, readonly: "readonly", rows: 1  %>

</div>

 

5) 처음에 사람들에게 보여질 지도의 위치에 대한 정보를 나타냅니다.

 참고  현재 좌표는 강원대학교 춘천캠퍼스를 가리킵니다.

 

그리고 레일즈에 있어  form_with  는 새 글 작성/수정을 같이 담당하는 태그인데,

저희는 새 글 작성/수정 상황에 따라 지도의 뷰가 다르게 보이게 하고자 합니다.

 

46번째 줄에서 만약 lat가 아무 내용도 없다면 새 글로 간주(사실 새 글 구분 기준은 ID값이 있냐 없느냐로 하는게 좋긴 하나, 애초에 글을 작성 시에 지도에 마커표시를 안할 경우를 대비를 해서 이렇게 작성했습니다.),

그게 아니면 이미 DB에 저장된 데이터를 불러와서 마커표시했던 지점을 중심으로 지도가 보여지게 합니다.

44

45

46

47

48

49

50

51

52

var mapContainer = document.getElementById('map'), // 지도를 표시할 div 

mapOption = { 

    <if @post.lat == nil %>

        center: new daum.maps.LatLng(37.86890322758033127.74428448833586), // 최초 글 작성 시 지도의 중심좌표

    <else %>

        center: new daum.maps.LatLng(<%= @post.lat %><%= @post.lng %>), // 수정 시 보여지는 위치

    <end %>

    level: 2 // 지도의 확대 레벨

};

 

4.  /app/views/posts/index.html.erb  에 다음 코드를 입력합니다.

 예시 1  마우스 오버 시 info message가 보여지게 (모바일에서는 작동 안되는 듯 함.)

 

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

...

 

<div id="map" style="width:100%;height:350px;"></div>

<button onclick="hideMarkers()">마커 감추기</button>

<button onclick="showMarkers()">마커 보이기</button>

 

...

(scaffold 게시글이 보여지는 내용)

...

 

<%# 지도 Control 영역 (제일 아래에 작성) %>

<script>

var mapContainer = document.getElementById('map'), // 지도를 표시할 div  

    mapOption = { 

        center: new daum.maps.LatLng(37.86890322758033127.74428448833586), // 지도의 중심좌표

        level: 2 // 지도의 확대 레벨

    };

 

var map = new daum.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

 

// 마커를 표시할 위치와 내용을 가지고 있는 객체 배열입니다 

var positions = [

    <% @posts.each do |x| %>

    {

        content: '<div><%= x.title %></div>'

        latlng: new daum.maps.LatLng(<%= x.lat %><%= x.lng %>)

    },

    <end %>

];

 

// 지도에 표시된 마커 객체를 가지고 있을 배열입니다

var markers = [];

 

for (var i = 0; i < positions.length; i ++) {

    // 마커를 생성합니다

    var marker = new daum.maps.Marker({

        map: map, // 마커를 표시할 지도

        position: positions[i].latlng // 마커의 위치

    });

 

    // 마커에 표시할 인포윈도우를 생성합니다 

    var infowindow = new daum.maps.InfoWindow({

        content: positions[i].content // 인포윈도우에 표시할 내용

    });

    

    // 생성된 마커를 배열에 추가합니다

    markers.push(marker);

 

    // 마커에 mouseover 이벤트와 mouseout 이벤트를 등록합니다

    // 이벤트 리스너로는 클로저를 만들어 등록합니다 

    // for문에서 클로저를 만들어 주지 않으면 마지막 마커에만 이벤트가 등록됩니다

    daum.maps.event.addListener(marker, 'mouseover', makeOverListener(map, marker, infowindow));

    daum.maps.event.addListener(marker, 'mouseout', makeOutListener(infowindow));

}

 

// 인포윈도우를 표시하는 클로저를 만드는 함수입니다 

function makeOverListener(map, marker, infowindow) {

    return function() {

        infowindow.open(map, marker);

    };

}

 

// 인포윈도우를 닫는 클로저를 만드는 함수입니다 

function makeOutListener(infowindow) {

    return function() {

        infowindow.close();

    };

}

 

 

/* 마커 보이기 및 숨기기 제어 */

// 배열에 추가된 마커들을 지도에 표시하거나 삭제하는 함수입니다

function setMarkers(map) {

    for (var i = 0; i < markers.length; i++) {

        markers[i].setMap(map);

    }            

}

 

// "마커 보이기" 버튼을 클릭하면 호출되어 배열에 추가된 마커를 지도에 표시하는 함수입니다

function showMarkers() {

    setMarkers(map)    

}

 

// "마커 감추기" 버튼을 클릭하면 호출되어 배열에 추가된 마커를 지도에서 삭제하는 함수입니다

function hideMarkers() {

    setMarkers(null);    

}

</script>

 

이번 과정에서 코드좀 짚고 넘어가보겠습니다.

 

1) 예시 1  index.html.erb  의 지도 API 예시는 다음 예시를 활용했습니다.

· 여러개 마커에 이벤트 등록하기1 [클릭]

· 여러개 마커 제어하기 [클릭]

 

2) 마커를 띄우는 Javascript 태그입니다. json 방식이 쓰였습니다.

레일즈의 each do 를 이용해서 여러개의 마커가 보여지도록 반복합니다.

1

2

3

4

5

6

7

8

9

// 마커를 표시할 위치와 내용을 가지고 있는 객체 배열입니다 

var positions = [

    <% @posts.each do |x| %>

    {

        content: '<div><%= x.title %></div>'

        latlng: new daum.maps.LatLng(<%= x.lat %><%= x.lng %>)

    },

    <end %>

];

 

3) 지도에 표기된 마커를 보여주거나 숨기기 위한 작업 준비 코드로서, 마커들에 대한 정보를 해당 배열에 담아둘 예정입니다.

72

var markers = [];

 

4) (87번 째 줄 코드) 생성된 마커들의 정보를 72번 째 줄에 입력했던 배열에 담아둡니다.

74

 

 

86

87

 

 

94

for (var i = 0; i < positions.length; i ++) {

    ...

    

    // 생성된 마커를 배열에 추가합니다

    markers.push(marker);

 

    ...

}

 

5) 마커 정보가 담긴 배열들을 setMap 함수에 등록(초기화) 합니다.

113

114

115

116

117

function setMarkers(map) {

    for (var i = 0; i < markers.length; i++) {

        markers[i].setMap(map);

    }            

}

 

6) showMarkers() 함수의 역할을 설정합니다. (해당 이벤트 발생 시 지도에서 마커들이 보여짐)

120

121

122

function showMarkers() {

    setMarkers(map)    

}

 

7) hideMarkers() 함수의 역할을 설정합니다. (해당 이벤트 발생 시 지도에서 마커들이 보여짐)

125

126

127

function hideMarkers() {

    setMarkers(null);    

}

 

8) 마커들을 보여주거나 숨기게 합니다. (이벤트 트리거)

24

25

<button onclick="hideMarkers()">마커 감추기</button>

<button onclick="showMarkers()">마커 보이기</button>

 

 예시 2  마우스 클릭 시 info Message가 보여지게

 

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

...

 

<div id="map" style="width:100%;height:350px;"></div>

 

...

 

<script>

var mapContainer = document.getElementById('map'), // 지도를 표시할 div  

    mapOption = { 

        center: new daum.maps.LatLng(37.86890322758033127.74428448833586), // 지도의 중심좌표

        level: 2 // 지도의 확대 레벨

    };

 

var map = new daum.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

 

// 마커를 표시할 위치와 내용을 가지고 있는 객체 배열입니다 

var positions = [

    <% @posts.each do |x| %>

    {

        content: '<div><%= x.title %></div>'

        latlng: new daum.maps.LatLng(<%= x.lat %><%= x.lng %>)

    },

    <end %>

];

 

// 지도에 표시된 마커 객체를 가지고 있을 배열입니다

var markers = [];

 

for (var i = 0; i < positions.length; i ++) {

    // 마커를 생성합니다

    var marker = new daum.maps.Marker({

        map: map, // 마커를 표시할 지도

        position: positions[i].latlng, // 마커의 위치

        clickable: true

    });

    

    

    var iwContent = positions[i].content, // 인포윈도우에 표출될 내용으로 HTML 문자열이나 document element가 가능합니다

    iwRemoveable = true// removeable 속성을 ture 로 설정하면 인포윈도우를 닫을 수 있는 x버튼이 표시됩니다

    

    // 인포윈도우를 생성합니다

    var infowindow = new daum.maps.InfoWindow({

    content : iwContent,

    removable : iwRemoveable

    });

    

    // 생성된 마커를 배열에 추가합니다

    markers.push(marker);

 

    // 마커에 클릭이벤트를 등록합니다

    daum.maps.event.addListener(marker, 'click', makeClickListener(map, marker, infowindow));

}

 

// 클릭 이벤트 발현에 대한 함수입니다.

function makeClickListener(map, marker, infowindow) {

  return function() {

    infowindow.open(map, marker);

  };

}

</script>

 

코드좀 짚고 넘어가보겠습니다.

 

1) 예시 2  index.html.erb  의 지도 API 예시는 다음 예시를 활용했습니다.

· 여러개 마커 제어하기 [클릭]

· 마커에 클릭 이벤트 등록하기 [클릭]

 

2) 클릭 이벤트 발현 시, 이벤트가 발현되는 함수로 넘겨줍니다.

96

daum.maps.event.addListener(marker, 'click', makeClickListener(map, marker, infowindow));

 

3) 클릭 이벤트 처리를 담당하는 함수입니다.

100

101

102

103

104

function makeClickListener(map, marker, infowindow) {

  return function() {

    infowindow.open(map, marker);

  };

}

 

5. 위와같이 설정을 하면 대략적인 지도 API 활용을 하실 수 있게 됩니다!

참고로 Scaffold 게시글이 지워지면, 마커 또한 지워지는 점 참고해주세요!

 

 예시 3  마우스 클릭 시 info Message가 보여지게 + 비동기 방식

* 비동기 방식은 데이터 처리속도가 빠르다는 장점이 있음.

연두색 글씨 : 비동기 방식으로 데이터를 불러오는 코드

하늘색 글씨(17번 째 줄) : 자신의 파일 이름에 맞는 json 파일명 입력 (현재 예제처럼 따라했다면 안바꿔도 됨.)

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

...

 

<div id="map" style="width:100%;height:350px;"></div>

 

...

 

<script>

  var mapContainer = document.getElementById('map'), // 지도를 표시할 div  

      mapOption = { 

          center: new daum.maps.LatLng(37.86890322758033127.74428448833586), // 지도의 중심좌표

          level: 2 // 지도의 확대 레벨

      };

   

  var map = new daum.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

   

  // Json 비동기 처리방식

  $.getJSON('/posts.json'function(data){

    var markers = [];

    $.each(data, function(i, item){

      

      var positions = [

        {

          content'<div>'+item.title+'</div>'

          latlng: new daum.maps.LatLng(item.lat, item.lng)

        },

      ];

      

      for (var i = 0; i < positions.length; i ++) {

        // 마커를 생성합니다

        var marker = new daum.maps.Marker({

          map: map, // 마커를 표시할 지도

          position: positions[i].latlng, // 마커의 위치

          clickable: true

        });        

        

        var iwContent = positions[i].content// 인포윈도우에 표출될 내용으로 HTML 문자열이나 document element가 가능합니다

        iwRemoveable = true// removeable 속성을 ture 로 설정하면 인포윈도우를 닫을 수 있는 x버튼이 표시됩니다

        

        // 인포윈도우를 생성합니다

        var infowindow = new daum.maps.InfoWindow({

          content : iwContent,

          removable : iwRemoveable

        });

        

        // 생성된 마커를 배열에 추가합니다

        markers.push(marker);

        

        // 마커에 클릭이벤트를 등록합니다

        daum.maps.event.addListener(marker, 'click', makeClickListener(map, marker, infowindow));

      }

      

    })

  }) 

  

  // 클릭 이벤트 발현에 대한 함수입니다.

  function makeClickListener(map, marker, infowindow) {

    return function() {

      infowindow.open(map, marker);

    };

  }

</script>

 

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

## 참고 : Json 파일 (해당 내용은 그저 참고로만 보시고, 배낄 필요는 없습니다.)

 

[

{

"lat":"37.86844026066022",

"lng":"127.74483670632969",

"title":"테니스장",

"content":"ㅇㅅㅇ",

"created_at":"2018-10-25T17:20:11.055Z",

"updated_at":"2018-10-25T17:20:11.055Z",

"url":"https://intructure-material-kbs4674.c9users.io/posts/1.json"

},

{

"lat":"37.868446169315334",

"lng":"127.74318886960685",

"title":"강대 운동장",

"content":"ㅇㅅㅇ",

"created_at":"2018-10-25T17:20:41.278Z",

"updated_at":"2018-10-26T16:47:29.427Z",

"url":"https://intructure-material-kbs4674.c9users.io/posts/2.json"

},

{

"lat":"37.86935673313407",

"lng":"127.74309004914765",

"title":"연적지",

"content":"ㅇㅇ",

"created_at":"2018-10-26T17:17:09.071Z",

"updated_at":"2018-10-26T17:17:09.071Z",

"url":"https://intructure-material-kbs4674.c9users.io/posts/8.json"

},

{

"lat":"37.86918935132096",

"lng":"127.74462831410895",

"title":"대학본부",

"content":"ㅎㅎ",

"created_at":"2018-10-26T17:17:24.894Z",

"updated_at":"2018-10-26T17:17:24.894Z",

"url":"https://intructure-material-kbs4674.c9users.io/posts/9.json"

}

]

 

 

출처 : http://blog.naver.com/PostView.nhn?blogId=kbs4674&logNo=221381753132&parentCategoryNo=&categoryNo=78&viewDate=&isShowPopularPosts=false&from=postView

반응형
Comments