pile·
백엔드·마켓컬리마켓컬리 Hello World·

주소정제 서비스 내재화 - 5화 ( 어질어질한 변화구들 )

컬리 주소정제 내재화 시리즈 5화로, 2024년 1~3월 복합 건물(아파트·다세대) 정제를 다룬다. 단독 건물은 대부분 해결됐지만 트래픽의 약 40%가 여전히 외부 API를 타고 있어 복합 건물 해결이 필요했고, 정확도 레벨 Enum 체계와 상세 건물 추출 로직으로 EXACT 99.2%를 달성한 과정을 정리한다.

핵심 포인트
  • 복합 건물은 동·호 상세 정보가 필요해 단독 건물보다 훨씬 어렵다.
  • 정제 결과를 EXACT/HIGH/MODERATE/MEDIUM/LOW/BAD/NONE 7단계 Enum으로 분류해 관리했다.
  • HIGH는 옆 단지 동을 찾는 케이스로, 건물ID 앞 14자리와 단지명 토큰화로 관련 건물을 탐색한다.
  • MEDIUM(변화구)은 이백팔동·2o8동 같은 고객 입력 변형이라 개발 시간이 가장 많이 들었다.
  • 2025-01-14 기준 주문의 99.2%가 EXACT로 정제됐고, 복합 건물 내재화로 월 약 35만원을 절감했다.
상세 정리
  • 난이도: 단독 건물은 기본 주소만으로 위치를 특정하지만 복합 건물은 정확한 동 정보가 필요하다. 상세주소는 자유 입력이라 208 5101, 이백팔동 오천백일호, 2o8-5oo1호 등 형식이 제각각이다.
  • 목표 재설정: 같은 단지에서 208동 대신 201동 좌표를 줘도 위경도·건물ID 3개만 다르지만, 새벽 배송 오배송·불가지역 폴리곤 판정 오류를 유발한다. 외부 업체도 자주 상세 건물 추출에 실패해 목표를 외부 업체 이상으로 정제로 잡았다.
  • Enum 도입: EXACT(같은 단지 동 추출), HIGH(옆 단지 동), MODERATE(상세 조회 불필요-대형병원·대학), MEDIUM(행안부 DB 오류 의심), LOW(기본주소 변경·철거), BAD(고객 입력 오류), NONE(서버에러 실패)로 이슈를 체계적으로 관리했다.
  • BAD: 동 번호 누락 케이스로 하루 약 100건, 100% 배송 실패라 Slack 알림으로 즉시 감지 후 CS가 취소·재주문을 유도한다.
  • HIGH(정제의 꽃): 고른 단지에 대상 동이 없으면 인접 단지에 있는지 묻는다. 압구정 현대14차(203~206동)에 208동 입력 시 208동이 있는 현대13차로 기본주소를 재정제한다. 주소 선택 팝업이 동 구분 없이 단지명을 보여줘 오선택이 발생하며, 하루 약 150건이다.
  • HIGH 탐색 시행착오: 같은 우편번호 범위는 실패(범위 과대), 같은 전체 도로코드 범위도 실패, 반경 200~300m는 보수적으로 임시 성공, 최종 채택은 건물ID 앞 14자리와 단지명 토큰화다.
  • 건물ID: 25자리 구조로 행정구역이 바뀌어도 불변이고 중복이 없다. 14자리 접두어는 문서 근거 없이 13·15자리 실험 끝에 경험적으로 최적으로 확정했다.
  • 관련 건물 채택 조건: 기본 주소와 관련 건물 모두로 조회해 정확히 1개 상세 건물이 잡힐 때만 인정한다. 다중 매칭은 사람 판단이 필요하다.
  • MEDIUM(변화구): 행안부 208동 대 고객 이백팔동·2.0.8동·2o8(O를 0으로). 행안부 DB에 상세 건물 누락·단지 내 208동 중복도 존재한다. 배송 실패는 적지만 GPS 핀 오배치·폴리곤 정밀도 실패가 남아 지속 패치하며, 하루 300~400건이다.
  • 상세 건물 추출 3단계: 전처리 없이 고객 입력 건물명이 행안부 DB와 정확히 1개 매칭되는지 확인(1002호 102동 역순, 드림디포 1층 등), 실패 시 양쪽에 전처리 로직 적용, 처리 후 정확히 1개 매칭을 검증한다.
  • 전처리: 지역별로 (푸르지오)103동부터 103까지 표기가 달라, A동/가동 같은 영문·한글 동 표기(MEDIUM의 약 5%)를 숫자 표준형으로 통일해 모호성을 제거한다.
  • 숨은 MVP: OMS 백오피스 건물 관리(기본주소·건물ID·배송요청번호 조회, 좌표 드래그 조정, 반경 인접 건물 시각화, 이력 조회·수동 입력, 캐시 일괄 삭제). 비개발 CS가 직접 주소 교정에 참여했다.
왜 읽나자유 입력 한글 주소를 파싱해 아파트 동·호까지 정제하는 지오코딩·주소 정규화 엔지니어에게 정확도 레벨 설계와 퍼지 매칭 실전 사례.
마켓컬리
마켓컬리 Hello World 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·github-engGitHub Engineering·

    조기 종료를 없애야 벡터화된다 — 메모리 속도 소스 코드 케이스 폴딩

    GitHub의 코드 검색 엔진 Blackbird는 480TB 이상의 소스 코드를 인덱싱하기 전 모든 바이트에 case folding을 적용한다. 이 글은 Rust로 구현한 case folding을 메모리 대역폭 한계(45+ GiB/s)까지 끌어올린 두 가지 반직관적 최적화를 상세히 다룬다. 핵심은 루프 조기 종료(break) 제거로 LLVM 벡터화를 유도하고, UTF-8을 디코딩하지 않고 바이트 공간 산술만으로 fold를 수행하는 것이다.

    #rust#unicode#simd+2
  2. 백엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    트랜잭션 스크립트에서 숙소 메타 + 가격 계산 모듈로 — 전시 아키텍처 개선기 (2/3)

    여기어때 전시개발팀이 숙소 상세(PDP) API를 해부한 결과, 코드상으로는 DB 호출 3번처럼 보이던 요청이 실제로는 MongoDB $lookup 체인으로 컬렉션을 19회 접근하는 구조였다. 이 트랜잭션 스크립트 방식의 핵심 문제는 "aggregation이 I/O를 가린다"는 점으로, 독립적인 쿼리 10개가 단일 파이프라인에 직렬화되어 병렬화 기회를 잃고, 가격 때문에 거의 안 바뀌는 이미지까지 매 요청마다 읽어야 하는 읽기 증폭이 발생했다. V3에서는 "조회 시점 조립"을 "쓰기 시점 사전 조립"으로 전환하고, 화면별로 복제되던 가격 계산 로직을 goodsprice 단일 모듈로 수렴했다. 4개 API(PLP/PDP/RDP/ILP)의 반복 마이그레이션은 Claude Code skill로 절차를 고정하고 쉐도잉 + 동일성 검증으로 안전망을 마련하는 방식으로 진행됐다.

    #architecture#migration#caching+2