Prolog

내가 다니던 회사의 후배 개발자들의 고생담을 페이스북에서 보면 뭔가 "찡~~" 한 느낌이 온다.

아마 내가 옛날에 겪었던 고생한 기억과 동질감이라는 감성적인 이유도 있지만,

협업하는 업체와 바라보는 입장이 달라서 겪었던 기술적인 문제들도 생각났기 때문이다.

 

검색프로젝트는 분명 일반적인 방법과 다르게 접근할 부분과 지식이 존재한다.

하지만, 안타깝게도 이런 정보나 경험은 찾아보기 힘들다는 문제점이 있었다.

그때는 찾아 다녔지만, 이제는 나의 지식과 노하우를 공유할때가 되지 않았나 생각한다.


일단,  기술적인 내용은 "독크루저"라는 상용 검색엔진을 사용한 경험과

프로토타입 개발시 사용한 mongoDB, 그밖의 DB사용경험을 토대로 이야기를 풀어보려고 한다. 

 

참고로 필자(=정선생)는 검색프로젝트팀에서 3년, 검색연구개발팀에서 1년을 개발했고.

지금은 검색광고데이터를다루고 있는 6년차 프로그래머이다.

나보다 더 많은 경험을 쌓으신분이라면 까기보다는 의견을 달아주면 좋겠다. (^ㅅ^)/


 


 1. 서비스 오픈후에 더 바쁜 사람들


검색은 데이터성격의 작업이다. 

데이터가 어느정도 쌓이고 사용자가 검색을 하면서 품질에 대한 이슈가 발생하기 시작한다.

서비스가 오픈하고나서 듣는 말들이 있다.

 

  Q: "검색이 안되요"  

  Q: "왜, 이 결과가 안나오나요?"

  Q: "검색결과에서 이 문서가 왜 상단에 나오지 않나요??"

  Q: "검색이 느려요"




왜 이런현상이 일어날까? 몇년전 그룹장님이 했던 한마디가 떠오른다.


"검색은 데이터에 기생하는 존재다"

  

보통 초기에는 테스트성 데이터만 존재한다.

이런 데이터로는 기능이 동작하는걸 확인하는 개발은 가능하지만, 원하는 결과를 나오게 한다는건 불가능하다.

물론 성능이나 일부 속도 테스트에는 유용할지 모르지만, 검색품질을 테스트하려면 실데이터가 필요하다.

그렇다보니, 실제 데이터가 들어오고 어느정도 검색이 필요한 시점이 되어야 요구사항이 빗발치기 시작한다.

(= 왜 실데이터가 있어야 하는가에 대한 내용은  다음에  "정확도와 재현률"을 다룰때  이야기 하겠다.)


그래서, 검색프로젝트의 성공을 하려면 사실 아래 그림과 같이 검색대상과 요구사항에 대한 분석을 위해

초중반부에 분석을 요청하고, 실제 투입은 후반에 요청하는것이 가장 효율적이다.

특히 가능하다면 프로젝트 종료 이후에도 맨먼스를 확보해두는것이 좋다.




물론 종종 무조건 같이 초반부터 프로젝트에 넣어달라고 하는 경우도 있다.

억지로 초반에 요청하여 잡고 있으면 진짜 필요한 후반부에 담당 개발자는 딴 프로젝트에 투입되어버릴지 모른다.



 


2. 검색엔진과 DBMS에서 바라보는 입장은 다르다


DBMS(Database Management System)는 이름에서 알수있듯이 데이터의 관리에 촛점을 맞춘다.

데이터 이상현상(Anomaly)을 해결하기위해 정규화를 거치고, 트랜잭션이나 롤백같은 기능도 존재한다.

하지만 검색엔진에서 일반적으로 트랜잭션이나 롤백같은 기능이 없다.

멋을 위해 시각을 포기한 머리스타일 같다고 할까?

(사족으로 말하면, NOSQL제품군도 유사하게 트리거나 트랜잭션 같은 기능은 지원되지 않는대신 insert속도를 향상시키기도 한다.)



 

아주 간단한 예를 들어, 아래와 같은 형태의 블로그를 만들고 이곳에 검색엔진을 도입한다고 하자.

그러면 DBA는 어떻게 설계를 할까?



DB를 조금 공부 했으면 알겠지만, 태그값의 경우 여러개의 값으로 존재한다는걸 인지하고 정규화를 하려고 할것이다. 참고로 "1차정규화" 조건을 보면 "복수의 속성값을 갖는 속성을 분리 한다" 라는 조건이 있다.

즉, 정규화를 거치면 아래와 (a) 구조와 같이,두 개의 테이블로 만들 것이다.


(a) DB입장

 (b) 검색엔진 입장

 



그러면, 검색엔진에서 데이터를 넣기위한 구조는 어떤 형태로 만들어야 할까?

검색 스키마는 화면에 보여지는 모든 데이터가 하나의 테이블로 구성하는것이 기본이다. =(b)테이블 참고


그런데, 조금 이상해 보인다. 태그부분의 경우 하나의 필드에 묶어버리면, 검색할때 무조건 like검색으로 써야 해서 속도도 떨어지고, 정규화도 안된 이상한 스키마 구조이다. (=DB만 접한 사람은  그럴수 있다는의미)

최근에는 그나마 NoSQL기반의 플랫폼이 나오고 많이 알려지면서 이런 특이한 구조가 낯설지 않겠지만, 불과 얼마전까지만해도 용납할수 없는 상상할수 없는(?) 구조였다. 

(=사족으로 MongDB라는 제품은 스키마라는게 아예 존재하지않고 JSON형태의 DocumentDB를 지원한다)


 

그렇다보니 프로젝트에서 종종 오해가 생기기 시작한다. 

태그를 묶어서 달라고 했는데 단순히 OUTER JOIN을 해서 줘버린다.

이러면 데이터가 뻥튀기 되고, 이 데이터를 그대로 색인(INDEX)해서 사용하면 중복되는 결과가 나올것이다.


즉, 검색담당자가 원하는 검색용 VIEW는 위와 같은 구조가 아니라 아래와 같은 형태의 결과를 의미하는것이다.

내가 사용했던 검색엔진에서는 색인키를 구분자 단위로 만드는 필드가 존재했다.

(=쉽게 생각해서 하나의 필드에 LIST 형태의  값을 넣을수 있다고 생각하면 된다)

그래서 하나의 필드에 여러개의 값을 넣어서 색인도 가능하고 빠르게 검색이 가능했다.



일반적으로 정규화된 테이블에서 이런식으로 구분자로 묶는 형태로 쿼리를 짜는 경우가 적다보니 어떻게 접근할지 감이 안잡히는분이 있을텐데, 보통 function을 만들거나 몇몇 DB의 내장함수를 활용해서 만들어 낸다.

아래 글을 참고하면 도움이 될듯하다.


a. oracle에서 함수를 만들어서 묶는 예제 (링크)

b. oracle의 XML관련 내장함수를 이용해 행을 묶는 예제 (링크)



Tip & 잡담.

비정규화 기법은 DB에서도 JOIN비용이 너무 클 경우 일부 중복데이터를 감안하고 테이블을 추가로 만들어 쓰기도 한다. 물론 검색엔진만큼 극단적인 구조는 아니지만 조회 성능향상을 위해 사용되는 방법이니 참고하기 바란다.


 


3. 1부를 마치며


글을 쓰면서 어디서 부터 시작하고 어떻게 해야 할지 고민이 많이 되었다.

그래서 가장 크게 오해할 수 있는 부분을 1부의 내용으로 다뤄봤다.


"2부는 색인(INDEX) 그리고 검색" 이라는 주제로 글을 다뤄보려고 한다.

검색을 하기위해서는 색인이라는 작업을 거친다.
색인이라는 작업이 왜 필요하고, 검색엔진의 색인과 DB의 색인은 뭐가 다른가 같은 기본지식을 알려주고 싶다
DB에서는 안되는 검색엔진의 검색에 대한 이해라고 생각하면 될것같다.

"3부는 재현률/정확도/랭킹/정렬" 이라는걸 다루려고 한다.
검색결과에 대한 여러가지 이야기를 하려고 한다. 왜 이 결과가 상위에 올라오는가.
비슷해 보이지만 저 용어는 뭘까?


알쏭달쏭한 이야기를 내가 쉽게 풀어내야할텐데 알려주고 싶은건 많은데, 말로 쉽게 안풀려 고민이 된다 ^_^;


2.1 색인 인덱스편 ( http://tost.tistory.com/206 )


+ Recent posts