본 내용은 혼자서 공부하기 위한 용도로 사용된 것으로 비효율적일 수 있으며 실용적이지 않을 수 있습니다.
다음 과정을 나아가기 위하여 먼저 살펴보아야할 것이 있다. jQuery에서의 Ajax이다.
0. jQuery(Ajax)
jQuery에서의 기능 중 Ajax(Asynchronos Javascript And XML)을 살펴본다. 풀네임을 살펴보듯이 핵심은 '비동기'이다. 우리가 여태껏 사용하였던 방식은 클라이언트의 요청을 보냄과 동시에 웹페이지도 즉시 반응하는 동기적인 구성이였다. 그러나 Ajax를 사용하면 클라이언트의 요청을 보내도 따로 웹페이지에서의 변화는 없다. 그렇지만 요청에 따라서 서버는 해당하는 데이터를 보내주어준다. 이 방식을 앞으로 계속 사용할 것이다. 그러므로 간단하게 살펴보자.
$.ajax({ url: "클라이언트의 요청을 보낼 주소", dataType:"서버로 부터 받아오는 데이터 타입", type: "받아올 때의 형식:GET,POST", contentType : "클라이언트 요청의 타입", data: 클라이언트 요청이나 데이터, success: function(result) { 데이터 전송 성공 } }, error:function(){ 데이터 전송 실패 } });
- 위에 간단하게 적어 놓았지만 설명을 보태자면 url 부분은 서버로 요청을 보내는 주소로 controller에서 받는 주소 *.do 와 같은 것을 말하는 것이다. dataType은 말 그대로 서버로부터 받아올 때의 데이터 타입이며, type은 POST, GET 방식의 선택을 말한다. contentType의 경우는 ajax를 통해 클라이언트 요청을 보낼 때의 데이터 타입을 말하며 data가 클라이언트의 요청 또는 데이터를 말한다. 성공 시 success의 함수가 실행되며 파라미터인 result가 서버로부터 받아온 데이터를 뜻하는 것이다. 실패 시 error의 함수가 실행된다.
일단은 여기까지만 알아도 앞으로의 개발에는 전혀 문제가 없을 것이다.
1. 다음 지도 API에 정류장 위치 나타내기
먼저, jsp 파일부터 살펴보자. 밑의 코드 node_find.jsp 스크립트 부분에 추가해주자.
$("#node_find").addClass("selected"); fn_clickSetting(); $(document).ready(function(){ $("#sc_btn").on("click",function(e){ e.preventDefault(); fn_clickSearchButton(); }) $("a[name^='node']").on("click",function(e){
e.preventDefault();
fn_clickNode($(this));
}) }) function fn_clickSearchButton(){ setMarkers(null); $("#resultBox").children().remove(); //경도 위도를 ajax를 통해 보낼 데이터에 추가 var data={}; data["LAT"]=$("#lat").val(); data["LNG"]=$("#lng").val(); //지도 중심을 변경합니다. map.setCenter(new daum.maps.LatLng(data["LAT"],data["LNG"])); /* 이 부분에서 위도 경도 좌표를 서버로 보내주고 서버에서는 오픈API를 통해 정류장 ID와 정류장 이름을 가져와 ajax로 리턴해준다. 보내는 데이터 : lat,lng 받는 데이터 : List<Map<String,Object> 정류장 정보> 정류장 정보들 */ $.ajax({ url: "/gcbus/nodeList.do", dataType:"json", type: "POST", contentType : "application/json", data: JSON.stringify(data), success: function(result) { for(var i=0; i< result["list"].length;i++){ var map=result["list"][i]; var str = "<a href='#this' nodeid='"+map["NODEID"]+"' lat='"+map["LAT"]+"' lng='"+map["LNG"]+"' name='node"+i+"' id='node"+i+"' class='result sc_node_result'>"+map["NODENM"]+"</a>"; $("#resultBox").append(str); //Daum API marker 생성 함수() fn_nodeMarkerMaker($("a[name='node"+i+"']")); } $("a[name^='node']").on("click",function(e){ e.preventDefault(); fn_clickNode($(this)); }) }, error:function(){ alert("실패"); } }); }
(무슨 이유에선지 마지막에/map~~~라고 하는 부분이 같이 뜨는데 이 부분은 복사하지마라.)
- 1~15라인
제일 첫 부분은 사이드 메뉴 중 현재 메인 페이지인 정류소 찾기 버튼의 클릭시 CSS 적용을 위해 클래스를 추가해주는 부분이며, 3라인의 경우는 이 전전 포스팅에서 설정해둔 부분(지도 클릭 이벤트)이므로 생략해도 된다. 그 후 찾기 버튼에 대한 이벤트를 작성해놓았다. 또 그 밑은 나중 결과값에 대한 클릭 이벤트이다.
- 17~61라인
찾기 버튼을 클릭 하였을 시 경도, 위도에 적혀 있는 주변의 정류소를 찾기 위한 함수이다. 하나씩 살펴보자면 19~21라인의 경우는 정류소 마커 부분들과 정류장 검색 결과들을 초기화 시켜주기 위함이다. 23~25라인에서 ajax를 통해 서버로 보낼 위도 경도 데이터들을 할당 해주고 ajax를 통해 해당 데이터를 JSON으로 변형 뒤 보내준다(40라인). 데이터를 받아오기가 성공하였을 경우 받아온 데이터 중 list에 저장되어 있는 정류소 정보를 결과박스에 추가해주고 정류소 정보를 통해 지도 위에 마커를 생성해준다(48라인). 그 후 정류소 결과값에 대한 이벤트 처리를 해준다.
위 48라인의 기능을 하는 함수를 map.js에 추가하라.
webapp/js/daumAPI/map.js
//마커를 생성하고 지도 위에 표시하는 함수입니다 function fn_nodeMarkerMaker(obj){ //다음 맵 API 마커 생성하기 var markerPosition = new daum.maps.LatLng(obj.attr("lat"), obj.attr("lng")); // 마커를 생성합니다 var marker = new daum.maps.Marker({ position: markerPosition, clickable: true }); //마커를 지도 위에 표시되도록 세팅합니다. marker.setMap(map); //생성된 마커를 배열에 추가합니다. markers.push(marker); daum.maps.event.addListener(marker,"click",function(e){ if(obj.attr("id").slice(0,4)=="node"){ //마커 클릭 이벤트를 선언해줍니다. fn_clickNode(obj); }else if(obj.attr("id").slice(0,4)=="path"){ fn_clickPath(obj); } }); }
- 다음 지도 API에서 마커를 생성하는 함수로 위도,경도를 받아와 생성하고 지도 위에 표시해준다. 그리고 마커에 대한 클릭 이벤트를 추가하여준다. 23~26라인의 경우 나중에 노선에 대한 정보를 가진 마커에 대한 부분이니 미리 작성해둔다.
이제 ajax를 통해 데이터를 주고 받기 위한 클라이언트 요청을 받을 컨트롤러부터 작성하여보자.
2. Controller
GCBusController.java
@RequestMapping(value="/nodeList.do") public @ResponseBody ModelAndView busList(@RequestBody Mapmap) throws Exception{ map.put("list", gcBusServ.nodeList(map)); return new ModelAndView("jsonView", map); }
- 원래 보던 메소드와 다른 형태인 것을 볼 것이다. @ResponseBody가 선언 되어 있으면 값이 리턴이 view를 통해서 전달되는 것이 아니라 해당 자바 객체를 HTTP 응답 몸체로 변경하여 전달하고, @RequestBody의 경우는 HTTP 요청 몸체를 자바 객체로 변경한다.(좀더 깊은 설명을 위해서는 검색하여 보길 추천한다.) gcBusServ를 호출하여 정류소 리스트를 map에 추가하고, 그리고 MappingJacksonJsonView(action-servlet.xml 39~41라인 선언)를 이용하여 Map을 json으로 변환하여 리턴한다.
3. Service, ServiceImpl, DAO
GCBusService.java
List<Map<String,Object>> nodeList(Map<String, Object> map) throws Exception;
GCBusServiceImpl.java
public List<Map<String, Object>> nodeList(Map<String, Object> map) throws Exception {
return gcBusDAO.selectNodeList(map);
}
GCBusDAO.java
@SuppressWarnings("unchecked")
public List<Map<String, Object>> selectNodeList(Map<String, Object> map) {
return (List<Map<String,Object>>)selectList("gcbus.selectNodeList",map);
}
- Service, DAO 단에서는 특별한 것 없이 일반적인 형태를 띄어 설명을 하진 않겠다.
4.SQL
resources/mapper/gcbus_SQL.xml
<mapper namespace="gcbus">
<select id="selectNodeList" parameterType="HashMap" resultType="HashMap">
<![CDATA[
SELECT
NODEID,
NODENM,
NODENO,
GPSLATI AS LAT,
GPSLONG AS LNG
FROM
NODE_INFO
WHERE
GPSLATI > (#{LAT}-0.002) AND GPSLATI < (#{LAT}+0.002) AND GPSLONG > (#{LNG}-0.002) AND GPSLONG < (#{LNG}+0.002)
]]>
</select>
</mapper>
- 위 코드를 작성하여 준다. 정류소 정보들을 불러오는데 받아온 위도와 경도에서의 0.002(+-)를 하여 해당하는 위도 경도 값을 가진 정류소 정보들만 가져온다. 이외에 특별한 것은 없다.
5. 테스트
- 찾기 클릭 시
이 화면까지 잘 처리가 된다면 잘 따라온 것이다.