안녕하십니까? Visual C# MVP / Windows Azure Cafe SYSOP / DEVPIA C# Forum SYSOP / Visual Studio 2010 한국 공식 팀 블로그 멤버 남정현입니다.

2010년 9월 13일부터 15일까지 열리는 Korea Games Conference (KGC) 2010에서 13일 오전 10시 30분에 오디토리움 101에서 진행되는 세션을 맡게 되었습니다. Windows Azure Platform과 소셜 게임이라는 주제를 바탕으로, 클라우드 컴퓨팅, Rich Internet Application 기술의 결합과 발전 방향성을 한 시간 동안 설명할 예정입니다. 또한, 이날 오전 세션은 Visual Studio 2010 한국 공식 팀 블로그의 DirectX 및 Agile Development 부문 전문가분들의 세션이 연속으로 진행되므로 관심있으신 분들께서는 함께 해주시면 감사하겠습니다. :-)

관심있으신 분들의 많은 참석을 부탁드리며, 여러모로 의미있는 시간이 되었으면 합니다. 감사합니다. :-)

등록 신청하기: http://www.kgconf.com/

세션 정보 자세히 보기

등록 신청하기: http://www.kgconf.com/

저작자 표시 비영리 동일 조건 변경 허락
이 장소를 Daum지도에서 확인해보세요.
서울특별시 강남구 삼성1동 | 코엑스
도움말 Daum 지도
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

네이버 오픈 API를 데이터 소스로 사용하여 Windows Forms에 Binding하는 샘플을 간단히 만들어보았습니다. 지난번에 예를 들었던 난수 생성을 위한 데이터 소스에서 언급했던 IListSource 인터페이스의 사용법을 기초로 발전시킨 샘플입니다. :-)

 

using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Data;
using System.Text;
using System.Collections;
using System.Globalization;
using System.ComponentModel;

namespace OpenApiBinding
{
    [ToolboxItem(true)]
    [DesignTimeVisible(true)]
    public partial class NaverSearchBinding : Component, IListSource
    {
        public NaverSearchBinding()
            : this(null)
        {
        }

        public NaverSearchBinding(Container container)
            : base()
        {
            if (container != null)
                container.Add(this);

            this.InitializeComponent();

            this.key = String.Empty;
            this.target = NaverSearchTarget.WebDocuments;
            this.query = String.Empty;
            this.display = 100;
            this.start = 1;
            this.sort = NaverSortMode.Similarity;
        }

        private string key;
        private NaverSearchTarget target;
        private string query;
        private int display;
        private int start;
        private NaverSortMode sort;

        [NonSerialized]
        private const string RequestUrl = "http://openapi.naver.com/search";

        [Browsable(true)]
        [DefaultValue("")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string Key
        {
            get { return this.key; }
            set { this.key = (value ?? String.Empty).Trim(); }
        }

        [Browsable(true)]
        [DefaultValue(NaverSearchTarget.WebDocuments)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public NaverSearchTarget Target
        {
            get { return this.target; }
            set { this.target = value; }
        }

        [Browsable(true)]
        [DefaultValue("")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string Query
        {
            get { return this.query; }
            set { this.query = (value ?? String.Empty).Trim(); }
        }

        [Browsable(true)]
        [DefaultValue(100)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Display
        {
            get { return this.display; }
            set { this.display = value; }
        }

        [Browsable(true)]
        [DefaultValue(1)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Start
        {
            get { return this.start; }
            set { this.start = value; }
        }

        [Browsable(true)]
        [DefaultValue(NaverSortMode.Similarity)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public NaverSortMode Sort
        {
            get { return this.sort; }
            set { this.sort = value; }
        }

        public override string ToString()
        {
            return String.Format(
                CultureInfo.CurrentCulture,
                "{{ Target: '{0}', Query: '{1}' }}",
                this.target,
                this.query);
        }

        private Uri CreateUri()
        {
            if (String.IsNullOrEmpty(this.key))
                return null;

            StringBuilder buffer = new StringBuilder();
            buffer.AppendFormat("key={0}&", this.key);

            switch (this.target)
            {
                case NaverSearchTarget.Blog:
                    buffer.Append("target=blog&");
                    break;

                case NaverSearchTarget.Cafe:
                    buffer.Append("target=cafe&");
                    break;

                case NaverSearchTarget.CafeArticles:
                    buffer.Append("target=cafearticle&");
                    break;

                case NaverSearchTarget.News:
                    buffer.Append("target=news&");
                    break;

                default:
                case NaverSearchTarget.WebDocuments:
                    buffer.Append("target=webkr&");
                    break;
            }

            buffer.AppendFormat("query={0}&", this.query);
            buffer.AppendFormat("display={0}&", this.display);
            buffer.AppendFormat("start={0}&", this.start);

            switch (this.sort)
            {
                default:
                case NaverSortMode.Similarity:
                    buffer.Append("sort=sim");
                    break;

                case NaverSortMode.Date:
                    buffer.Append("sort=date");
                    break;

                case NaverSortMode.Member:
                    buffer.Append("sort=member");
                    break;

                case NaverSortMode.NewArticles:
                    buffer.Append("sort=newArticles");
                    break;

                case NaverSortMode.Rank:
                    buffer.Append("sort=rank");
                    break;
            }

            return new Uri(String.Concat(RequestUrl, '?', buffer.ToString()));
        }

        public IList GetList()
        {
            Uri requestUri = this.CreateUri();

            if (requestUri == null)
                return null;

            WebRequest webRequest = WebRequest.Create(requestUri);

            using (WebResponse webResponse = webRequest.GetResponse())
            {
                using (Stream webResponseStream = webResponse.GetResponseStream())
                {
                    XmlDocument xmlDocument = new XmlDocument();
                    xmlDocument.Load(webResponseStream);

                    DataTable inferencedTable = new DataTable(this.target.ToString());

                    switch (this.target)
                    {
                        case NaverSearchTarget.Blog:
                            inferencedTable.Columns.Add("title", typeof(string));
                            inferencedTable.Columns.Add("link", typeof(string));
                            inferencedTable.Columns.Add("description", typeof(string));
                            inferencedTable.Columns.Add("bloggername", typeof(string));
                            inferencedTable.Columns.Add("bloggerlink", typeof(string));
                            break;

                        case NaverSearchTarget.Cafe:
                            inferencedTable.Columns.Add("title", typeof(string));
                            inferencedTable.Columns.Add("link", typeof(string));
                            inferencedTable.Columns.Add("description", typeof(string));
                            inferencedTable.Columns.Add("ranking", typeof(string));
                            inferencedTable.Columns.Add("member", typeof(string));
                            inferencedTable.Columns.Add("totalarticles", typeof(string));
                            inferencedTable.Columns.Add("newarticles", typeof(string));
                            break;

                        case NaverSearchTarget.CafeArticles:
                            inferencedTable.Columns.Add("title", typeof(string));
                            inferencedTable.Columns.Add("link", typeof(string));
                            inferencedTable.Columns.Add("description", typeof(string));
                            inferencedTable.Columns.Add("cafename", typeof(string));
                            inferencedTable.Columns.Add("cafeurl", typeof(string));
                            break;

                        case NaverSearchTarget.News:
                            inferencedTable.Columns.Add("title", typeof(string));
                            inferencedTable.Columns.Add("link", typeof(string));
                            inferencedTable.Columns.Add("description", typeof(string));
                            inferencedTable.Columns.Add("originallink", typeof(string));
                            inferencedTable.Columns.Add("pubDate", typeof(string));
                            break;

                        default:
                        case NaverSearchTarget.WebDocuments:
                            inferencedTable.Columns.Add("title", typeof(string));
                            inferencedTable.Columns.Add("link", typeof(string));
                            inferencedTable.Columns.Add("description", typeof(string));
                            break;
                    }

                    foreach (XmlNode eachNode in xmlDocument.SelectNodes("/rss/channel/item"))
                    {
                        XmlElement eachElement = eachNode as XmlElement;

                        if (eachElement == null)
                            continue;

                        int i = 0;
                        object[] values = new object[inferencedTable.Columns.Count];

                        foreach (DataColumn eachColumn in inferencedTable.Columns)
                            values[i++] = eachElement.SelectSingleNode(eachColumn.ColumnName).InnerXml;

                        inferencedTable.Rows.Add(values);
                    }

                    return inferencedTable.DefaultView;
                }
            }
        }

        public bool ContainsListCollection
        {
            get { return true; }
        }
    }

    [Serializable]
    public enum NaverSearchTarget : int
    {
        Blog,
        Cafe,
        CafeArticles,
        WebDocuments,
        News
    }

    [Serializable]
    public enum NaverSortMode : int
    {
        Similarity,
        Date,
        Member,
        NewArticles,
        Rank
    }
}

 

위의 소스 코드를 프로젝트에 추가하여 Windows Forms – 또는 – ASP.NET 프로젝트에 연결하거나, 독립적으로 객체를 만들어서 사용하는 것이 가능합니다. 다음은 Windows Forms 디자인 타임에서의 사용 예시입니다.

 

 

컴포넌트에서 API Key를 Key 프로퍼티에 설정하고, 검색어를 Query 프로퍼티에 설정하여 검색 결과를 수신할 수 있습니다. 데이터 그리드를 이용하여 수신한 데이터를 곧바로 보여줄 수도 있습니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

사용자 삽입 이미지

Microsoft Live Labs Volta 프로젝트 (이하 Volta 프로젝트)는 Technology Preview 단계의 프로젝트로서 클라이언트 응용프로그램에서 사용하던 프로그래밍 기법 (플랫폼 특정적인 기법이 아닌 디자인 패턴과 같은 주제들)을 웹 응용프로그램에서도 손쉽게 적용할 수 있는 모델을 구현하는 독특한 프로젝트입니다. 이름에서 알 수 있듯이 "빠르고 간편함"을 강조하고 있습니다.

Volta 프로젝트를 통하여 완성할 수 있는 응용프로그램은 상당히 특이한 모양을 지니고 있습니다. Volta Application Server를 통하여 실행할 수 있도록 간단한 스텁 코드와 컨텐츠 서버만이 제공된 상태에서 이를 Volta Application Server나 IIS 호스팅 환경 상에 게시하여 로컬 컴퓨터와 인터넷 응용프로그램으로의 Formation 전환이 손쉽게 되어있습니다.

Volta 프로젝트를 통해서 다계층 응용프로그램, AJAX 기반 웹 응용프로그램, 스마트 클라이언트와의 통합, Open API 매쉬업 등 최근 이슈가 되고 있는 다양한 웹 2.0 기술들을 한 번에 해결할 수 있게 하여 "새로운 것"에 대한 부담감을 개발자들에게서 덜어내고자 하는 것이 프로젝트의 궁극적인 목표라고 합니다.

Volta는 앞서 언급한 대로 Technology Preview 단계에 있기 때문에 기술적인 한계와 불편함이 아직 남아있으며, 발견되지 않은 문제점들도 있을 가능성이 있습니다. 제일 큰 걸림돌은 Volta가 동적으로 생성하는 JavaScript 코드와 라이브러리가 무겁고, 다운로드 시간과 처리 속도가 느리다는 단점이 있습니다. 이 문제는 향후 Volta 프로젝트가 정식 버전에 가까워질수록 많은 개선이 있을 것입니다.

조만간 Volta 프로젝트 기반의 응용프로그램에 대한 상세한 원리와 기술적 접근을 블로그에 별도의 카테고리로 개설하여 강좌를 올릴 예정이니 많은 관심 바랍니다.

Volta 공식 홈페이지: http://labs.live.com/volta
Volta 팀 블로그: http://labs.live.com/volta/blog/


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

1. 설치하기: 아래의 압축 파일을 풀면 msi 파일과 exe 파일이 저장되는데 이 중 setup.exe 파일을 실행하여 설치를 진행하실 수 있습니다. - 또는 - Winzip이나 알집의 자동 설치를 이용하여 간편하게 설치를 완료하실 수 있습니다.

2. 안내자료: 실행하기 전에 꼭 아래의 문서를 참조하시기 바랍니다. (Microsoft PowerPoint 2007 PPTX / Adobe Reader Compliant PDF)

3. 프로젝트 리포지터리: http://sources.clifx.com:8080/clifxmashup


크리에이티브 커먼즈 라이선스
Creative Commons License

'Project Blend: > Freewares' 카테고리의 다른 글

Oracle Table Dump Utility  (0) 2009/07/10
文房四友(문방사우)를 소개합니다!  (0) 2008/02/12
CLIFX Regular Expression Tester  (0) 2008/02/01
Posted by Windows Azure MVP 남정현 (rkttu.com)