나만의 주소 검색엔진 만들기 (고도화)

·2022년 10월 24일
0

삽질

목록 보기
9/11

점심까지만 해도 프로덕트에 넣으려고 AWS를 알아보고 있었는데, 2시간 30분의 회의 끝에
우리가 주소검증을 하지 않는게 맞다는 결론이 나면서 사실상 프로덕트에 올려볼 수 없게 됐다.

그런데 기왕 작업을 한거, 끝을 보고 싶었다.
외부 API를 호출하는 것보다 속도가 확실하게 빠르기 때문에, 이것은 충분히 작업해볼 가치가 있다고 느꼈다.

문제를 체크해보자.

현재 문제가 여러가지가 있었는데, 그것을 나열해보겠다.

  • 입력값과 출력값이 정확하게 일치해야 신뢰를 할 수 있다.
    • 무슨 문제가 있었냐면, 서울시로 입력을 하더라도 결과값은 서울특별시다.
      • 이것을 보정해주는 작업이 필요했다, 완벽하게 일치해야지만 신뢰를 할 수 있다.
  • 지번 주소와 도로명 주소의 구분이 필요하다.
    • 이것은 내가 ES를 제대로 다루지 못해서 벌어지는 일이겠지만, 정확해도 스코어가 2등인 경우가 발생했다.
      * 그래서 지번 주소와 도로명 주소를 명확하게 분리한 후,
      boosting을 통해 스코어를 올려주는 방식을 사용해야한다.
  • 만약 지번이름(도로명)과 지번 번호(도로명번호)가 붙어있을 경우 검증을 못한다.
    • 어떤 말이냐면 강남대로 1로 들어와야 정상처리가 되는데, 강남대로1로 들어올 때 검증에 실패했다.
      • 이유는 trim 단위로 검증을 하는데 한개로 붙어있으니까 인식을 못한거다..

그래서 지금 상태는 어느정도 진행?

원래 집와서 쉴라고 그랬는데 어떻게든 완성을 하고 싶어서 계속 작업을 했다(...)

광역시, 특별시, 자치시를 보정하자.

이 부분은 그렇게 어렵지 않았다. 코드가 더럽긴한데...

작동을....해야지....ㅠㅠ

근데 헷갈리는게 있었다..

광주는 경기도 광주시와 전라남도 광주광역시로 구분이 되어있는데.....

이 두개를 구분하는게 조금 애를 먹었지만, 해결했다.

전라남도 광주광역시같은 경우는 5구의 하위 행정구역으로 구성되어있다.
동구, 서구, 남구, 북구, 광산구

즉 상단의 5개 구가 아닌 주소라면 경기도 광주시라는 것이고
반대로 상단의 5개의 구 중 한개라도 속한다면 해당 주소는 광주광역시라는 의미다.

그래서 겁내 더러운데 원하는 결과는 뽑아낼 수 있었다.

  private updateAddress(address: string[]): string {
    if (address[0].match('경기') !== null) {
      address[0] = '경기도';
    } else if (address[0].match('서울') !== null) {
      address[0] = '서울특별시';
    } else if (address[0].match('대전') !== null) {
      address[0] = '대전광역시';
    } else if (address[0].match('인천') !== null) {
      address[0] = '인천광역시';
    } else if (address[0].match('부산') !== null) {
      address[0] = '부산광역시';
    } else if (address[0].match('울산') !== null) {
      address[0] = '울산광역시';
    } else if (address[0].match('세종') !== null) {
      address[0] = '세종특별자치시';
    } else if (address[0].match('광주') !== null) {
      const isGwangju_Metropolitan_City = address.some((val) => {
        return val === '광산구' || '북구' || '서구' || '동구' || '남구';
      });
      isGwangju_Metropolitan_City ? (address[0] = '광주광역시') : (address[0] = '광주시');
    }
    return address.join(' ');
  }

지번 주소와 도로명 주소의 구분을 하자.

이거 정말 고민하고 있었는데, 아는 분께서 정말 좋은 사진을 주셔서 생각보다 금방 해결했다.

지번주소에는 무조건 혹은 가 들어간다.
들어가지 않는다면 모조리 도로명주소다.

    const isZibun = address.some((val) => {
      return val[val.length - 1] !== '동' || '리';
    });

    let boosting = '';

    if (isZibun) {
      boosting = 'doro_address';
    } else {
      boosting = 'zibun_address';
    }

    const document = await this.elasticsearchService.search({
      index: 'address',
      size: 1,
      query: {
        multi_match: {
          query: address,
          type: 'cross_fields',
          operator: 'OR',
          fields: [boosting],
        },
      },
    });

사실 부스팅은 필드에 ^2같은 식으로 해당 필드에 가중치를 주는 것을 이야기한다.

=> https://kazaana2009.tistory.com/6

그런데 지번주소인지 도로명주소인지 확인을 했다면, 필드에 가중치를 주는 것이 아니라
해당 필드를 기준으로만 조회를 하는 것이 더 정확하다.

그래서 지번과 도로명 여부를 확인한 후 부스팅에 해당 정보를 넣고 조회하는 것으로 방향을 틀었다.

건물정보 혹은 동,리 + 숫자가 붙어있는 것을 분리하자.

이건 아직 해결 못했다, 오늘 진짜 집와서 쉰다 했는데 하나도 못 쉬어가지고... 이거 그냥 누구한테 물어볼까싶다 ㅠ

택배사 주소검증 API에서도 확인을 해봤는데

숫자와 문자를 기반으로 구분을 명확하게 하는 것 같다.

예를 들어서 ~ 번길 같은 도로명 주소같은 경우에는 ~번길 앞에 무.조.건 숫자가 들어가야한다.
~로 같은 도로명 주소 같은 경우에는 ~로 앞에 숫자가 들어가면 에러가 발생한다.

즉 어떻게봐도 정규식을 통해서 해당 주소의 정보를 검증하는 것으로 추측이 가능한데

똑같이 만들려고 했더니 내가 정규식 짜는 실력이 너무...모자르다ㅠㅠ

그렇지만 어떻게 짜야할지는 확실하게 알 것 같다.

  • 도로명주소같은 경우에는 혹은 뒤에 건물 번호가 붙는다.
    • 그 뒤에 건물 부번이 존재할 경우 하이픈이 붙지만, 절대로 한글이 붙을 순 없다.
  • 지번주소같은 경우에는 혹은 뒤에 지번 번호가 붙는다.
    • 도로명과 마찬가지로 건물 부번이 존재할 경우 하이픈이 붙지만, 절대로 한글이 붙을 수 없다.

그래서 지금 필요한게 뭐냐면

  1. , , , 다음 문자가 숫자인 것을 판별하는 정규식 1개
    왜냐하면 붙어있을 경우 띄어쓰기를 해야한다(ㅠㅠ)

아니 이게 왜 도대체 붙어서 오는건데 진짜 이해를 못하겠네

  1. 건물 번호 & 지번 번호 뒤로 모든 값을 날려버릴 수 있는 정규식 1개

대충 낙성대로 18-15 빛나는 아파트 102동 195호라고 치면

낙성대로 18-15 / 빛나는 아파트 102동 195호 이렇게 번호 뒤를 분리할 수 있는 정규식이 필요하다.

숫자로 구성되어있고, 하이픈이 들어갈 수 있으며, 하이픈이 들어가면 숫자가 존재한다. 라는 기준으로 짜면 될 것 같은데.....

건물 본번은 최대 5자리 건물 부번은 최대 4자리
지번 본번은 최대 4자리 지번 부번은 최대 4자리다.

....주소가 이렇게까지 숫자를 늘려야할 정도로 많은건가? 진짜 미친듯이 많네(...)

아무튼 내일 저 정규식만 짜면...사실상 음........ 모르겠다 젠장

벌써 23시 56분이네ㅠ

profile
물류 서비스 Backend Software Developer

0개의 댓글