컬리가 약 10개월에 걸쳐 주소정제 서비스를 내재화한 여정의 마지막화다. 외부 업체 API 호출을 전체의 1% 미만으로 줄여 2024년 9월 30일 계약을 종료했고, 마지막까지 남은 지번 주소와 LOW 레벨 주소 두 케이스를 처리한 방법과 프로젝트 회고를 담는다.
핵심 포인트- 외부 호출을 1% 미만으로 줄이고 2024-09-30 외부 업체 계약을 종료했다.
- 남은 지번 주소 요청(하루 약 20건)은 행안부 도로명주소 조회 API로 우회했다.
- LOW 레벨(철거 건물·행정구역 변경)은 변경 이력 DB를 만들어 해결했다.
- 최종 버전은 2024년 8월 배포, 이후 2달간 외부 인터페이스 없이 운영하며 검증했다.
- 두 DB 어디에도 없는 주소만 처리 불가로 응답하며, 정상 주소를 오분류한 사례는 없었다.
상세 정리- 지번 배경: 지번 주소 요청은 하루 20건 수준으로 줄어, 별도 지번 DB 구축은 과설계로 판단했다.
- 지번 해결: 요청을 AddressSearchParam으로 변환하고 isJibunAddress()/isRoadAddress() getter로 유형을 구분, 지번이면 행안부 도로명 조회 API로 건물관리번호를 얻어 내부 건물 DB를 조회한 뒤 도로명 처리 로직을 태운다.
- 지번 결과: 현재까지 문제없이 동작한다.
- LOW 케이스1(철거): reasonCode=63인 철거 예정 건물은 외부 호출하면 안 된다. 외부 업체의 오래된 응답으로 배송기사가 없는 건물을 찾아가 배송 실패가 날 수 있어서다.
- LOW 케이스2(행정구역 변경): 동탄2신도시 도로명 변경(동탄대로→동탄역로)이나 관할 개편처럼 시민이 앱 주소를 곧바로 갱신하지 않는 경우다.
- LOW 해결: OMS 일배치로 기준 대비 속성 변경을 감지해 이전 값을 변경 이력 DB에 저장한다. 기본 건물 DB 조회 실패 시 이력 DB에서 건물관리번호를 꺼내 현재 기준으로 정제한다.
- 과거 이력 보완: 구현 이전의 변경분은 기록이 없어, 백오피스로 이력을 수동 추가·수정·삭제했다. 하루 1~2건씩 3개월 처리하니 양이 줄었다.
- 예외 처리: 두 DB 모두에 없는 주소만 처리할 수 없는 주소 예외를 던진다. 정상 주소를 오분류한 케이스는 관측되지 않았다.
- 검증: 8월에 정상 주소가 외부 호출을 유발하는지 감사, 9월에 외부 인터페이스를 완전히 제거하고 안정성을 관찰했다. 2달간 무결.
- 회고(아쉬움): 건물 DB를 먼저 구축했다면 개발이 빨랐을 것, 저빈도 엣지 케이스를 허용 실패 기준 정의보다 먼저 쫓은 점, 서버 로그 수동 검증이 번거로웠고 지도 기반 백오피스가 대응력을 바꿨다.
- 회고(성공): 단독·복합 건물 로직 초기 분리, 1588-0061(7자리 도로명 안내) 활용, LOW/HIGH 정확도 레벨 도입, 업체를 능가하는 기능 구현, 90% 감축 후에도 남은 10%까지 밀어붙인 점.
- 성과 정의: 90% 감축에서 멈추지 않고 남은 10%인 지번·LOW 케이스까지 해결해 외부 호출을 1% 미만으로 낮춘 것이 계약 종료의 근거가 됐다.
왜 읽나외부 벤더 API를 내재화해 완전 대체하려는 백엔드 엔지니어에게 마지막 10% 엣지 케이스 처리와 계약 종료 검증 절차의 실전 레퍼런스.