> ## Content Index
> Fetch the complete content index at: https://www.popit.kr/llms.txt
> Use this file to discover other available public pages before exploring further.

# AI로 장소 검색 서비스 만드는 중입니다 (기술 8) — 기각의 박물관: 좋아 보였지만 데이터가 버리게 한 것들
- URL: https://www.popit.kr/ai-place-search-tech-8-museum-of-rejected-ideas/
- Published: 2026-08-09T23:50:51.000Z
- Updated: 2026-08-09T23:50:51.000Z
- Author: 김형준
- Tags: ai, 검색, #서비스소개, 유추카, LLM

![t8-rejected](https://www.popit.kr/content/images/wp/2026/07/t8-rejected-600x282.png)

이 연재의 숨은 주제는 **"직관은 자주 틀린다"** 였습니다. 기술 7편의 평가 인프라가 걸러낸 실패들을 한자리에 모았습니다. 그냥 나열하지 않고 **왜 그렇게 믿었는지**까지 적었습니다 — 실패의 값어치는 결과가 아니라 **어디서 논리가 꺾였는지**에 있으니까요.

## 들어가며 — 기각을 기록해야 하는 이유

성공한 개선은 코드에 남습니다. 코드를 보면 뭘 했는지 알 수 있죠. 그런데 **기각된 시도는 아무 데도 안 남습니다.** 코드에도 없고, 기억에서도 반년이면 사라집니다.

그러면 어떻게 되냐면 — **같은 아이디어를 다시 냅니다.** "리랭커 점수로 순위를 매기면 좋지 않을까?" 이 생각은 정말 그럴듯해서, 잊어버리면 반드시 다시 떠오릅니다. 그리고 다시 이틀을 씁니다.

그래서 기각을 남깁니다. 각 전시물마다 **① 왜 그럴듯했나 ② 실제 결과 ③ 왜 틀렸나 ④ 무엇을 배웠나**를 적었습니다.

박물관을 돌다 보면 실패들이 **네 개의 방**으로 묶인다는 걸 알게 됐습니다.

---

# 제1전시실 — "정보를 더 넣으면 좋아진다"

가장 많이, 가장 크게 틀린 가정입니다. 신호를 하나 더 넣으면 검색이 똑똑해질 것 같지만, 실제로는 **기존 신호를 망가뜨리는** 경우가 훨씬 많았습니다.

## 1\. 피처 가중치 상향 (기각)

**왜 그럴듯했나** — 유추카는 장소마다 구조화된 피처(뷰·시설·분위기)를 갖고 있습니다. 임베딩 코사인만 쓰지 말고 이 피처 점수를 섞으면, "정보가 더 많으니" 더 정밀해질 것 같았습니다.

**결과** — 순수 코사인이 모든 혼합 조합을 이겼습니다.

| 방식            | 성능            |
| ------------- | ------------- |
| **순수 cosine** | **0.464**     |
| 피처 혼합 (여러 비율) | 0.365 → 0.296 |

**왜 틀렸나** — 이유가 예상 밖이었습니다. 피처를 섞자 **코사인 점수의 간격이 0.040에서 0.008로 압축**됐습니다. 원래 1등과 10등 사이에 0.04의 차이가 있었는데, 다른 신호가 섞이면서 그 차이가 5분의 1로 눌린 겁니다.

**순위를 매기려면 점수가 벌어져야 합니다.** 모두가 비슷한 점수를 받으면 순서는 사실상 무작위가 됩니다. 정보를 더한 게 아니라 **해상도를 지운** 셈이었습니다.

**배운 것** — 신호를 섞을 땐 "정보량이 느는가"가 아니라 **"변별력이 유지되는가"** 를 봐야 합니다. 피처는 정렬 점수에 안 섞고 **하드게이트(있다/없다)** 로만 쓰기로 했습니다.

## 2\. 리랭커에게 근거 문장을 함께 주기 (기각)

**왜 그럴듯했나** — 리랭커가 "이 장소가 이 검색어에 맞나"를 판정할 때, 관련 리뷰 문장을 뽑아서 같이 보여주면 판단이 좋아질 것 같았습니다. 근거를 주는데 나빠질 리가 없어 보였죠.

**결과** — **두 지표가 동시에 나빠졌습니다.** 이건 드문 일입니다.

|                  | 전     | 후           |
| ---------------- | ----- | ----------- |
| capped Recall@10 | 82.7% | **78.4%** ↓ |
| 오탐 위반            | 42    | **49** ↑    |

보통은 하나가 오르고 하나가 내립니다(정밀도-재현율 교환). 둘 다 나빠졌다는 건 **개입 자체가 해로웠다**는 뜻입니다.

**왜 틀렸나** — 두 가지가 겹쳤습니다.

첫째, **오답에게도 근거가 공급됐습니다.** 발췌는 키워드로 뽑았기 때문에, 정답이 아닌 장소에서도 검색어와 글자가 겹치는 문장이 뽑혀 나왔습니다. "여긴 스페셜티는 아니지만"이 근거로 제출되는 거죠. 리랭커는 근거가 있으니 적합 쪽으로 기울었고, 오탐이 늘었습니다.

둘째, **발췌가 프롬프트를 통째로 교란했습니다.** 문장이 추가되면서 프롬프트 구조가 바뀌었고, 발췌와 무관한 다른 쿼리들의 판정까지 흔들렸습니다.

**배운 것** — **근거는 중립적이지 않습니다.** 정답과 오답 모두에게 같은 방식으로 근거를 주면, 판정을 돕는 게 아니라 **오답을 변호**하게 됩니다. 재시도한다면 키워드가 아니라 **의미(벡터) 기반 선별**과, **적합 판정 방향으로만 비대칭 설계**가 필요합니다.

## 3\. 사진으로 판정하기 (데이터는 남기고, 검색 소비는 전량 기각)

**왜 그럴듯했나** — 이건 꽤 큰 투자였습니다. **4,817곳의 사진을 비전 모델로 태깅**했습니다. 야간 사진 692곳, 한옥 건물 272곳 같은 식으로요. 리뷰 텍스트가 놓치는 걸 사진은 잡을 테니, "야경 좋은 곳" 검색의 재현율을 크게 올릴 거라 기대했습니다.

**결과** — 검색에 쓰는 모든 방법이 실패했습니다.

- **게이트에 OR로 추가** → 구제된 정답 **0건**, 되살아난 오답 **+1\~5건**
- **리랭커 프롬프트에 병기** → 효과 입증 불가 (측정 요동보다 작음)

**왜 틀렸나** — 한 문장으로 요약됩니다. **"밤에 찍은 외관 사진"과 "야경 명소"는 다릅니다.**

비전 모델은 "이 사진이 밤에 찍혔다"를 정확히 맞혔습니다. 문제는 그게 우리가 알고 싶은 것이 아니었다는 겁니다. 야경 명소는 "그 장소에서 야경이 보이는 곳"이지 "밤에 사진이 찍힌 곳"이 아닙니다. **모델은 정확했고, 우리가 잘못된 질문을 데이터로 만든 겁니다.**

**배운 것** — 새 데이터 축을 만들 때는 **"이 데이터가 정확한가"** 보다 **"이 데이터가 내 질문에 답하는가"** 를 먼저 확인해야 합니다. 정확한 오답은 부정확한 정답보다 위험합니다 — 데이터가 깨끗해 보이니 의심을 안 하게 되거든요.

한편 태깅한 사진 데이터는 **지우지 않고 자산으로 남겼습니다.** 나중에 다른 질문(예: 실내/실외 판별)엔 맞을 수 있으니까요. **기각은 데이터가 아니라 용법에 대한 판정입니다.**

---

# 제2전시실 — "더 똑똑한 모델이면 이긴다"

두 번째로 자주 틀린 가정입니다. LLM은 강력하지만, **강력한 것과 이 일에 맞는 것은 다릅니다.**

## 4\. 로컬 LLM으로 순위 재정렬 (기각)

**왜 그럴듯했나** — 가장 크게 기대했던 시도입니다. 코사인 유사도는 결국 벡터 산수인데, 문장을 읽는 LLM이 다시 매기면 당연히 좋아질 것 같았습니다.

**결과** — 온라인에 쓸 수 있는 로컬 모델 중 **코사인을 이긴 게 하나도 없었습니다.**

| 리랭커                   | nDCG@10   | vs cosine              |
| --------------------- | --------- | ---------------------- |
| **cosine 순위만 (기준)**   | **0.552** | —                      |
| qwen3:14b             | 0.541     | −0.011                 |
| qwen3:8b / gemma3:12b | 0.540     | −0.012                 |
| exaone3.5:7.8b        | 0.462     | −0.090                 |
| qwen3:30b             | 0.594     | +0.042 (20초·18GB — 실격) |

**왜 틀렸나** — LLM은 "이게 적합한가"라는 **이분 판정**은 잘합니다. 그런데 "3등과 7등 중 뭐가 더 적합한가"라는 **미세한 서열**은 못 매깁니다. 순위표를 통째로 주고 재배열시키면, 잘 매기던 부분까지 흔들어 놓습니다.

유일하게 이긴 30B는 20초에 18GB라 온라인 검색엔 못 씁니다. **"이길 수 있다"와 "쓸 수 있다"는 다른 문제**였습니다.

**배운 것** — 리랭커의 역할을 **재정렬에서 "부적합 컷 + 이유 생성"으로 축소**했습니다. LLM에게 잘하는 일만 시키는 원칙이 여기서 나왔습니다. (상세: 기술 1편)

## 5\. 리랭커가 매긴 점수로 순위 재계산 (기각)

**왜 그럴듯했나** — 4번을 반성한 뒤의 재시도입니다. "순위표를 통째로 재배열하는 게 문제라면, 리랭커가 장소마다 매긴 **점수**만 받아서 그걸로 정렬하면 되지 않을까?"

**결과**

| 방식                | capped Recall@10 |
| ----------------- | ---------------- |
| 기준선               | 28.5%            |
| LLM 점수 단독 정렬      | 25.3% (−3.2p)    |
| 기존 점수 × LLM 점수 결합 | 23.3% (−5.2p)    |

**섞었을 때 더 나빴다**는 게 인상적입니다. 좋은 신호에 나쁜 신호를 섞으면 중간이 되는 게 아니라, 나쁜 쪽으로 끌려갑니다.

**왜 틀렸나** — 4번과 같은 이유입니다. **LLM이 뱉는 점수는 판정의 부산물이지 서열이 아닙니다.** 0.8과 0.85 사이에 의미 있는 차이가 없습니다. 그 차이로 정렬하면 노이즈로 정렬하는 것과 같습니다.

**배운 것** — **LLM은 컷과 이유 생성에만, 순위는 결정적 점수로.** 두 번 시도해서 두 번 다 같은 자리에서 꺾였다는 건, 이게 우연이 아니라 성질이라는 뜻입니다.

## 6\. 상위 모델로 리랭크 (기각)

**왜 그럴듯했나** — `gemini-2.5-flash`. 이름에 `flash-lite`보다 상위 티어가 붙어 있으니 더 나을 것 같았습니다.

**결과** — **약 9.8초로 4\~6배 느렸고**, 품질은 동등했습니다. 게다가 thinking 모드가 출력 토큰을 잠식해서 **검색 이유가 빈 값으로 돌아오는** 사고까지 났습니다. 비싸고(출력 $2.50) 느린데 불안정.

**왜 틀렸나** — 모델 티어는 **추론 난도**에 대한 것이지 **이 작업에 대한 적합도**가 아닙니다. 리랭크는 짧은 판정을 대량으로 하는 일이라 지연이 곧 품질인데, 상위 모델은 정확히 그 축에서 나빴습니다.

**배운 것** — **기능마다 모델을 따로 고른다.** 이름값이 아니라 그 기능의 지배 요인(여기선 지연)으로. (상세: 기술 2편)

## 7\. 컨셉 점수로 임베딩 대체 (기각)

**왜 그럴듯했나** — LLM이 매긴 188개 컨셉 점수가 하드게이트로 P@8을 29% → 100%로 올렸습니다(기술 4편). 그렇게 좋다면 **임베딩 없이 컨셉만으로 1차 검색**을 해도 되지 않을까?

게다가 초기 측정에서 **컨셉이 임베딩을 이겼습니다** — 컨셉 0.965 vs 임베딩 0.881.

**결과** — 새 정답셋에서 완전히 뒤집혔습니다.

| 방식         | nDCG (신규 gold)              |
| ---------- | --------------------------- |
| 컨셉 점수 단독   | 0.11 (생성 쿼리) / 0.43 (합성 쿼리) |
| **임베딩 단독** | **0.46 / 0.70**             |

**왜 틀렸나** — 초기의 0.965는 **정답셋 과적합 착시**였습니다. 그 정답셋이 컨셉 점수를 참고해 만들어진 부분이 있었거든요. 기술 7편의 "정답셋이 자기 자신을 정답으로 삼는" 문제와 같은 뿌리입니다.

근본적으로는 **역할이 다릅니다.** 컨셉은 **닫힌 목록**이라 목록에 없는 개념을 못 잡습니다. 1차 검색기는 어떤 검색어가 와도 뭐라도 불러와야 하는데, 컨셉은 자기가 아는 축이 아니면 아무것도 못 합니다. **필터로는 훌륭하고 검색기로는 무능합니다.**

**배운 것** — **임베딩은 소환, 컨셉은 게이트.** 각 도구에 제자리가 있습니다. 그리고 **"측정에서 이겼다"를 볼 땐 그 측정이 어떻게 만들어졌는지부터** 봐야 합니다.

---

# 제3전시실 — "더 정확한 신호로 좁히면 좋아진다"

세 번째 함정입니다. 신호를 정밀하게 다듬으면 정밀도가 오를 것 같은데, **좁힌 만큼 정답도 같이 잘려나갑니다.**

## 8\. 청크 임베딩으로 정렬 (기각)

**왜 그럴듯했나** — 청크가 후보 소환에서 대성공을 거뒀습니다(후보 재현율 44.6% → 93.8%). 정렬에도 쓰면 더 좋을 것 같았습니다. 마침 "썸 타는 사람과" 같은 검색은 근거가 리뷰 한 문장에 국소적으로 있으니, 청크가 유리해 보였고요.

**결과**

> **R@10 78.8% → 71.0% 붕괴** — 디저트 100 → 20, 수다 100 → 30, 혼밥 100 → 50

**왜 틀렸나** — 리뷰가 24개나 있으면 **어떤 검색어를 넣어도 그중 한 문장쯤은 어느 정도 비슷합니다.** 그러니 청크 최고 점수는 거의 모든 장소에서 고만고만하게 높고, **변별력이 없습니다.** 1번(피처 혼합)과 같은 붕괴입니다.

**배운 것** — **"근거가 있느냐"와 "얼마나 좋으냐"는 다른 질문**입니다. 청크는 앞의 질문에만 답합니다. (상세: 기술 5편)

## 9\. 키즈 신호를 더 정확한 것 하나로 좁히기 (롤백)

**왜 그럴듯했나** — "아이들과 가기 좋은 곳" 검색에 키즈존이 아닌 곳이 섞였습니다. 원인을 보니 게이트에 `kids_zone`(키즈존)과 `kids_friendly`(아이 배려) 두 신호가 OR로 걸려 있었고, **배려 수준의 카페들이 상위를 차지**하고 있었습니다. 그럼 진짜 신호인 `kids_zone` 하나로 좁히면 되겠죠.

**결과**

> **"아이들과 카페" R@10 100% → 0%**

**전멸했습니다.**

**왜 틀렸나** — **태깅 편차** 때문이었습니다. 진짜 키즈카페인데 `kids_zone`이 안 붙고 `kids_friendly`만 붙은 곳이 상당수 있었습니다. 그 장소들에게는 `kids_friendly`가 **유일한 구조 신호**였고, 그걸 지우니 통째로 사라졌습니다.

**배운 것** — **라벨이 완벽하다는 전제 위에서만 신호를 좁힐 수 있습니다.** 라벨링이 자동화(기술 6편)라 편차가 있는 상황에서는, 부정확한 신호도 **누락 방지 그물** 역할을 합니다. 두 신호 OR을 유지하고, 대신 순서로 해결했습니다.

## 10\. 반려동물 조건을 필수로 (기각)

**왜 그럴듯했나** — 강아지 동반 검색에 반려동물 불가 장소가 하나 섞였습니다. `pet_friendly`를 필수 조건으로 걸면 막히겠죠.

**결과** — **표적 오탐은 안 막혔고**(그 장소는 다른 경로로 통과), **정답만 강등**됐습니다(강아지 쿼리 90 → 80).

**왜 틀렸나** — 오탐 하나를 보고 규칙을 만들면, 그 규칙은 대개 **오탐은 못 잡고 정답만 잡습니다.** 오탐이 어떤 경로로 들어왔는지 확인하지 않고 "관련 있어 보이는 조건"을 필수로 걸었기 때문입니다.

**배운 것** — 규칙을 추가하기 전에 **표적이 정확히 어느 경로로 들어왔는지 트레이스로 확인**합니다. 기술 7편의 귀인 진단이 필요한 이유이기도 합니다.

## 11\. 승격 기준 조이기 (롤백)

**왜 그럴듯했나** — 약한 신호로도 상위 등급으로 승격되는 문제가 있어서, 승격 최소 가중치를 0.15에서 0.25로 올렸습니다. 기준이 엄격해지니 정밀해질 것 같았습니다.

**결과** — **전체 −6.8%p.** 표적 하나를 고치려고 전체를 깎았습니다.

**왜 틀렸나** — 임계값 하나가 **모든 쿼리에 동시에 작용**한다는 걸 간과했습니다. 표적 쿼리에서 문제였던 그 값이, 다른 수십 개 쿼리에서는 정상 동작의 근거였습니다.

**배운 것** — **전역 임계값은 국소 문제의 해법이 아닙니다.** 특정 쿼리 유형의 문제는 그 유형에만 작용하는 규칙으로 풀어야 합니다.

---

# 제4전시실 — 측정이 만든 유령

마지막 방입니다. 여기 있는 것들은 기법이 아니라 **잘못 읽은 숫자**입니다. 어떤 의미에선 가장 위험한 실패입니다 — 나머지는 데이터가 막아줬지만, 이건 데이터를 잘못 읽어서 생긴 거니까요.

## 12\. "1초로 8배 빨라졌다" (측정 착오)

리랭크 설정을 바꿨더니 응답이 1초로 떨어졌습니다. **8배 개선.** 신나서 기록했습니다.

알고 보니 폐기된 모델명을 부르고 있었고, API가 404를 뱉어 **LLM을 아예 안 타고 있었습니다.** 빨라진 게 아니라 일을 안 한 거였죠. 정직한 개선은 "2배쯤"이었습니다.

**배운 것** — **결과가 너무 좋으면 성공이 아니라 버그를 의심합니다.** 개선폭이 예상 범위를 크게 넘으면, 축하하기 전에 "정말 그 일을 하고 있나"부터 확인합니다.

## 13\. 평균은 올랐는데 오탐이 늘었다 (기각)

코사인 유사도를 1차 정렬 기준으로 올리는 실험을 했습니다.

|             | 결과            |
| ----------- | ------------- |
| capped R@10 | **+0.7p** ↑   |
| 오탐 위반       | 39 → **49** ↑ |

**평균 지표만 봤으면 채택했을 겁니다.** 실제로는 코사인이 높은 오답들이 정답과 **함께** 올라온 것이었습니다. 코사인이 높다는 건 "관련은 있어 보인다"는 뜻이지 "맞다"는 뜻이 아니니까요 — 기술 4편의 감자탕/한옥이 딱 그 경우입니다.

**배운 것** — **단일 지표로 채택 결정을 하지 않습니다.** 재현율과 오탐은 항상 같이 봅니다.

## 14\. 한 쿼리를 살리고 다른 쿼리를 죽였다 (기각)

특정 후보군을 무조건 상위 등급으로 올리는 실험이었습니다.

| 쿼리   | 전 → 후          |
| ---- | -------------- |
| 호수뷰  | 33 → **67** ↑  |
| 부모님과 | 100 → **20** ↓ |

표적 쿼리는 두 배가 됐는데, 다른 쿼리가 5분의 1이 됐습니다. 원인은 승격 조건이 **상황형 의도**(부모님과, 데이트 등)에서는 너무 광범위하게 참이 돼서, 진짜 정답을 밀어냈기 때문입니다.

**배운 것** — 이래서 채택 게이트에 **"급락하는 쿼리가 0건인가"** 를 넣었습니다(기술 7편). 전체 평균은 이 경우 거의 안 움직였을 겁니다. **평균은 학살을 숨깁니다.**

---

## 이 박물관이 말하는 것

전시물을 다 보고 나면 패턴이 몇 개 보입니다.

**① "더하기"는 공짜가 아니다.** 피처 혼합은 순위 해상도를 지웠고, 근거 발췌는 오답을 변호했고, 청크 정렬은 변별력을 덮었습니다. 신호를 추가할 땐 **기존 신호에 무슨 일이 일어나는지**를 봐야 합니다.

**② 각 도구에는 제자리가 있다.** 임베딩은 소환, 컨셉·품질은 게이트, LLM은 컷과 이유. 하나로 다 하려고 할 때마다 무너졌습니다. **좋은 도구를 잘못된 자리에 놓는 것**이 가장 흔한 실패였습니다.

**③ 좁히면 정답도 잘린다.** 라벨이 완벽하지 않은 세계에서, 부정확한 신호는 그물 역할을 합니다. 정밀도를 위해 신호를 줄일 땐 **그 신호가 유일한 근거인 정답**이 있는지 확인해야 합니다.

**④ 숫자는 읽는 법을 안 알려준다.** 8배는 버그였고, +0.7p는 오탐 +10을 숨겼고, 평균은 학살을 숨겼습니다. **지표는 여러 개를 같이 봐야 하고, 이상하면 원본을 열어봐야 합니다.**

그리고 마지막으로 — **기각은 실패가 아닙니다.** 이 목록의 절반은 "안 되는 걸 알아낸" 성과입니다. VLM 사진 데이터는 검색에는 못 썼지만 자산으로 남았고, 30B 실험은 "로컬로는 이만큼이 상한"이라는 좌표를 줬습니다. 그리고 리랭커를 두 번 기각한 끝에 **"LLM은 컷과 이유에만"** 이라는 원칙이 나왔습니다.

유추카가 지금의 품질에 도달한 건 좋은 아이디어를 많이 넣어서가 아니라, **좋아 보이는 나쁜 아이디어를 데이터로 계속 걷어냈기 때문**입니다. 화려한 성공 목록보다 이 기각의 목록이, 서비스를 만든 진짜 기록에 더 가깝습니다.

다음 글(기술 9)에서는 이 모든 걸 얹고도 **검색을 1020초에서 25초로** 줄인 속도 최적화를 봅니다.

- [유튜버추천카페로 이동하기](https://youchuca.popit.kr/?ref=popit.kr)