danc
danc*dev
danc
  • 분류 전체보기
    • codestates_BE_bootcamp39
      • 주단위 일기
      • 회고
    • programming
      • JAVA
      • SPRING
      • GENERAL
      • LINUX
      • ALGORITHM
      • ERROR_HANDLING
    • web
      • NETWORK
      • DB
      • HTML
      • CSS
    • kr
    • nz

최근 글

인기 글

태그

  • AOP
  • 일기
  • React에서 Authorization헤더
  • 윈도우 11 우분투
  • 코드스테이츠 백엔드
  • TIL 일기
  • TIL일기
  • css
  • HTTP
  • TIL
  • 회고
  • 코드스테이츠

최근 댓글

티스토리

hELLO · Designed By 정상우.
danc

danc*dev

재미있었던 외부 API 도입 feat. Kakao API
codestates_BE_bootcamp39/회고

재미있었던 외부 API 도입 feat. Kakao API

2022. 10. 7. 17:39

해당 글은 코드 스테이츠 개인 기술 회고를 하면서 작성함 


위치 서비스를 구현해야 하는 만큼 사용자의 위치 정보를 얻어야 하는 점이 이번 프로젝트의
critical task 중 하나였습니다.

 

처음 위치정보를 어떤 식으로 받아와야 하는 것에 대해 막연하게
“그거 그냥 카카오나 네이버 지도 api” 쓰면 될 것 같은데라고 생각하였지만
“어떻게?”라는 관점에서 보니
정말 막막하였습니다.


1. 사용자 IP로 위치정보 받아오기

처음에는 IP로 확인을 하면 되지 않을까 해서 찾아본 결과, MaxMind회사의 GeoLite2라는
api를 사용하면 도시정보를 받아볼 수 있다는 걸 알게 되어 바로 도입을 해보았습니다.

GeoLite2는 큰 그림에서 봤을 때 접속자의 IP를 토대로 GeoLite2 DB상에 저장된 도시정보를
반환하는 형식이었습니다.

DB(.mmdb)를 프로젝트 폴더 내에 위치시키고 읽어오는 형식으로 구현

 

따라서 실 사용자의 IP를 추적하는 것이 필요했습니다.
이는 HttpServletRequest의 getRemoteAddr()를 사용하면 손쉽게 가능할 줄 알았으나
실 사용자가 아닌
프록시나 로드 밸런서의 IP 주소를 받는 경우가 많습니다.

따라서 구글링 후, 하단의 코드를 추가하여 여러 중개 서버를 고려한 실제 클라이언트 ip주소를
받을 수 있도록
하였습니다.

더보기
@Transactional
    public String getRemoteIP(HttpServletRequest request) {

        String ip = null;
        ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-RealIP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("REMOTE_ADDR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

Ip자체를 받는 것에는 이상이 없었으나, 문제는 도시 정보가 “영문”으로 반환된다는 점과
반환된 주소의 정확도가 꽤나 떨어진다는 문제가 있었습니다. (예: 부천인데 화성으로 표시)

Ip주소로 도시이름, 위도, 경도 추출

 


2. 위/경도 값으로 위치정보 받아오기


이대로는 실제 서비스 시 무리가 올 것이 분명하기 때문에 고민 끝에 kakao api를 사용해보기로
결정했습니다. 저희는 위/경도 나 ip 주소를 실제 도시 정보로 반환받길 원했기 때문에 kakao api의
“Reverse GeoCoding”이라는 기술이 적합했습니다.

다만 상기 api는 위도 / 경도를 요청으로 보내야 하기 때문에 우리 측에서 위/경도 값을 먼저
갖고
있어야 합니다. 이를 위해 프론트 분들께 GeoLocation을 사용하여 위/경도 값을 받고
서버 쪽으로 보내달라고
요청했습니다.

카카오 API - Reverse GeoCoding을 사용하면 보낸 위/경도 값으로 해당 지역 정보를 한글로 상세하게
반환받을 수 있습니다. (JSON 형태로 String값 반환)

"documents": [
    {
      "address_name": "전북 익산시 부송동 100",
      "y": "35.97664845766847",
      "x": "126.99597295767953",
      "address_type": "REGION_ADDR",
      "address": {
        "address_name": "전북 익산시 부송동 100",
        "region_1depth_name": "전북",
        "region_2depth_name": "익산시",
        "region_3depth_name": "부송동",
        "region_3depth_h_name": "삼성동",
        "h_code": "4514069000",
        "b_code": "4514013400",
        "mountain_yn": "N",
        "main_address_no": "100",
        "sub_address_no": "",
        "x": "126.99597295767953",
        "y": "35.97664845766847"
      },
      "road_address": {
        "address_name": "전북 익산시 망산길 11-17",
        "region_1depth_name": "전북",
        "region_2depth_name": "익산시",
        "region_3depth_name": "부송동",
        "road_name": "망산길",
        "underground_yn": "N",
        "main_building_no": "11",
        "sub_building_no": "17",
        "building_name": "",
        "zone_no": "54547",
        "y": "35.976749396987046",
        "x": "126.99599512792346"
      }
    }

 

반환 형식은 도로명주소 + 일반 주소로 이루어져 있는데 도로명 주소가 없으면
일반 주소에서
찾도록 하였고, 저희는 상세 지역정보가 아닌 “시” 단위의 정보가 필요했기에
반환 형식에서의
“region_2 depth_name “ 부분만 필요했습니다.

따라서 구글링을 토대로 JSONObject와 JSONArray클래스를 사용해 해당 부분을 구했습니다.

예외적으로, “서울”은 "region_1 depth_name"으로 반환되기 때문에 위의 방식대로 한다면
“xx구“라고
반환이 됩니다. 따라서 먼저 서울이라는 문자열이 있는지 판단하고 만약 서울이라면
바로 “서울”을 string에 담아 반환하도록 하였습니다.

***
//서울로 시작하면 바로 반환
	if("서울".equals((String)address.get("region_1depth_name"))){
          return "서울"; } 
          else {
                    value = (String) address.get("region_2depth_name");
                }
***


이후로 위치정보를 사용자 entity에 저장하여 활용할 수 있게 되었습니다.


추가적으로 내 주변의 스터디를 파악해야 하기 때문에 위 / 경도 값을 계산하여 반경 3KM 내

존재하는 스터디(스터디장의 위치정보)를 리스트로 반환하도록 하였습니다.

해당 위경도 간 계산 부분은 같은 백엔드 팀원께서 구현을 도와주셨습니다.


결론

우여곡절이 많았고 쉽지 않았지만 처음으로 외부 api를 사용해보았다는 점에서 스스로 의미가 있었다고
생각합니다. 또한, 하면서 원하는 결괏값을 얻을 수 있었기 때문에 개인적으로 재밌게 구현할 수 있었고
추후에 다른 프로젝트를 하게 되더라도 기꺼이 도입해볼 수 있겠다는 자신감도 얻었습니다.

 

전반적인 코드는 아래의 블로그를 참고하였습니다.

 

[Java] Kakao map 카카오맵 로컬 API 좌표(경도, 위도)로 주소 변환하기(REST API)

안녕하세요 애리몽입니다. 오늘은 좌표를 이용하여 주소를 가져오는 카카오맵 로컬 API를 사용하면서 삽질했던 부분들 정리 해보려고 합니다. 좌표-주소 변환 특정 좌표의 지번 주소 및 도로명

developerjal.tistory.com

 

저작자표시 (새창열림)

'codestates_BE_bootcamp39 > 회고' 카테고리의 다른 글

Pre-Project 돌아보기  (2) 2022.09.10
Section 4 돌아보기  (2) 2022.08.18
Section 3 돌아보기  (2) 2022.07.20
Section 2 돌아보기  (0) 2022.06.22
Section 1 돌아보기  (6) 2022.05.23
    'codestates_BE_bootcamp39/회고' 카테고리의 다른 글
    • Pre-Project 돌아보기
    • Section 4 돌아보기
    • Section 3 돌아보기
    • Section 2 돌아보기
    danc
    danc
    Backend 개발자를 목표로 공부 중 입니다.

    티스토리툴바