[23/07/31] 카카오 맵 API 사용하기

yeju·2023년 7월 31일
0

연습

목록 보기
7/7
post-thumbnail

1. 라이브러리 필요

gson-2.8.9.jar
json-20220320.jar

2. 기본 로직

1) jsp 페이지에서 주소를 입력받음

2) 입력받은 주소를 구글맵 api에 전달해 위도, 경도를 JSON으로 받아옴

  • 구글 api 연결하는 방법
    URL 객체 만들어서 openConnection() 메서드 호출 -> 받아온 URLConnection의 getInputStream() 메서드 호출 -> InputStream 반환
    InputStream 읽기 위해 BufferedReader 객체 생성
    (생성자에 new InputStreamReader(InputStream객체, 인코딩타입) 넣어주기)

  • BufferedReader로 받아온 데이터 읽어오는 방법
    읽을 내용(JSON 형태의 문자열) 담을 String 변수(str),
    읽은 내용을 누적할 StringBuilder 변수(strBuilder) 만들기

while((str = 버퍼.readLine()) != null) {
	// 데이터셋 다음 줄로 이동후 그 값을 str에 담고, 해당 값이 존재하면
	strBuilder.append(str);
	// StringBuilder에 해당 값을 이어붙임
}
  • JSON 객체 만들기
    완성한 StringBuilderJSON 객체 로 만들어 값 가져오기
    해당 JSON 객체는 { "results" : "JSON객체 배열[]" , "status" : "OK" } 형태

    results의 값인 JSON 배열을 JSONArray 객체로 받아오기
JSONArray arr = jsonObj.getJSONArray("results");

해당 배열의 첫번째 값(JSON객체) 받아오고, 받아온 JSON 객체 안에 든 JSON객체를 계속 받아와서 최종적으로 "lat", "lng" 키의 값을 Double 타입으로 받아옴

3) 받아온 JSON을 자바 DTO에 담아 바인딩 후 출력 페이지로 포워드

4) 출력 페이지에서 DTO에 담긴 위도, 경도 값을 가져와 카카오 맵 api를 사용해서 자바스크립트로 코드로 지도 화면 출력

3. 필요한 jsp 페이지 / 자바 클래스

1) 주소 입력 페이지 : form 태그의 action 속성으로 서블릿 매핑

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주소 입력</title>
</head>
<body>
<form action="map">
	주소 : <input type="text" name="addr" value="창원시 마산회원구 양덕북12길 113">
	<input type="submit" value="입력">
</form>
</body>
</html>

2) 컨트롤러 서블릿 : jsp에서 요청받은 주소 처리
주소를 DAO에 파라미터로 전달해 메서드 호출하고 위도, 경도, 위치값 담은 DTO 받기
받은 DTO를 request에 바인딩하고 출력 페이지로 포워드

package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dao.MapDAO;
import dto.MapDTO;

@WebServlet("/map")
public class MapController extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 주소 정보를 한글로 받기 때문에 한글 깨짐 방지
		request.setCharacterEncoding("utf-8");
		// 입력한 주소를 변수로 받기
		String addr = request.getParameter("addr");
		
		// dao 사용을 위해 객체 생성
		MapDAO dao = new MapDAO();
		// dao의 메서드 호출해 MapDTO 받아오기
		MapDTO dto = dao.getByGeoDataByAddress(addr);
		dto.setName(addr);
		
		// request에 바인딩하고 포워드
		request.setAttribute("mapInfo", dto);
		RequestDispatcher dispatch = request.getRequestDispatcher("view.jsp");
		dispatch.forward(request, response);
	}
}

3) DAO 클래스 : 주소를 가지고 구글맵 api를 사용해 JSON 형태의 문자열로 돌려받고,
해당 문자열을 JSON객체/JSON배열 객체 등으로 변환해 필요한 값을 가져옴
값(위도, 경도)을 DTO에 set하고 해당 DTO 리턴

package dao;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;

import org.json.JSONArray;
import org.json.JSONObject;

import dto.MapDTO;

public class MapDAO {
	public MapDTO getByGeoDataByAddress(String addr) throws IOException {
		// return할 데이터 준비
		MapDTO dto = new MapDTO();
		
		// API key(키값)
		String API_KEY = "AIzaSyDXMN6Lg3WVVzi20NcbAEEBJu6Xw9Ai3Cs";
		// 입력한 주소(address), API key(key)를 파라미터로 가지는 url 준비 (google 서버에 전달하기 위해)
		// 주소는 한글이므로 url에 붙일 때 깨지지 않도록 URLEncoder.encode() 사용
	    String surl = "https://maps.googleapis.com/maps/api/geocode/json?address=" + URLEncoder.encode(addr, "UTF-8") + "&key="+API_KEY;
	    
	    // html에서 a태그, form 태그 쓰는 것처럼 자바에서 다른 서버에 action 요청하는 방법 : URL 객체 사용하기
	    URL url = new URL(surl);
	    
	    // URL.openConnection() : google에 쿼리 날리기(action 실행)
	    // URLConnection.getInputStream() : java가 아닌 외부에서 데이터 받아오기(InputStream)
	    InputStream is = url.openConnection().getInputStream();

	    // 받아온 데이터 버퍼(보조 스트림)에 담기
	    BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "utf-8"));
	    
	    // StringBuilder : String 객체는 내용이 변할 때마다 객체가 새로 생성되는데,
	    // StringBuilder는 한 객체에 내용을 계속 누적시키므로 내용이 계속 변해도 메모리를 절약할 수 있음
	    StringBuilder responseStrBuilder = new StringBuilder();
	    String inputStr;
	    
	    // 받아온 데이터 읽어와서 값 strBuilder에 누적하기
	    while ((inputStr = streamReader.readLine()) != null) {
	    	responseStrBuilder.append(inputStr);
	    }
	    System.out.println("StrBuilder : " + responseStrBuilder);
	    System.out.println("======================================");
	    
	    // 받아온 문자열은 json 형식으로 되어 있음, 사용하기 위해 json 객체로 변환하기
	    JSONObject jsonObj = new JSONObject(responseStrBuilder.toString());
	    System.out.println("jsonObj : " + jsonObj);
	    System.out.println("======================================");
	    // 해당 json 객체는 results라는 키에 모든 json 객체를 값(배열)으로 가지기 때문에,
	    // results 키의 값인 배열을 JSONArray로 만들어 각 배열 요소에 접근함
	    JSONArray results = jsonObj.getJSONArray("results");
	    
	    if(results.length() > 0) {
	    	JSONObject obj;
	    	// 배열의 첫번째 값 가져오기 : json 객체
	    	obj = results.getJSONObject(0);
	    	// 그 객체 안의 geometry 키의 값(json객체) -> 안의 location 키의 값(json객체) -> 안의 lat 키의 값(double) 가져오기 : 위도, 경도 가져오기
	    	Double lat = obj.getJSONObject("geometry").getJSONObject("location").getDouble("lat");
	    	Double lng = obj.getJSONObject("geometry").getJSONObject("location").getDouble("lng");
	    	System.out.println("lat : " + lat + ", lng : " + lng);
	    	System.out.println("======================================");
	    	// 받아온 위치 값을 MapDTO에 set하고 리턴
	    	dto.setX(lat);
	    	dto.setY(lng);
	    	return dto;
	    }
	    // if문 실행되지 않았을때 null 리턴
	    return null;
	}
}

4) DTO : 위도(x좌표), 경도(y좌표), 주소(name)을 멤버로 가지는 DTO

package dto;

public class MapDTO {
	private String name;
	private double x;
	private double y;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getX() {
		return x;
	}
	public void setX(double x) {
		this.x = x;
	}
	public double getY() {
		return y;
	}
	public void setY(double y) {
		this.y = y;
	}
}

5) 지도 출력 페이지 : 카카오 맵 api 사용, js 코드로 지도 화면 출력

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="dto.MapDTO" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주소 출력</title>
</head>
<body>
<%
	// 바인딩한 MapDTO 가져오기
	MapDTO dto = (MapDTO) request.getAttribute("mapInfo");
%>
<!-- 카카오 지도 web api에서 소스 가져오기 -->
<div id="map" style="width:500px;height:400px;"></div>
<p><%= dto.getName() %></p>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=6d096e2d7e3f4c07523b417978a66ad0"></script>
<script>
	var container = document.getElementById('map');
	var options = {
		center: new kakao.maps.LatLng(<%= dto.getX() %>, <%= dto.getY() %>),
		level: 3
	};
	var map = new kakao.maps.Map(container, options);
</script>
</body>
</html>

💻 실행 결과

profile
🌱

0개의 댓글