Collapse AllExpand All

4.8.1. 금칙어

sample3.jsp

금칙어는 검색을 요청하기 전에 처리해야 한다. 예를 들어 검색어가 "성인 영화"이고 금칙어에 "성인"이 포함되어 있으면 검색 요청 시 "성인"을 제거한 "영화"라는 검색어로 요청해야 한다. 아래는 입력된 검색어로부터 금칙어 목록을 구하고 원래 검색어에서 금칙어를 제거한 후 검색 요청하는 코드이다.

1.	<%@ page import="org.apache.commons.lang3.StringUtils,…
2.	                  com.konantech.ksf.client.KsfClient,
3.	…
4.	KsfClient ksfclient = new KsfClient("http://localhost:7612/ksf");
// 쿼리로부터 금칙어 목록을 구한다.
5.	String[] censored = ksfclient.getCensoredWords(0, query);
// 검출된 금칙어가 있을 경우
6.	if (censored.length > 0) {
7.	  for (int i = 0; i < censored.length; i++) {
    // 원래 쿼리로부터 금칙어를 제거한다.
8.	    query = StringUtils.remove(query, censored[i]);
9.	  }
10.	  query = query.trim();
  // 쿼리로부터 검출된 금칙어 목록을 censored라는 세션 애트리뷰트에 저장한다.
11.	  session.setAttribute("censored", StringUtils.join(censored, ','));
12.	}
13.	…
14.	SearchResultSet srs = crzclient.search(sq);
15.	…

금칙어 목록은 입력된 쿼리에 따라 달라지므로 입력된 쿼리가 이전 요청의 쿼리와 같은 경우(예를 들어 페이지 이동)에는 다시 구할 필요가 없다. 따라서 쿼리에 따른 금칙어 목록을 세션 애트리뷰트에 저장하고 쿼리가 변경되지 않았을 경우에는 재사용한다.

검색 엔진으로 전달할 쿼리는 사용자가 입력한 쿼리가 아닌 금칙어 제거 과정을 거친 쿼리이므로 금칙어 목록과 함께 금칙어를 제거한 쿼리도 함께 저장하고 있어야 한다. 따라서 서버로 전달되어야 할 입력 쿼리 관련 파라미터는 사용자가 입력한 쿼리(query), 이전 요청에서 사용자가 입력한 쿼리(original-query), 이전 요청에서 금칙어 처리 과정을 거친 쿼리(previous-query) 이렇게 세 가지이다.

사용자가 입력한 쿼리와 이전 요청에서 사용자가 입력한 쿼리가 같을 경우에는 이전 요청에서 금칙어를 제거한 쿼리를 검색 엔진에 넘기고 금칙어 목록도 세션에 저장되어 것을 재사용한다. 같지 않을 때에는 세션에서 저장된 금칙어 목록을 제거하고 금칙어 목록을 새로 구한다.

1.	…
2.	String query = RequestUtils.getParameter(request, "query");
3.	String originalQuery = RequestUtils.getParameter(request, 
                          "original-query");
4.	if (query == null || !query.equals(originalQuery)) {
// 이전 사용자 입력 쿼리와 동일하지 않을 경우 세션에 저장된 금칙어 목록을 제거
5.	  session.removeAttribute("censored");
6.	}
7.	if (query != null) {
8.	  pageContext.setAttribute("query", query);
9.	  KsfClient ksfclient = new KsfClient("http://localhost:7612/ksf");
10.	  if (query.equals(originalQuery)) {
    // 이전 사용자 입력 쿼리와 동일할 경우 이전 요청에서 금칙어를 제거한
    // 쿼리를 재사용
11.	    query = RequestUtils.getParameter(request, "previous-query");
12.	  } else {
    // 이전 사용자 입력 쿼리와 동일하지 않을 경우 금칙어 목록을 새로 구함
13.	    String[] censored = ksfclient.getCensoredWords(0, query);
14.	    if (censored.length > 0) {
15.	      …
16.	      session.setAttribute("censored", StringUtils.join(censored, ','));
17.	    }
18.	  }
19.	  …
20.	}

사용자가 입력한 쿼리(query), 이전 요청에서 사용자가 입력한 쿼리(original-query), 이전 요청에서 금칙어 처리 과정을 거친 쿼리(previous-query)는 각각 아래와 같이 폼에 설정한다.

1.	…
2.	<script>
3.	…
4.	$("#original-query").val($("#query").val());
5.	…
6.	</script>
7.	…
8.	<form name="search-form" method="post" class="form-inline" 
         role="form">
9.	…
10.	  <input class="form-control" placeholder="Search" type="text" 
             id="query" name="query" 
             value="<c:out value="${query}"/>"/>
11.	  <input type="hidden" id="original-query" name="original-query"
       />
12.	  <input type="hidden" id="previous-query" name="previous-query"
             <c:if test="${not empty sq}"> 
              value="<c:out value="${sq.query}"/>"</c:if>/>
13.	  …
14.	</form>
15.	…

금칙어가 포함되어 있을 경우 아래와 같이 금칙어가 제외되었음을 표시한다.

1.	<c:if test="${not empty censored}">
2.	  <dl class="suggestions">
3.	    <dd><strong>"<c:out value="${censored}"/>"</strong>이(가) 
                    검색어에서 제외되었습니다.</dd>
4.	  </dl>
5.	</c:if>
결과

그림 C.9. 금칙어

금칙어