프로그래밍 기술/XML.NET

[XML.NET] 25. OPEN API 활용

언제나휴일 2016. 4. 18. 14:02
반응형

OPEN API 활용



 OPEN API는 표준 웹 프로토콜을 이용하여 프로그램 개발에 사용할 수 있는 공개 API 입니다. 일반적으로 현실 세계에 있는 실제 데이터를 수집한 단체에서 개발자들이 개발하는 응용에서 사용할 수 있게 제공하고 있습니다. 이러한 OPEN API에서는 웹 쿼리로 검색 질의를 보내면 XML 문서 형태로 결과를 보내는 것이 일반적입니다.

 

 여기에서는 Naver 검색 API를 이용하여 도서를 검색하는 간단한 콘솔 응용을 제작하는 과정을 소개할게요.

 

 먼저 네이버 개발자센터에서  Application 메뉴를 선택하고 다시 애플리케이션 등록을 선택하세요.

[그림 5.2] 네이버 개발자 센터 - 내 애플리케이션 등록 선택


[그림 5.2] 네이버 개발자 센터 - 내 애플리케이션 등록 선택


 애플리케이션 이름을 정하고 사용 API 중에서 검색을 선택하세요. 환경추가에서 WEB설정을 선택하시고 웹 서비스 URL을 입력하세요. 만약 웹 서비스 URL을 소유하고 있는 것이 없다면 http://sample.co.kr로 입력하십시오.

[그림 5.3] 네이버 개발자 센터 - 내 애플리케이션 등록


[그림 5.3] 네이버 개발자 센터 - 내 애플리케이션 등록


 네이버 개발자센터의 내 애플리케이션 메뉴를 선택하여 등록한 애플리케이션을 선택하면 Open API를 사용하기 위해 발급한 ClientIDClientSecret을 확인할 수 있습니다.

[그림 5.4] 애플리케이션 정보

[그림 5.4] 애플리케이션 정보

 

 이제 네이버 개발자 센터의 [Document]=>[검색]을 선택하세요.

 [그림 5.5] 네이버 개발자 센터 - 검색 선택


[그림 5.5] 네이버 개발자 센터 - 검색 선택

 

 OpenAPI 서비스는 웹 서비스 URL을 이용합니다. 여기에서는 검색 서비스 중에 책을 검색하는 예를 사용할 것입니다. 네이버 개발자 센터에서 제공하는 Open APIXML 출력포멧 혹은 JSON 출력포멧으로 결과를 제공하고 있는데 여기에서는 XML 출력포멧을 이용할 것입니다. 책 검색 서비스의 XML 출력포멧으로 책기본검색과 책상세검색을 제공하는데 여기에서는 책기본검색을 사용할게요. 요청 URL 주소를 기록해 두세요.

[그림 5.6] 검색 서비스 -책 - API 기본 정보


[그림 5.6] 검색 서비스 - - API 기본 정보

 

  OpenAPI 서비스를 사용할 때는 요청 URL과 요청 변수를 결합하여 쿼리 문자열을 만들어서 사용합니다. 책 검색 서비스의 요청 변수는 검색하고자 하는 질의 문자열은 필수이며 이 외에 여러 종류의 요청 변수가 있습니다.

 

 쿼리 문자열을 만드는 방법은 요청 URL?요청 변수=&요청 변수=... 형태로 전달합니다. 예를 들어 책 검색 서비스 요청 URLhttps://openapi.naver.com/v1/search/book.xml과 요청 변수 query의 값이 언제나이고 display의 값이 15라고 가정한다면 쿼리 문자열은 다음과 같습니다.

https://openapi.naver.com/v1/search/book.xml?query=언제나&display=15

[그림 5.7] 검색 서비스 -책 - 요청 변수

[그림 5.7] 검색 서비스 - - 요청 변수

 

 

 

 

 책 검색 서비스를 이용하여 검색 요청을 하였을 때 검색 결과는 다음과 같습니다.

 [그림 5.8] 검색 서비스 -책 - 응답 예


[그림 5.8] 검색 서비스 - - 응답 예

  

 

 응답의 XML 요소들의 의미도 네이버 개발자 센터에서 확인할 수 있습니다. 다음은 책 검색 서비스 응답의 XML 요소에 관한 설명의 일부입니다.

[그림 5.9] 검색 서비스 -책 - 응답의 요소 설명


[그림 5.9] 검색 서비스 - - 응답의 요소 설명

  

 이제 프로그램에서 이를 사용하는 방법을 알아봅시다.

 

 도서 검색을 위해 먼저 검색할 도서명을 입력받습니다. 그리고 도서 검색 개체를 생성할게요. 도서 검색 개체는 검색할 도서명을 입력인자로 받아 검색 요청을 하고 검색한 결과를 출력하기로 할게요.

class Program

{

    static void Main(string[] args)

    {

        string book_name = string.Empty;

        Console.WriteLine("검색할 도서명을 입력하세요.");

        book_name = Console.ReadLine();

        BookSearcher bs = new BookSearcher();

        bs.Find(book_name);

        bs.View();

    }

}

 

 도서 검색을 위한 클래스로 BookSearcher 클래스와 검색한 도서를 위한 Book 클래스를 정의할게요. 도서 검색을 위한 BookSearcher 클래스는 생성자와 검색 요청하는 Find 메서드, 결과를 요청하는 View 메서드를 제공합시다.

class BookSearcher

{

    internal BookSearcher();

    internal void Find(string book_name);

    public void View();

}

 

 생성자에서는 검색 결과를 보관할 컬렉션 개체를 생성하기로 할게요.

internal BookSearcher()

{

    ar = new ArrayList();

 }

 

 도서를 검색하는 Find 메서드에서는 입력 받은 도서명으로 검색 질의를 만드세요. 그리고 검색 서비스 사용에 필요한 네이버 개발자 센터에서 내 애플리케이션의 Client IDCleint Secret을 변수에 설정하세요.

internal void Find(string book_name)

{

   this.book_name = book_name;

   string url = string.Format("https://openapi.naver.com/v1/search/book.xml?query={0}&display=20", name);

     string id = "[자신의 네이버 개발자 센터 Client-ID]";

     string secret = "[자신의 네이버 개발자 센터 Client-Secret]";

 

 

 웹 서비스 요청을 할 때 WebRequest 개체를 사용합니다. WebRequest 형식 개체는 WebRequest 클래스의 정적 메서드 Create에 요청 url을 입력 인자로 전달하여 생성할 수 있어요.

    WebRequest request = null;

    request = WebRequest.Create( url);

 

 네이버 검색 서비스를 사용하기 위해서는 요청할 때 Client IDClient Secret을 헤더에 추가하여 보내야 합니다.

    request.Headers.Add("X-Naver-Client-Id", id);

    request.Headers.Add("X-Naver-Client-Secret", secret);

 

 네이버 검색 서비스를 실제 사용하는 것은 WebRequest 개체의 GetResponse 메서드를 호출하는 것입니다.

    WebResponse response = request.GetResponse();

 

 이제 서비스 결과를 분석하여 프로그램의 데이터로 변환해야겠죠. 이처럼 A 포멧의 입력 데이터를 분석하여 자신의 원하는 형태로 변환하는 작업을 파싱(Parsing)작업이라 부르며 이러한 작업을 수행하는 것을 파서(Parser)라 부릅니다. 여기에서는 XmlDocument를 이용할 것입니다.

 

 XmlDocument 개체를 통해 분석하기 위해 응답 결과인 WebResponse 개체의 GetResponseStream 메서드를 호출하여 Stream 개체를 참조한 후에 이를 입력 인자로 XmlDocument 개체의 Load 메서드의 입력 인자로 전달합니다.

   Stream stream = response.GetResponseStream();

   XmlDocument xdoc = new XmlDocument();

   xdoc.Load(stream);

 

 도서 검색 문서에 루트 노드인 "rss" 노드를 선택하고 자식 노드인 "channel" 노드를 선택합니다.

 

XmlNode node = doc.SelectSingleNode("rss");

XmlNode n = node.SelectSingleNode("channel");

 

 그리고 반복해서 "item" 노드를 선택하여 해당 노드를 입력 인자로 Book 개체를 생성합니다. 생성한 Book 개체는 검색 결과를 보관하는 컬렉션에 추가합니다. 개체를 생성하는 것은 Book 클래스의 정정 메서드 MakeBook을 정의하여 생성하기로 할게요.

 

Book book = null;

foreach (XmlNode el in n.SelectNodes("item"))

{

    book = Book.MakeBook(el);

    ar.Add(book);

}

  

 검색 결과를 출력하는 View 메서드에서는 질의에 사용한 도서명을 출력한 후에 검색 결과를 보관한 컬렉션의 책의 정보를 출력하기로 할게요.

 

Console.WriteLine("질의문:{0}", book_name);

foreach (Book book in ar)

{

     Console.WriteLine(book.Title);

     Console.WriteLine("\t저자:{0}", book.Author);

     Console.WriteLine("\t출판사:{0}", book.Publisher);

     Console.WriteLine("\t가격:{0}", book.Price);

     Console.WriteLine("\t설명:{0}", book.Description);

}

 

 검색 결과인 책은 Book 클래스로 정의할게요. Book 클래스에는 검색 결과를 설정하고 얻어오는 멤버 속성과 생성자를 제공합니다. 각 속성의 설정을 의한 set 블록은 Book 클래스 내에서 접근 가능하게 private으로 설정하고 얻어오는 get 블록은 프로젝트 내에서 접근할 수 있게 internal로 지정할게요.

 

internal string Title{    get;    private set;}

internal string Author{    get;    private set;}

internal int Price{    get;    private set;}

internal string Publisher{    get;    private set;}

internal string Description{    get;    private set;}

 

 생성자 메서드도 Book 클래스 내에서 접근 가능하게 private으로 설정할게요. 실제 Book 개체를 생성하는 것은 정적 메서드인 MakeBook을 이용하게 할 것입니다.

internal Book(string title, string author, int price, string publisher, string description)

{

    Title = title;

    Author = author;

    Price = price;

    Publisher = publisher;

    Description = description;

}

  

 

 XmlNode 개체를 입력인자로 전달받아 Book 개체를 생성하여 반환하는 MakeBook 메서드의 알고리즘은 다음과 같습니다. 입력 인자로 전달받은 XmlNode 개체는 "item" 요소에 관한 XmlNode 개체입니다. 질의 결과는 item 자식 요소로 "title", "price", "publisher", "description" 등이 있습니다. 여기에서는 각 요소의 내부 텍스트를 얻어와서 "<" ">" 사이에 있는 문자열을 필터링하는 ConvertString 메서드를 이용하여 결과를 얻어올게요. 그리고 난 후에 얻은 결과를 입력 인자로 Book 개체를 생성하기로 합시다.

static internal Book MakeBook(XmlNode xn)

{

    string title = string.Empty;

    string author = string.Empty;

    int price = 0;

    string publisher = string.Empty;

    string description = string.Empty;

 

    XmlNode title_node = xn.SelectSingleNode("title");

    title = ConvertString(title_node.InnerText);

   XmlNode price_node = xn.SelectSingleNode("price");

   price = int.Parse(price_node.InnerText);

   XmlNode publisher_node = xn.SelectSingleNode("publisher");

   publisher = ConvertString(publisher_node.InnerText);

   XmlNode description_node = xn.SelectSingleNode("description");

   description = ConvertString(description_node.InnerText);

 

    return new Book(title, author, price, publisher, description);

}

private static string ConvertString(string str)

{

    int sindex = 0;

    int eindex = 0;

    while (true)

    {

        sindex = str.IndexOf('<');

        if (sindex == -1)

        {

            break;

        }

       eindex = str.IndexOf('>');

       str = str.Remove(sindex, eindex - sindex+1);

    }

    return str;

}

 

 

 

 다음은 도서 검색 응용 프로그램 코드입니다.

 

using System;

using System.Xml;

using System.Collections;

 

namespace 예제_5._4_도서_검색_응용

{

    class Book

    {

        internal string Title

        {

            get;

            private set;

        }

        internal string Author

        {

            get;

            private set;

        }

        internal int Price

        {

            get;

            private set;

        }

        internal string Publisher

        {

            get;

            private set;

        }

        internal string Description

        {

            get;

            private set;

        } 

 

        static internal Book MakeBook(XmlNode xn)

        {

            string title = string.Empty;

            string author = string.Empty;

            int price = 0;

            string publisher = string.Empty;

            string description = string.Empty;

 

            XmlNode title_node = xn.SelectSingleNode("title");

            title = ConvertString(title_node.InnerText);

            XmlNode price_node = xn.SelectSingleNode("price");

            price = int.Parse(price_node.InnerText);

            XmlNode publisher_node = xn.SelectSingleNode("publisher");

            publisher = ConvertString(publisher_node.InnerText);

            XmlNode description_node = xn.SelectSingleNode("description");

            description = ConvertString(description_node.InnerText);

 

            return new Book(title, author, price, publisher, description);

        }

 

        internal Book(string title, string author, int price, string publisher, string description)

        {

            Title = title;

            Author = author;

            Price = price;

            Publisher = publisher;

            Description = description;

        }

 

        private static string ConvertString(string str)

        {

            int sindex = 0;

            int eindex = 0;

            while (true)

            {

                sindex = str.IndexOf('<');

                if (sindex == -1)

                {

                    break;

                }

                eindex = str.IndexOf('>');

                str = str.Remove(sindex, eindex - sindex+1);

            }

            return str;

        }

        public override string ToString()

        {

            return Title;

        }

    }

 

    class BookSearcher

    {

        ArrayList ar = new ArrayList();

        string book_name;

        internal BookSearcher()

        {

            ar = new ArrayList();

        }

        internal void Find(string book_name)

        {

            this.book_name = book_name;

            string url = string.Format("https://openapi.naver.com/v1/search/book.xml?query={0}&display=20", book_name);

        string id = "[자신의 Client ID]";

        string secret = "[자신의 Client Secret]";

 

        WebRequest request = null;

        request = WebRequest.Create( url);

        request.Headers.Add("X-Naver-Client-Id", id);

        request.Headers.Add("X-Naver-Client-Secret", secret);

 

        WebResponse response = request.GetResponse();

        Stream stream = response.GetResponseStream();

 

        XmlDocument xdoc = new XmlDocument();

        xdoc.Load(stream);

            XmlNode node = doc.SelectSingleNode("rss");

            XmlNode n = node.SelectSingleNode("channel");

           

            Book book = null;

            foreach (XmlNode el in n.SelectNodes("item"))

            {

                book = Book.MakeBook(el);

                ar.Add(book);

            }

        }

 

        public void View()

        {

            Console.WriteLine("질의문:{0}", book_name);

 

            foreach (Book book in ar)

            {

                Console.WriteLine(book.Title);

                Console.WriteLine("\t저자:{0}", book.Author);

                Console.WriteLine("\t출판사:{0}", book.Publisher);

                Console.WriteLine("\t가격:{0}", book.Price);

                Console.WriteLine("\t설명:{0}", book.Description);

            }

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            string book_name = string.Empty;

            Console.WriteLine("검색할 도서명을 입력하세요.");

            book_name = Console.ReadLine();

            BookSearcher bs = new BookSearcher();

            bs.Find(book_name);

            bs.View();

        }      

    }

}

[소스 5.4] OPEN API를 이용한 도서 검색 예제 코드

 

 

 

반응형