검색 엔진 관련된 일을 10여년간 하면서 여러 복잡한 검색 기획서들을 접해봤다. 검색 기획서는 아이디어 복제와 추가 과정을 거쳐 점점 더 복잡해지고 있다. 오늘도 기획서를 보고 새롭게 기획된 기능들을 어떻게 구현할지를 고민하던 중이었다. 색인 필드를 너무 많이 추가해 엔진 한계를 넘었고 일 2백만 실시간 동적 색인이 발생하는 콜렉션이었다. 골치 아픈 기획 기능이었다. 복잡했다. 그 순간 문득 "기능은 계속 추가되는데 왜 기능을 삭제하는 기획은 없지?"란 생각이 들었다. 한번도 생각한 적 없는 생소한 질문이었다.

저녁 먹으로 가는 길에 지나가는 동료에게 물었다. 혹시 검색 기능을 빼는 기획서를 본적이 있냐고. 그 친구 "허허 그런적 없죠. 당연히~~". 왜 그렇게 생각하는지도 물었다. 답은 으외로 단순했다. "10개 기능이 있었고, 1개 기능을 추가하면 더 성공할 가능성이 높아지죠. 당연히~~" 우문에 현답을 했다.
 
답은 모른다. 다만 기능 추가 기획보다 기능 삭제 기획이 더 어려워 보인다. 기능 추가는 '더하기'로 보이지만 기능 삭제는 '빼기'처럼 보이기 때문이다. 하지만 역으로, 복잡해진 기획 안에서 삭제가 추가 보다 더 가치있고 실제로 'PLUS'효과를 기대할 수 있지 않을까? 최신 냉장고의 숨긴 기능들이 나날이 복잡해지지만 노출된 기능들은 점점 단순해지는 하드웨어 세상 같이 말이다.

삼성의 이건희 회장이 혁신을 외치고, 대한민국의 미래가 아이폰 같은 혁신 상품에 있다고 다들 주장한다. 새로운 아이디어를 만드는 방법으로 첫 번째는 더하기/빼기라 한다. A와 B를 더해 C를 만들고 A에서 B를 빼서 새로운 C를 만든다. 삭제 서비스 기획 안을 들고 가서 보스를 설득이 어려우니, 보스 설득 확률이 높은 추가 기획을 하고 있지는 않을까 곰곰히 생각해본다.

@윤종완

추신. 누구 삭제 기획을 하시는 분 보신적 있나요?

신고


최근 검색 트렌드는 의미 검색(Semantic Search)인 것 같다. 구글이 키워드 검색을 꽉잡고 있고 개인 맞춤 검색은 시들해진 여파 같다. 의미 검색(Semantic Search)을 어떤 식으로 얘기해도 역 파일 기반 검색엔진을 통해 구현한다면 검색어, 색인어 선별 문제로 국한된다. 문장 또는 검색어에 나타난 그대로를 색인하면 키워드 검색이 된다. 의미 기준에 따라 선별하면 의미 검색이라고 불릴 자격이 부여된다. 사용자 입장에서 보면 검색어가 돌출돼 있는 문서를 머릿속에서 상상하며 검색하면 키워드 검색이다. 반면 문서를 그 자체로 생각하며 검색한다면 의미 검색이 된다. 웹 검색이 대표적인 키워드 검색라면 쇼핑몰 검색이 대표적인 의미 검색 분야다. 웹 문서는 디지털화된 문자열로 쉽게 상상되지만 구매 대상인 옷들을 문자열로 상상하기란 힘들다.

쇼핑몰에서는 잘 조직화된 의미사전을 사용해 검색어를 자동 확장하여 의미 검색을 시도한다. 아래에 GS이숍의 "나이키" 검색결과가 있다. 잘보면 첫 결과에 "나이키"란 단어가 없다. 나이키의 영문표기인 "NIKE"를 자동으로 넣어 검색했다. "NIKE"와 "나이키"는 수작업으로 의미사전에 등록되어 있고 검색엔진에서는 "나이키"를 "나이키 or NIKE"로 확장해서 검색했을 뿐이다. 질의확장 용도의 의미사전은 정교하게 튜닝되어야 하기에 모두 수작업으로 만든다. 잘못된 오확장은 검색결과를 나쁘게 만들기 때문이다. 일일이 등록되는 모든 상품을 검토할 수 있다면 수작업을 뭐라 할 수 없다. 하지만 옥션과 같이 사용자들이 올리는 상품이라면 불가능하다. 이런 경우 자동화된 질의확장방법이 절대적이다.
 

상품 내용 그 자체만을 분석해서 쿼리를 자동 확장하는 잠재 은닉 색인(Latent Semantic Indexing)이란 기법이 있다. 상당히 잘 동작한다고 알려져 있는데 국내에 잘 소개되지 못한 것 같다. LSI가 심한(?) 행렬 계산을 필요로 하고 문서와 질의를 은닉차원으로 전환하기 위해 2차 색인을 참조해야 하는 여러 부담 때문에 LSI를 적용한 엔진을 구경하기 힘든것 같다. SVD(Singular Value Decomposition)이란 어려운 선형대수가 나오기 때문일지도 모르겠다. 색인기법으로 LSI와 같은 고급기법들을 채택한 똑똑한 검색엔진이 나왔으면 한다.

@webJOY



신고

루씬은 단순 라이브러리다. 데몬 형태로 항시 실행되며 검색어를 찾아주는 검색 서버를 만들려면 웹 서버가 필요하다. 검색 서버용 웹 서버는 검색어를 동시 처리해야 하므로 멀티 쓰레딩이 되어야 하고 적어도 HTTP 1.0을 지원해야 한다. 욕심을 내자면 HTTP Keep Alive를 지원하는 HTTP 1.1 스펙을 지원하면 더 좋다. 사용자 쿼리 폭증 시에 검색 서버가 마비되는 현상을 막기 위해 허용 연결 갯수를 제한할 수 있는 기능이 있으면 금상첨화다. 여러 오픈소스 웹 서버가 있었지만 제티(Jetty)를 골랐다. 다른 자바 웹 서버를 사용해도 상관없다.

웹 서버는 해결되었지만 루씬의 검색 API인 IndexSearcher가 멀티쓰레드로 검색하는 경우에 대한 속 시원한 코드나 답변을 좀처럼 찾기 어려웠다. IndexSearcher는 가급적 1개 인스턴스만 가지고 작업을 하도록 루씬 매뉴얼에 권장되어 있어(참조) 멀티쓰레드가 공유해서 나눠쓰도록 코딩했었다. 결과는 엉망되었는데 ab 스트레스 테스트에 거의 80 ~ 90% 검색어를 처리하다 실패했다. 예외 메시지만 보았을때는 루씬 세그먼트 파일 오픈 실패였다. 파일 갯수 제한에 그 원인이 있는 줄 알고 동시 연결 클라이언트 수를 제약해보거나 단일 쓰레드로 테스트해보았지만 오류는 같았다.

해결책을 찾아 이리저리 구글링하다 코지 세키구치(Koji Sekiguchi)란 일본인이 쓴 "Apache Lucene 入門"이란 책의 예제 코드에서 해결점을 찾았다. 코지는 IndexSearcher 인스턴스를 한 개만 만들고 close()하지 않은채 계속 사용하는 DelayCloseIndexSearcher란 클래스를 만들어섰다. 첫 실험이 쓴 실패가 IndexSeacher.close()를 자주 호출하기 때문에 발생한 것 같다. 코지의 코드를 약간 수정해 Jetty + DelayCloseIndexSearcher로 만족할 만한 루씬 멀티 쓰레드 검색 서버를 만들었다.

고속 루씬 검색 서버로 가려면 넘어야 할 산들이 더 있다. 루씬 2.4 스펙에 들어 있지만 실제론 3.0에 구현될 예정이라는 읽기 전용 모드의 IndexReader를 사용해야 할 것 같다(LUCENE-1329). 처리율 향상을 위해서다. 또, 루씬 2.4에 새롭게 추가된 허용 시간내 색인 읽기 기능(LUCENE-997)도 꼭 필요하다. 대용량 콜렉션에서 빈번하게 출현된 색인어를 검색하는 경우에 대용량 IO발생으로 검색 서버의 IO 대역폭을 과점하여 다른 검색이 느려지기 때문이다. Jetty에서 동시 연결 갯수를 제한하는 기능은 아직 못 찾았다. 이 또한 검색어 폭주 현상에서 검색 서버가 원활히 동작하기 위해 꼭 필요한 기능이다.

@webJOY

우워~~ 코지 세키구치가 솔라(Solr) 커미터였군요 ^^
conv2님의 블로그에 코지 세키구치의 예제코드가 있어요. 약간 오타가 있답니다. 찾아보세요.

신고

티스토리 툴바