- 새롭게 진행중인 "점심메뉴 추천서비스" 토이 프로젝트에 카카오맵 API를 활용하여 현재 사용자의 위치 근방에 존재하는 음식점들의 정보를 보여줄 수 있게 카카오맵 API 를 활용하였다.

 

- Js를 사용하면 더욱 간편하게 사용이 가능하지만 서버에서 데이터를 받아와서 화면에 뿌려주는 방식으로 구현하여 추후 기능 업데이트시에 서버에서 데이터를 별도로 가공할 목적으로 카카오맵 API를 Rest하게 사용하도록 구현하였다.

 

- 모든 코드는 GitHub에서 확인 가능하다

Link : https://github.com/DoHyeonJ/LunchRecommend


1. Controller

package com.lunchrecommend;

import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequiredArgsConstructor
public class LunchController {

    private final LunchService lunchService;

    /**
     * 음식점 추천 List Post 요청
     * @param request 요청 데이터
     * @return ResponseEntity
     */
    @PostMapping("/lunch")
    private ResponseEntity<String> searchLunch(HttpServletRequest request) {
        String latitude = request.getParameter("latitude");
        String longitude = request.getParameter("longitude");
        String page = request.getParameter("page");

        return lunchService.getSearchLunchList(latitude, longitude, page, "15");
    }

    @PutMapping("/lunch")
    private ResponseEntity<String> updateLunch() {
        return ResponseEntity.status(HttpStatus.OK).body("PutMapping!!");
    }

    @DeleteMapping("lunch")
    private ResponseEntity<String> deleteLunch() {
        return ResponseEntity.status(HttpStatus.NO_CONTENT).body("DeleteMapping!!");
    }

}
  • Controller에서는 "/lunch"라는 url 호출시 동작할 mapping들을 정의해 놓았다.
  • 현재는 PostMapping만 사용하지만 추후 사용성을 대비하여 Put과 Delete도 구현해놓았다.
  • Url 요청시에 "http://localhost:8080/lunch" 를 호출 할 경우 Http Method를 Post, Put, Delete를 설정하여 호출할 경우를 각각 구현하였다.
  • 필수 파라미터로는 latitude : 위도, longitude : 경도, page : 노출 페이지 수 / 3개의 파라미터를 받게된다.

 

2. Service

package com.lunchrecommend;

import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@Service
public class LunchService {

    /**
     * 좌표 기준 음식점 데이터 조회
     * 파라미터 순서는 x, y 순서로 넘겨줘야 데이터 리턴 받을 수 있음
     * @param longitude 경도 -> x
     * @param latitude 위도 -> y
     * @param page 페이지 수 1,2,3
     * @param size 페이지당 조회 수 15
     * @return ResponseEntity
     */
    public ResponseEntity<String> getSearchLunchList(String longitude, String latitude, String page, String size) {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(List.of(MediaType.APPLICATION_JSON));
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "KakaoAK {APIKEY}");

        HttpEntity<String> entity = new HttpEntity<>("", headers);

        String baseUrl = "https://dapi.kakao.com/v2/local/search/category.json?" +
                "category_group_code=FD6" +
                "&page=" + page +
                "&size="+ size +
                "&sort=accuracy" +
                "&x=" + latitude +
                "&y=" + longitude;

        RestTemplate restTemplate = new RestTemplate();

        return restTemplate.exchange(baseUrl, HttpMethod.GET, entity, String.class);
    }

}
  • 위에서 본 Controller에서 Post요청을 통해 getSearchLunchList 메서드를 호출한다.
  • 경도, 위도, 노출 페이지 파라미터는 받았으며, 여기서 따로 설정해줘야 하는 부분은 headers.set을 해주고있는 부분의 {APIKEY}를 넣어줘야 한다.
  • Key값 얻는법 
 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

3. View

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Kakao 지도 시작하기</title>
    <script src="https://code.jquery.com/jquery-3.6.0.js" crossorigin="anonymous"></script>
</head>
<body>
<div>
    <input type="hidden" id="select_count" value="3">
    <input id="lunch_recommend" type="button" value="맛집 추천"/>
</div>

<div id="lunch_list">
    <!-- lunch list area -->
</div>

<!-- TODO : appkey 변수화 작업 필요-->
<script type="text/javascript"
        src="//dapi.kakao.com/v2/maps/sdk.js?appkey={APPKEY}&libraries=services"></script>
<script>

    $('#lunch_recommend').click(function () {
        if ("geolocation" in navigator) {	/* geolocation 사용 가능 */
            navigator.geolocation.getCurrentPosition(function (data) {

                const latitude = data.coords.latitude;
                const longitude = data.coords.longitude;
                const page = $('#select_count').val();

                searchLunchReccomend(latitude, longitude, page);
            }, function (error) {
                alert(error);
            }, {
                enableHighAccuracy: true,
                timeout: Infinity,
                maximumAge: 0
            });
        } else {	/* geolocation 사용 불가능 */
            alert('geolocation 사용 불가능');
        }
    });

    function searchLunchReccomend(latitude, longitude, page) {

        // 이미 한번이라도 호출했던 리스트 제거
        $('.lunch_list_content').remove();

        for (var i=1; i<parseInt(page)+1; i++) {
            const jsonData = {
                latitude: latitude,
                longitude: longitude,
                page: i
            }

            $.ajax({
                type: "post",
                url: "/lunch",
                data: jsonData,
                dataType: "json",
                success: function (result) {
                    const lunchDiv = $('#lunch_list');
                    const resultList = Object.values(result)[0];

                    resultList.forEach(function (item) {

                        // 특정 카테고리 예외처리
                        if (checkCategoryName(item.category_name)) {
                            return;
                        }

                        const address = item.address_name;
                        const url = item.place_url;
                        const phone = item.phone;
                        const x = item.x;
                        const y = item.y;
                        const name = item.place_name;
                        const div = '<div class="lunch_list_content" ' + 'data-address=' + address + 'data-url=' + url + 'data-x=' + x + 'data-y=' + y + 'data-phone=' + phone + '>' + name + '</div>'
                        lunchDiv.append(div);
                    });

                    $('#lunch_recommend').hide();
                    $('#random_recommend').show();
                },
                error: function (e) {
                    alert("Fail");
                    console.log(e);
                }
            });
        }
    }


</script>
</body>
</html>
  • 맛집 추천이라는 버튼을 누르게 될경우 lunch_recommend 클릭 이벤트가 발생하여 현재위치의 위도,경도값을 가져온다.
  • 그 후 searchLunchRecommend 함수가 실행되며 lunch_list 라는 div 태그안에 현위치 근방의 음식점들이 노출되게 된다.
  • 설정이 필요한 부분은 src="//dapi.kakao.com/v2/maps/sdk.js?appkey={APPKEY}&libraries=services" 스크립트영역에 APPKEY를 넣어주면된다.
  • 크롬에서는 SSL 이 붙어있지않다면 현위치 조회가 불가하기 때문에 테스트는 다른 브라우저에서 해야한다.