 |  |
|
난이도 : 중급 Martin Brown, Developer and writer, Freelance
2007 년 11 월 20 일 본 시리즈 마지막 기술자료에서는, VoiceXML을 인풋으로 취하고, 기본적인 웹 검색과 Yahoo 로컬 검색에 Yahoo Search API를 쿼리하는 애플리케이션을 개발해 보도록 하겠습니다. 이 쿼리는 특정 위치와 지역 내의 비즈니스에 관한 정보를 리턴합니다. 애플리케이션은 제출 후에 콜러에게 결과를 읽어줍니다.
머리말
인터넷 검색은 요즘 같은 시대에는 당연한 것으로 받아들여지고 있고, 수 많은 서비스들이 제공된다. 웹 검색 역시 확대되었다. 웹을 갖고 있는 많은 기업들이 이제는 자신들의 웹과 비즈니스 디렉토리 같은 전통적인 오프라인 데이터를 합병하고 있고, 다양한 비즈니스와 정보용 검색에 사용할 수 있도록 지도와 위치 정보를 합병하고 있다.
이와 같은 정보들을 VoiceXML(VXML)을 사용하여 검색하고 리턴된 결과를 듣는 것도 가능하다. 이 글에서는 이러한 일을 수행하는 애플리케이션을 구현하고, 아울러,
- 웹 검색 워크플로우에 대해 알아본다.
- VXML 폼 엘리먼트를 출력하는 기본 클래스를 생성한다.
- 광범위한 인풋을 지원하는 VXML 문법을 만든다.
- Yahoo 검색 인터페이스를 사용한다.
- VXML과 Yahoo 검색을 사용하여 웹 검색을 실행한다.
- VXML과 Yahoo 검색을 사용하여 로컬 검색을 실행한다.
시리즈 소개
음성과 오디오는 웹에서 점점 더 대중화 되고 있다. 현재 온라인에서 사용할 수 있는 음악이나 웹캐스트(webcast)가 한 예이다. 본 시리즈에서는 음성과 XML을 결합하여 유용한 애플리케이션들을 개발하는 여러 가지 방법을 소개하고자 한다:
-
Part 1
—음성 실행 RSS 리더.
-
Part 2
—음성 실행 달력.
-
Part 3
—음성 실행 블로그 및 Twitter 애플리케이션.
- Part 4—음성 실행 Yahoo 검색 애플리케이션.
웹 검색 워크플로우
웹 검색 워크플로우는 두 개의 검색 유형들인 로컬 검색과 전통적인 웹 검색 중 하나를 선택할 수 있도록 하는 메뉴를 제공한다. 전자는 두 개의 인풋 값, 검색어, 위치를 필요로 하고, 후자는 검색어만 필요로 한다. 그림 1은 기본적인 시퀀스이다.
그림 1. 웹 검색 워크플로우
본 시리즈의 이전 파트에서는, 기본 메뉴 선택을 지원하는 방법을 설명했으므로, 그 부분은 넘어가도록 하겠다.
검색어의 경우, VoiceXML 스팩에 의해 인식되는 인풋 용어에 훨씬 더 광범위한 선택권을 지원하게 될 것이고, 간단한 VoiceXML 클래스를 구현하여 애플리케이션의 일부로서 정보를 출력할 것이다.
자유 형식(freeform) 문법 인풋 만들기
본 시리즈 Part
3에서 보았지만, VoiceXML을 위한 블로깅 솔루션의 경우, 음성 텍스트에서 읽고 이것을 텍스트 포맷으로 변환하는 편리한 녹음(transcription) 메소드가 없다. 찾고 싶은 단어와 구문을 지정하여 음성 인식 시스템이 보다 정확할 수 있도록 해야 한다.
일반적으로, "I am sad" 같은 특정 구문을 지정한다면, 문법 규칙에 명확하게 이 구문을 정의한다: (eye am sad).
웹 검색의 경우, 자유 형식 텍스트 인풋이 필요하다. 부족한 "녹음" 지원 때문에 아무 텍스트나 모른 채로 받아들일 수 없지만, 일정 범위의 용어들을 제공하고, 사용자가 원하는 대로 다양한 용어들을 반복하게 할 수 있다.
이를 위해서, 용어 그룹을 지정한 다음, 이들 용어들 중 최소한 한 개 이상을 지원하는 규칙을 만든다. 예를 들어, "java", "apple", "windows" 또는 이 단어들의 조합을 지원해야 한다면, 용어 그룹을 다음과 같이 지정할 수 있다: Terms [ (java) (apple) (windows) ].
그리고 나서, 이것의 반복을 기대하는 같은 문법에 규칙을 추가한다: .Phrase +Terms.
이제 사용자는 이러한 용어들이나 용어 조합들을 언제라도 반복할 수 있다. "java apple" 또는 "java apple window" 모두 유효하다.
물론, 독립적으로는 비교적 쓸모 없다. 다른 수단을 통해서 이를 실현할 수 있다. 더욱 강력한 컨트롤을 결합하거나 제공할 수 있는 다른 영어 단어와 결합한다면 더욱 좋을 것이다. 예를 들어, 다음과 같이 정의를 확장시킬 수 있다: Terms [ (java) (apple) (windows) (and) (or) ].
사용자는 이제 "java and apple" 또는 "java and windows" 심지어는 "java and apple or windows"를 말할 수 있다.
이제, 표준화 된 아웃풋 클래스를 사용하여 대부분의 자유 형식 인풋을 수락하는 시스템을 구현해 보자.
기본적인 VXML 아웃풋 클래스 만들기
사전 정의된 포맷에 따라 프라그먼트의 특정 엘리먼트를 생성 할 표준화 된 VXML 아웃풋을 만들 수 있다. 이는 VXML의 생성을 단순화 하고, 특히 자유 형식 인풋 포맷으로는 정보 생성이 훨씬 더 쉽다.
많은 VXML 애플리케이션에서 작동하도록 WebSearchVXML 클래스를 조정할 수 있다. 애플리케이션에 필요한 올바른 VXML을 출력하는 간단한 메소드를 제공하기 때문이다. 이 버전은 표준 아웃풋으로 출력하지만(System.out.println() 메소드 사용), VoiceXML 애플리케이션의 동적 엘리먼트용 웹 기반 애플리케이션 내에서 작동하도록 쉽게 조정할 수 있다.
이 클래스는 다음과 같은 정보와 메소드를 제공한다.:
- 지원되는 웹 검색어 리스트
- 지원되는 로컬 검색어 리스트
- 지원되는 클래스나 위치 리스트
-
VXMLPrompt는 '<prompt>message</prompt>' 블록을 출력한다.
-
VXMLTerms는 삽입된 프롬프트 블록 안에 필드 블록과 자유 형식 용어 문법 아웃풋을 출력한다.
-
VXMLOptions는 삽입된 프롬프트 블록과 말로 표현된 옵션 리스트로 필드 블록을 출력한다.(이를 테면, 도시 리스트 같이 사용자가 가능한 리스트 중에서 하나를 선택하도록 해야 할 때 알맞다.)
-
VXMLHeader는 표준화 된 헤더를 출력한다.
-
VXMLFooter는 간단한 꼬리말을 출력한다.
Listing 1은 결과 클래스이다.
Listing 1. 표준화된 VXML 클래스
public class WebSearchVXML {
String webterms[] = { "java",
"apple",
"windows",
"britney spears",
"lindsey lohan"};
String localterms[] = { "plumber",
"restaurant",
"electrician",
"supermarket"};
String cities[] = { "London",
"Nottingham",
"Manchester",
"York",};
PrintStream out = System.out;
public void WebSearchVXML() {
}
private void OutputGSLTerms(String[] terms) {
this.out.println("<grammar type=\"text/gsl\">" +
"<![CDATA[\n" +
".Phrase +Terms\n" +
"Terms [ ");
for(int i=0;i<terms.length;i++) {
this.out.println("(" + terms[i] + ")");
}
this.out.println("]\n" +
"]]>" +
"</grammar>");
}
private void OutputOptionTerms(String[] terms) {
for(int i=0;i<terms.length;i++) {
this.out.println("<option>" + terms[i] + "</option>");
}
}
public void VXMLPrompt(String prompt) {
this.out.println("<prompt>" + prompt + "</prompt>");
}
public void VXMLTerms(String fieldname,
String prompt,
String [] terms) {
this.out.println("<field name=\"" + fieldname + "\">");
VXMLPrompt(prompt);
OutputGSLTerms(terms);
this.out.println("</field>");
}
public void VXMLOptions(String fieldname,
String prompt,
String [] terms) {
this.out.println("<field name=\"" + fieldname + "\">");
VXMLPrompt(prompt);
OutputOptionTerms(terms);
this.out.println("</field>");
}
public void VXMLHeader() {
this.out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
this.out.println("<vxml version=\"2.1\">");
}
public void VXMLFooter() {
this.out.println("</vxml>");
}
}
|
빠르게 VXML 폼을 출력하여 사용자에게 인풋을 수락한다.
기본 인터페이스 사용하기
예를 들어, Listing 2의 코드를 사용하여 "로컬" 검색용 VXML을 만든다고 생각해 보자.
Listing 2. 간단한 검색 출력하기
WebSearchVXML search = new WebSearchVXML();
search.VXMLHeader();
System.out.println("<form>");
System.out.println("<block>");
search.VXMLPrompt("Welcome to the Internet search service");
System.out.println("</block>");
search.VXMLTerms("phrase",
"Enter the search phrase to use when searching the web",
search.webterms);
search.VXMLOptions("location",
"Enter the location to limit your search to",
search.cities);
System.out.println("<filled><submit name=\"/VXMLSearch/search\"
namelist=\"phrase location\">");
System.out.println("</form>");
search.VXMLFooter();
|
Listing 3은 이것에 의해 생성된 결과 VXML이다.
Listing 3: VXML 아웃풋
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1">
<form>
<block>
<prompt>Welcome to the Internet search service</prompt>
</block>
<field name="phrase">
<prompt>Enter the search phrase to use when searching the web</prompt>
<grammar type="text/gsl"><![CDATA[
.Phrase +Terms
Terms [
(java)
(apple)
(windows)
(britney spears)
(lindsey lohan)
]
]]></grammar>
</field>
<field name="location">
<prompt>Enter the location to limit your search to</prompt>
<option>London</option>
<option>Nottingham</option>
<option>Manchester</option>
<option>York</option>
</field>
<filled><submit name="/VXMLSearch/search" namelist="phrase location">
</form>
</vxml>
|
이것의 진정한 효과는 지원되는 용어나 도시 리스트를 변경하거나 확장하려면 스트링 어레이만 업데이트 하면 된다.
결과 옵션과 지원되는 인풋 값은 순전한 자유 형식 텍스트는 아니지만, 적당한 용어 리스트를 사용하기 때문에 확장적이다.
Yahoo 검색 인터페이스 사용하기
Yahoo 검색 인터페이스에서, 거의 모든 Yahoo 검색 데이터베이스를 검색할 수 있다. 이러한 편리한 인터페이스는 다양한 검색 매개변수들을 생성하고 결과로부터 상세를 얻는 메소드를 제공한다.
Yahoo 검색 시스템을 사용하기 전에, API 키를 위해 등록을 해야 한다. API 키를 갖게 되면, Yahoo 검색 SDK를 다운로드 한다. (참고자료) SDK는 Yahoo 검색 인터페이스와 통신하는데 필요한 모든 것이 포함되어 있는 자바™ JAR 파일의 형태로 되어 있다.
이 API를 사용하는 자바 프로그램을 컴파일 하려면, 클래스 경로 $ javac -cp yahoo_search-2.0.2.jar LocalSearch.java에 Yahoo JAR를 포함시켜야 한다.
이제, 검색어를 취해서 찾은 결과를 리스팅 하는데 필요한 VXML을 출력하는 간단한 검색 함수를 사용해 보자.
웹 검색 실행하기
간단한 웹 검색을 실행하려면, 등록했을 때 Yahoo에서 받은 API 키를 사용하여 SearchClient() 객체 인스턴스를 만든다. 이것은 검색을 수행하고 어떤 검색 유형이라도 지원하는 클라이언트 객체를 만든다.
요청의 경우, WebSearchRequest() 클래스를 사용하여 새로운 요청 객체를 만들면서, 검색어로서 사용할 스트링을 지정한다.
클라이언트를 사용하여 요청을 제출하면, Yahoo는 요청에 대한 일반화 된 정보를 포함하고 있는 WebSearchResults 객체를 리턴하고, 개별 결과의 어레이를 리턴한다. 각 결과에는 페이지 제목, URL, 기타 정보 등을 포함하고 있는데, 이들 대부분이 VoiceXML 애플리케이션에서는 비교적 쓸모가 없다. Listing 4는 전체 시퀀스 모습이다.
Listing 4. Yahoo로 웹 검색 하기
public static void DoSearch(String term) {
SearchClient client = new SearchClient("INSERTKEY");
WebSearchRequest request = new WebSearchRequest(term);
try {
WebSearchResults results = client.webSearch(request);
System.out.println("<block><prompt>Found " +
results.getTotalResultsAvailable() +
" hits for " +
term +
". Detailing the top " +
results.getTotalResultsReturned() +
" results.</prompt></block>");
for (int i = 0; i < results.listResults().length; i++) {
WebSearchResult result = results.listResults()[i];
System.out.println("<block><prompt>" +
result.getTitle() +
".<break/>" +
"</prompt></block>");
}
}
catch (Exception e) {
System.err.println("An error occurred");
}
}
|
Listing 4의 코드는 텍스트의 프롬프트 블록을 출력하도록 설계되고, 하나는 전체 검색 정보(히트 수)이고, Yahoo 웹 검색 데이터베이스에서 찾은 각각의 결과 블록이다.
Listing 5는 이 프로세스에서 생성된 샘플 VXML이다.
Listing 5. 생성된 VXML
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1">
<form>
<block><prompt>Found 73600000 hits for britney spears. Detailing the top 10
results.</prompt></block>
<block><prompt>Britney Spears - The Official
Site.<break/></prompt></block>
<block><prompt>WORLDOFBRITNEY.COM.<break/>
</prompt></block>
<block><prompt>Britney Spears - britney.com - Jive
Records.<break/></prompt></block>
<block><prompt>Britney Spears Zone | Britney Divorce, Pregnant,
Baby Pictures, Pics &
News.<break/></prompt></block>
<block><prompt>britneyspears.org.<break/></prompt></block>
<block><prompt>WoBPictures.com [100030013].<break/>
</prompt></block>
<block><prompt>Britney Spears - Wikipedia, the free
encyclopedia.<break/></prompt></block>
<block><prompt>Britney Spears | Music Artist | Videos, News, Photos &
Ringtones | MTV.<break/></prompt></block>
<block><prompt>Britney Spears.<break/></prompt></block>
<block><prompt>Britney Spears - Yahoo! Music.<break/>
</prompt></block>
<disconnect/>
</form>
</vxml>
|
음성 브라우저가 말을 하면, 재미있는 방식으로 일부 정보를 기술한다. 아웃풋의 유형을 구분하려고 하기 때문이다. 예를 들어, 'WORLDOFBRITNEY.COM'은 글자들('W','O', 'R',...)처럼 출력될 것이다. 브라우저는 이것을 약어로 간주할 것이기 때문이다.
다른 값들은 음성 브라우저가 생각하는 대로 출력된다. 예를 들어, 히트 카운트는 "seventy three million, six hundred thousand"라고 정확히 말한다. 안타깝게도, "WoBPictures.com" 타이틀의 넘버는 순전한 숫자였던 것처럼 기술된다.
로컬 검색 실행하기
Yahoo 검색 시스템에서, 로컬 검색은 검색어와 위치에 기반한다. 위치를 지정할 수 있는 다양한 방식들이 있기 때문에, 검색 정보를 지정하는 메소드는 웹 검색 인터페이스 보다 복잡하다.
따라서, 로컬 검색의 경우, VoiceXML 선택 페이지에서 검색어와 위치를 수락하고 그 정보에 기반하여 검색을 실행한다. 시퀀스는 다음과 같다:
- Yahoo SearchClient 요청을 만든다.
- (
setLocation()을 사용하여) 검색용 위치를 설정한다.
- (
setQuery()를 사용하여) 검색용 쿼리를 설정한다.
검색 객체가 조립되면, 결과 데이터를 추출하는 기본 프로세스는 웹 검색 솔루션의 프로세스와 동일하다.
Listing 6은 실행 모습이다.
Listing 6. 로컬 검색에서 VoiceXML을 출력하기
public static void DoSearch (String term,String location) {
SearchClient client = new SearchClient("INSERTKEY");
LocalSearchRequest request = new LocalSearchRequest();
request.setLocation(location);
request.setQuery(term);
try {
LocalSearchResults results = client.localSearch(request);
System.out.println("<block><prompt>Found " +
results.getTotalResultsAvailable() +
" hits for " +
term + " in " + location +
". Detailing the top " +
results.getTotalResultsReturned() +
" results.</prompt></block>");
for (int i = 0; i < results.listResults().length; i++) {
LocalSearchResult result = results.listResults()[i];
Pattern pattern = Pattern.compile("&");
Matcher matcher = pattern.matcher(result.getTitle());
System.out.println("<block><prompt>" +
matcher.replaceAll("and") +
".<break/> Phone number: " +
result.getPhone() +
"</prompt></block>");
}
}
catch (Exception e) {
System.err.println("Error calling Yahoo! Search Service: " +
e.toString());
}
}
|
이 아웃풋에서 기억해야 할 한 가지는 앰퍼샌드(&) 문자와 "and"라는 단어를 교체한다는 점이다. 대부분의 VoiceXML 시스템은 대부분의 XML/HTML 이스케이프 문자들(이 경우, &이다. 이것은 &가 된다.)을 처리하지만, 일부 음성 브라우저들은 올바르게 이스케이프 되지 않은 것처럼 이 정보를 처리하지 않는다. (이것은 VXML 문서에서 XML의 효과를 떨어트린다.) 정확한 포맷으로 정보를 출력해야 한다. 위 예제의 경우, 정규식을 사용하여 대체 작업을 수행한다.
두 번째는 전화번호와 함께 회사의 이름을 출력한다는 점이다. 많은 음성 브라우저들은 넘버 포맷에서 전화번호를 구분하고, "nine hundred" 또는 "six hundred and six" 보다는 전화번호로서 숫자를 정확히 출력한다.
전체 VXML의 많은 예제를 보았다. 이제, 검색 결과를 출력할 기본적인 콘텐트 아웃풋(블록으로 구성됨)을 보자. (Listing 7).
Listing 7. 기본적인 콘텐트 결과
<block><prompt>Found 14 hits for plumber in New York.
Detailing the top 10 results.</prompt></block>
<block><prompt>State Plumbing Inspector.<break/>
Phone number: (606) 862-1297</prompt></block>
<block><prompt>Hibbitts Brothers Wholesale.<break/>
Phone number: (606) 864-2256</prompt></block>
<block><prompt>State Plumbing Inspector Paul Ray.<break/>
Phone number: (606) 862-1297</prompt></block>
<block><prompt>Willard Neeley Plumbing and Htg.<break/>
Phone number: (606) 864-6203</prompt></block>
<block><prompt>Vanhook Plumbing Htg and Cooling.<break/>
Phone number: (606) 862-8228</prompt></block>
<block><prompt>Rooter Man of South Eastern Ky.<break/>
Phone number: (606) 878-1339</prompt></block>
<block><prompt>Kettry Roaden Plumbing.<break/>
Phone number: (606) 528-3396</prompt></block>
<block><prompt>Prestige Marble.<break/>
Phone number: (606) 523-9186</prompt></block>
<block><prompt>Herb King Plumbing.<break/>
Phone number: (606) 364-4534</prompt></block>
<block><prompt>AAA Plumbing.<break/>
Phone number: (606) 528-0705</prompt></block>
|
이 아웃풋의 음성 버전은 그렇게 완벽하지 않다. "Vanhook Plumbing and Htg."의 "Htg"가 모두 판독된다. 음성 브라우저는 이 값을 "heating"으로 확장해야 한다는 것을 알고 있기 때문이다.
요약
이 글에서는 Yahoo 검색 API를 사용하여 Yahoo 웹 페이지 데이터베이스와 Yahoo 로컬 비즈니스 디렉토리 데이터베이스에 이루어진 검색에서 VXML을 출력하는 방법을 설명했다. 결과 솔루션에서, 사용자는 서비스를 호출하고, 시스템을 요청하여 New York에 있는 탑 10 배관공을 리스팅하거나, "java"와 "apple"을 언급하는 탑 10 사이트를 리스팅 한다. 자유 형식 구문 인풋으로는 구문, 단어, 이러한 단어와 구문의 한정된 결합을 지원하여 정밀한 검색을 가능케 한다.
또한, 표준 VoiceXML 브라우저 선택 시스템에서 사용되는 VXML을 생성하는 표준화된 메소드에 대해서도 살펴보았다.
VoiceXML 애플리케이션 개발을 하는 여러분에게 이 글이 도움이 되었기 바란다.
다운로드 하십시오 | 설명 | 이름 | 크기 | 다운로드 방식 |
|---|
| Part 4 샘플 코드 | x-voicexml4-search.zip | 3KB | HTTP |
|---|
참고자료 교육
-
Yahoo Developer Network: 서비스 검색 및 통합 관련 다운로드 및 자료.
-
자바 웹 개발자 프레임웍에서 VoiceXML 페이지 생성하기, Part 1: 자바 서블릿과 JSP를 사용하여 VoiceXML 생성하기 (Brett McLaughlin, developerWorks, 2006년 1월)
-
" 자바 웹 개발자 프레임웍에서 VoiceXML 페이지 생성하기, Part 2: 자바 기반 VoiceXML 애플리케이션 확대하기 (Brett McLaughlin, developerWorks, 2006년 1월)
-
VoiceXML 2.1 스펙
-
IBM XML 인증: XML 및 관련 기술 분야의 IBM 인증.
-
XML 기술 자료: developerWorks XML 존에 광범위한 기술 자료, 팁, 튜토리얼, 표준, IBM Redbook을 볼 수 있다.
-
developerWorks 기술이벤트와 웹캐스트
-
technology
bookstore
제품 및 기술 얻기
토론
필자소개  | 
|  | Martin Brown은 8년 경력의 전문 작가이다. 다양한 주제로 많은 책과 기술 자료을 쓰고 있다. Perl, Python, Java, JavaScript, Basic, Pascal, Modula-2, C, C++, Rebol, Gawk, Shellscript, Windows, Solaris, Linux, BeOS, Mac OS/X 같은 개발 플랫폼과 웹 프로그래밍, 시스템 관리와 통합 분야를 다루고 있다. Martin은 ServerWatch.com, LinuxToday.com, IBM developerWorks에 정기적으로 기고하고 있으며, Computerworld, The Apple Blog, Subject Matter Expert (SME) for Microsoft에 블로그를 운영하고 있다. (http://www.mcslp.com) |
기사에 대한 평가
|  |