Spring/๊ธฐ๋Šฅ ์ •๋ฆฌ

[Spring] - Kakao Maps Api๋กœ ํ˜„์žฌ ๋„๋กœ๋ช… ์ฃผ์†Œ ๋ฐ›์•„์˜ค๊ธฐ

Jwhy 2023. 9. 10. 00:24

๐Ÿ’จ ์š”์ฒญ ํ๋ฆ„

  1. JS๋กœ ํ˜„์žฌ ์œ„๋„, ๊ฒฝ๋„ ๋ฐ›์•„์˜ค๊ธฐ
  2. ๋ฐ›์•„์˜จ ๊ฐ’์„ BackEnd ์„œ๋ฒ„๋กœ ์ „๋‹ฌ
  3. Kakao Maps Api์— ์š”์ฒญ ๋ณด๋‚ด๊ธฐ
  4. ๋„๋กœ๋ช… ์ฃผ์†Œ ์ถœ๋ ฅํ•˜๊ธฐ

๐Ÿ—บ๏ธ ํ˜„์žฌ ์œ„๋„, ๊ฒฝ๋„ ๋ฐ›์•„์˜ค๊ธฐ

JavaScript์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ ์ค‘ geolocation์„ ์‚ฌ์šฉ

geolocation

์šฐ์„  geolocation์˜ ํ•จ์ˆ˜ ๋ชจ์–‘๋ถ€ํ„ฐ ์‚ดํŽด๋ณด์ž!

navigator.geolocation.getCurrentPosition(successFn, failedFn);

function successFn(position) {
    // ์œ„๋„
    const lat = position.coords.latitude;
    // ๊ฒฝ๋„
    const lng = position.coords.longitude;
    // ์‚ฌ์šฉ์ž ์ •์˜
}

function failedFn(positionError) {
    // ์‚ฌ์šฉ์ž ์ •์˜
}

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์„ฑ๊ณตํ–ˆ์„ ๋•Œ๋Š” position์„ ๋ฐ›์•„์™€ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์‹คํŒจํ•  ๊ฒฝ์šฐ positionError๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

๐Ÿ› ๏ธ ์ฝ”๋“œ ๊ตฌํ˜„

function setLocation() {
    navigator.geolocation.getCurrentPosition(function (position){
        const lat = position.coords.latitude;
        const lng = position.coords.longitude;
        $('#location').attr('value', lat + "," + lng);
    }, function (){
        Swal.fire({
            icon: 'question',
            html: '์œ„์น˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.<br>์œ„์น˜ ์ •๋ณด ํ—ˆ์šฉ์„ ํ•ด์ฃผ์„ธ์š”.',
        })
    });
}

form์— ์œ„๋„, ๊ฒฝ๋„์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์„œ ๋ณด๋‚ผ ์˜ˆ์ •์ด๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์ด input์— ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

์„ฑ๊ณต, ์‹คํŒจ์— ๋Œ€ํ•œ ํ•จ์ˆ˜๋Š” ๋”ฐ๋กœ ๋˜ ์‚ฌ์šฉํ•  ๊ฒƒ ๊ฐ™์ง„ ์•Š์•„์„œ ์ต๋ช…ํ•จ์ˆ˜๋กœ ๋Œ€์ฒดํ•ด ์‚ฌ์šฉํ–ˆ๋‹ค.

๐Ÿ•น๏ธ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ

Controller

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestBody;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class LocationController{

    private final KakaoMapsApiRestTemplate template;

    @PostMapping("/location")
    public String getLocation(@RequestBody Map<String, Object> datum) {
        String inputLocation = (String) datum.get("location");
        String locationAddressName = template.getLocationAddressName(inputLocation);
        return "...";
    }
}

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ form์˜ ๊ฐ’์„ json ํ˜•ํƒœ๋กœ ๋ฐ›์•„์˜ค๊ธฐ ์œ„ํ•ด Map<String, Object> ํ˜•ํƒœ๋กœ ๋ฐ›์•„์˜จ๋‹ค.
๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋Š” ์ œ์™ธํ•˜๊ณ  location๋งŒ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ด๊ธฐ ๋•Œ๋ฌธ์— Mapper๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๊ฐ€์ ธ์™€ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค!

RestTemplate

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Component
public class KakaoMapsApiRestTemplate {

    // properties์— ๋“ฑ๋กํ•ด๋†“์€ Kakao Rest Api Key
    @Value("${kakao.api.key}")
    private String REST_API_KEY;

    /**
     * ํ˜„์žฌ ์œ„์น˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค๊ธฐ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ
     * @param currentLat JS๋ฅผ ํ†ตํ•ด ๋ฐ›์•„์˜จ ์œ„๋„
     * @param currentLng JS๋ฅผ ํ†ตํ•ด ๋ฐ›์•„์˜จ ๊ฒฝ๋„
     * @return RestTemplate์„ ํ†ตํ•ด ๋ฐ›์•„์˜จ JSON(Map) ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
     * */
    public Map<String, Object> getCurrentPosInfo(String currentLat, String currentLng) {
        // ๋ฐ›์•„์˜จ ์œ„๋„, ๊ฒฝ๋„๋ฅผ ๊ฐ€์ง€๊ณ  KakaoMapsApi์— ์กฐํšŒ 
        String url = "https://dapi.kakao.com/v2/local/geo/coord2address.json?x={currentLng}&y={currentLat}";
        return getRestTemplateResult(url, currentLat, currentLng);
    }

    /**
     * Kakao Maps Api์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜
     * @param currentLat ์‚ฌ์šฉ์ž์˜ ์œ„๋„
     * @param currentLng ์‚ฌ์šฉ์ž์˜ ๊ฒฝ๋„
     * @return ์กฐํšŒ๋ฅผ ํ†ตํ•ด ๋ฐ›์•„์˜จ JSON(Map) ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
     * */
    public Map<String, Object> getRestTemplateResult(String url, String currentLat, String currentLng) {
        // Kakao Maps Api์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ RestTemplate
        RestTemplate restTemplate = new RestTemplate();

        // ์š”์ฒญ header์— Authorization : KakaoAK key๋ฅผ ๋‹ด์•„ ์š”์ฒญ
        HttpHeaders headers = new HttpHeaders();
        // KakaoAK ๋„์–ด์“ฐ๊ธฐ ์ฃผ์˜!!!
        headers.set("Authorization", "KakaoAK " + REST_API_KEY);

        // ์š”์ฒญ์„ ๋ณด๋‚ธ ๋’ค, ๋ฐ›์•„์˜จ ๊ฐ’์„ response์— ์ €์žฅ
        ResponseEntity<Map> response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), Map.class, currentLng, currentLat);
        return response.getBody();
    }

    /**
     * JSONObject ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜๋œ ๋ฐ์ดํ„ฐ ์ค‘์—์„œ address_name๋งŒ ๋ฐ›์•„์˜ค๋Š” ํ•จ์ˆ˜
     * @param json RestTemplate ์š”์ฒญ์„ ํ†ตํ•ด ๋ฐ›์•„์™€ ๋ณ€ํ™˜ํ•œ ๋ฐ์ดํ„ฐ
     * @return ์‚ฌ์šฉ์ž์˜ address_name์„ ๋ฐ˜ํ™˜
     * */
    public String getAddressName(JSONObject json) {
        JSONObject address = (JSONObject) json.get("address");
        return (String) address.get("address_name");
    }
}

์ฝ”๋“œ์˜ ๊ธธ์ด๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด JSONObject๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •๊ณผ ์ผ๋ถ€ ํ•จ์ˆ˜๋Š” ๋‹ด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

์œ„ ์ฝ”๋“œ์˜ ํ๋ฆ„๋Œ€๋กœ ์ง„ํ–‰๋˜๋ฉฐ, ํ˜„์žฌ ์‚ฌ์šฉ์ž์˜ ์œ„์น˜์˜ ๋„๋กœ๋ช… ์ฃผ์†Œ๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ˜„์žฌ ์ขŒํ‘œ์— ๋Œ€ํ•œ ์ฃผ์†Œ ๋ง๊ณ ๋„ ๋” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์ด ์žˆ์œผ๋‹ˆ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜๋Š”๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค!

๐Ÿค” ํšŒ๊ณ 

์ด์ „์— Kakao Maps Api๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์–ด๋ ต๋‹ค๊ณ  ๋А๊ปด์กŒ๋Š”๋ฐ, ์‹œ๊ฐ„์ด ์ง€๋‚˜ ๋‹ค์‹œ ์‚ฌ์šฉํ•ด๋ณด๋‹ˆ ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ต์ง€ ์•Š์€ ๋А๋‚Œ์ด ๋“ค์—ˆ๋‹ค.
์•„์ง์€ JSON ํ˜•ํƒœ๋ฅผ ๋ฐ›์•„์™€ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด ์ต์ˆ™ํ•˜์ง„ ์•Š์ง€๋งŒ, ๊ธˆ๋ฐฉ ๊ฐ์„ ์ตํž ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค!