NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    Web 2부 - 마이크로소프트 빙 기계 번역 API 사용하기. (Microsoft Translator Bing API)

    페이지 정보

    본문

    안녕하세요. 소심비형입니다. 요즘 상당히 우울한 하루를 보내고 있습니다ㅠㅠ; 새로운 사업을 구상하여 여러 투자사에 사업 계획서를 보냈지만 긍정적인 대답을 받지는 못했네요. 최대한 인맥을 통해 지인 투자도 알아보고 있지만, 생각처럼 쉽게 되지는 않는군요^^; 인큐베이팅이나 엑셀레이터 투자자 소개에는 예비 창업자도 지원 가능하다고 되어 있지만, 막상 진행되는 상황을 보면 어느정도 개발이 진행되고 있어야 하는듯합니다. 12군데 중에서 2군대에서 리젝되고 한군데는 아이디어가 참신하고 재미있다는 연락을 받았네요. 나머지 9곳은 아직도 접수중인걸 보면 시간이 꽤나 흘러야 어느정도 답이 나올듯 보입니다. 아이디어와 사업 계획서만으로 인큐베이팅 회사를 만날 수 있다면... 좋겠네요-_-;

    7HneGrI.jpg

     

     

    이전 시간에 이어서 실제 코드를 통해 번역 서비스를 구현해 보겠습니다. ASP.NET을 이용하여 구현하는 방법은 아래 링크를 통해 확인할 수 있습니다.

    https://blogs.msdn.microsoft.com/translation/walkthrough/gettingstarted2/

     

    번역기 위젯을 사용하려면 아래 링크를 통해 확인할 수 있습니다.

    https://blogs.msdn.microsoft.com/translation/2012/12/28/building-an-asp-net-web-app-with-the-microsoft-translator-widget-and-api/

     

    아래 내용은 이 홈페이지에서 서비스하고 있는 [ 자막 변환기 ]에 기능을 추가하는 방식으로 설명합니다. 단순히 윈폼을 이용하여 구현한다는 뜻이죠-_-;

     

    시작...

    아래와 같이 TranslatorView 윈폼을 추가한 후 컨트롤들을 배치하세요. Label 컨트롤 2개와 ComboBox 컨트롤 3개, Button 컨트롤 2개를 던져 놓으세요. 중간에 HR(중간쯤 위 아래를 구분하기 위해 추가한 바 형태의 컨트롤)이 있는데요. 이녀석의 정체는 Label입니다. 저런 모양의 컨트롤을 찾기 위해 시간을 낭비하지 마시길 바랍니다. Label 컨트롤을 이용해서 HR 컨트롤을 표현하려면 아래 링크를 참조하세요.

    HTML의 HR(Horizontal Rule) 컨트롤을 C# 윈폼으로 만들기. ]

    A9TSWgu.png

     

     

    아래 그림과 같이 각 컨트롤들의 아이디를 설정합니다.

    I7Fdlf7.png

     

     

    하얀 바탕에 파란 숫자가 있는 4개의 컨트롤만 설정하면 됩니다. (숫자는 탭 순서를 나타내며, 파란 바탕에 하얀 숫자는 탭키를 눌러도 적용받지 않는 컨트롤입니다.)

    1. cboTranslator

    2. cboStart

    3. cboEnd

    4. translator

    5. close

     

    BPXvGTo.jpg

     

     

    F7을 눌러서 소스 보기로 이동합니다. 0, 1, 2번의 콤보박스를 초기화 해주는 코드를 추가하세요.

    TranslatorView.cs

    public TranslatorView()
    {
        InitializeComponent();
     
        ComboBoxSettings();
        cboTranslator.SelectedIndex = 0;
        cboStart.SelectedIndex = 0;
        cboEnd.SelectedIndex = 1;
    }

     

     

    위 코드에서 ComboBoxSettings메소드를 아래와 같이 구현합니다.

    TranslatorView.cs

    private void ComboBoxSettings()
    {
        Dictionary translator = new Dictionary();
        translator.Add("MICROSOFT", "Microsoft Translator (Bing API)");
        translator.Add("NAVER", "NAVER Translator (NAVER API)");
        translator.Add("GOOGLE", "Google Translator (Google API)");
        Dictionary lang = new Dictionary();
        lang.Add("ko-kr", "한국어");
        lang.Add("en-us", "영어");
        lang.Add("zh-cn", "중국어");
        lang.Add("ja-jp", "일본어");
        cboStart.DataSource = new BindingSource(lang, null);
        cboStart.DisplayMember = "Value";
        cboStart.ValueMember = "Key";
        cboEnd.DataSource = new BindingSource(lang, null);
        cboEnd.DisplayMember = "Value";
        cboEnd.ValueMember = "Key";
    }

     

     

    Button 2개를 모두 더블 클릭하여 이벤트를 추가합니다. 먼저 가장 쉬운 close 버튼부터 처리하죠. 코드는 아래와 같습니다.

    TranslatorView.cs

    private void close_Click(object sender, EventArgs e)
    {
        this.Close();
    }

     

     

    핵심 코드인 번역 기능을 만들어야 합니다. 이 코드는 반복해서 사용되어야 하므로 별도의 클래스를 추가하여 처리하도록 합니다. 그리고 Microsoft, Naver, Google 번역기등... 여러가지 번역 API를 사용하기 위해 인터페이스도 추가합니다.

    ITranslator.cs

    namespace NGMASTERSubtitleConverter.Behaviors
    {
        public interface ITranslator
        {
            string Translate(string text, string from, string to);
        }
    }

     

     

    마이크로소프트 번역 서비스를 이용하기 위한 클래스를 만듭니다. 물론, ITranslator를 상속 받아야겠죠. 우선 Windows Azure 마켓플레이스 서비스에서 반환되는 정보를 저장하는 AdmAccessToken 클래스를 정의해야 합니다. 이 클래스는 변경할 수 없습니다. Azure 마켓플레이스 서비스에 매핑되기 때문이죠^^;

    BingTranslator.cs

    [DataContract]
    public class AdmAccessToken
    {
        [DataMember] public string access_token { get; set; }
        [DataMember] public string token_type { get; set; }
        [DataMember] public string expires_in { get; set; }
        [DataMember]
        public string scope
        {
            get; set;
        }
    }

     

     

    이 클래스는 번역 기능을 사용하기 위한 윈도우 에저 마켓 플레이스 서비스를 호출할 때 사용합니다. 번역 서비스를 호출하고 반환되는 정보를 이 클래스에 저장합니다. 이 서비스를 사용하기 위해 아래와 같이 네임스페이스를 추가합니다.

    • System.Runtime.Serialization

    • System.Xml.Linq

    • System.ServiceModel.Web

     

     

    이제 코드를 하나씩 살펴보도록 하겠습니다. AdmAccessToken을 이용하여 번역 서비스를 호출하고, 서비스를 사용할 ClientID와 ClientSecret을 전달합니다. Callback을 통해 서비스로부터 인증된 토큰을 Json 개체로 받아서 AdmAccessToken을 역직렬화합니다.

    BingTranslator.cs

    public class AdmAuthentication
    {
        public static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
        private string clientId; private string clientSecret;
        private string request;
        private AdmAccessToken token;
        private Timer accessTokenRenewer;
        private const int RefreshTokenDuration = 9;
        public AdmAuthentication(string clientId, string clientSecret)
        {
            this.clientId = clientId;
            this.clientSecret = clientSecret;
            this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
            this.token = HttpPost(DatamarketAccessUri, this.request);
            accessTokenRenewer = new Timer(new TimerCallback(OnTokenExpiredCallback), this, TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
        }
        public AdmAccessToken GetAccessToken() { return this.token; }
        private void RenewAccessToken()
        {
            AdmAccessToken newAccessToken = HttpPost(DatamarketAccessUri, this.request);
            this.token = newAccessToken;
        }
        private void OnTokenExpiredCallback(object stateInfo)
        {
            try
            { RenewAccessToken(); }
            catch (Exception ex) { Console.WriteLine(string.Format("Failed renewing access token. Details: {0}", ex.Message)); }
            finally
            {
                try
                { accessTokenRenewer.Change(TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1)); }
                catch (Exception ex)
                {
                    Console.WriteLine(string.Format("Failed to reschedule the timer to renew access token. Details: {0}", ex.Message));
                }
            }
        }
        private AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
        {
            WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "POST";
            byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
            webRequest.ContentLength = bytes.Length;
            using (Stream outputStream = webRequest.GetRequestStream())
            { outputStream.Write(bytes, 0, bytes.Length); }
            using (WebResponse webResponse = webRequest.GetResponse())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
                return token;
            }
        }
    }

     

     

    AdmAuthentication클래스를 이용하여 AccessToken을 가져옵니다. 이 토큰은 웹서비스를 호출하는 인증 토큰입니다. 당연하겠지만 이 예제를 따라하는 사용자마다 다릅니다. 인증 토큰을 사용하여 번역 서비스를 요청하고, 응답을 받습니다. 아래는 전체 소스입니다.

    BingTranslator.cs

    using System;
    using System.IO;
    using System.Net;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Json;
    using System.Text;
    using System.Threading;
    using System.Web;
    namespace NGMASTERSubtitleConverter.Behaviors
    {
        public class BingTranslator : ITranslator
        {
            private AdmAuthentication _auth; public BingTranslator(string clientID, string clientSecret) { _auth = new Behaviors.AdmAuthentication(clientID, clientSecret); }
            public string Translate(string text, string from, string to)
            {
                string uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + System.Web.HttpUtility.UrlEncode(text) + "&from=" + from + "&to=" + to;
                string authToken = "Bearer" + " " + _auth.GetAccessToken().access_token;
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
                httpWebRequest.Headers.Add("Authorization", authToken);
                WebResponse response = null;
                try
                {
                    response = httpWebRequest.GetResponse();
                    using (Stream stream = response.GetResponseStream())
                    {
                        System.Runtime.Serialization.DataContractSerializer dcs = new System.Runtime.Serialization.DataContractSerializer(Type.GetType("System.String"));
                        return (string)dcs.ReadObject(stream);
                    }
                }
                catch (Exception ex)
                {
                    return string.Format("ERROR: {0}", ex.Message);
                }
            }
        }
        [DataContract]
        public class AdmAccessToken
        {
            [DataMember]
            public string access_token { get; set; }
            [DataMember]
            public string token_type { get; set; }
            [DataMember]
            public string expires_in { get; set; }
            [DataMember]
            public string scope { get; set; }
        }
        public class AdmAuthentication
        {
            public static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
            private string clientId;
            private string clientSecret;
            private string request;
            private AdmAccessToken token;
            private Timer accessTokenRenewer;
            private const int RefreshTokenDuration = 9;
            public AdmAuthentication(string clientId, string clientSecret)
            {
                this.clientId = clientId;
                this.clientSecret = clientSecret;
                this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
                this.token = HttpPost(DatamarketAccessUri, this.request);
                accessTokenRenewer = new Timer(new TimerCallback(OnTokenExpiredCallback), this, TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
            }
            public AdmAccessToken GetAccessToken() { return this.token; }
            private void RenewAccessToken()
            {
                AdmAccessToken newAccessToken = HttpPost(DatamarketAccessUri, this.request);
                this.token = newAccessToken;
            }
            private void OnTokenExpiredCallback(object stateInfo)
            {
                try
                { RenewAccessToken(); }
                catch (Exception ex) { Console.WriteLine(string.Format("Failed renewing access token. Details: {0}", ex.Message)); }
                finally
                {
                    try
                    { accessTokenRenewer.Change(TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1)); }
                    catch (Exception ex)
                    {
                        Console.WriteLine(string.Format("Failed to reschedule the timer to renew access token. Details: {0}", ex.Message));
                    }
                }
            }
            private AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
            {
                WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.Method = "POST";
                byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
                webRequest.ContentLength = bytes.Length;
                using (Stream outputStream = webRequest.GetRequestStream())
                {
                    outputStream.Write(bytes, 0, bytes.Length);
                }
                using (WebResponse webResponse = webRequest.GetResponse())
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                    AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
                    return token;
                }
            }
        }
    }

     

     

    다음에는 네이버 번역 API를 사용하는 방법에 대해 알아보겠습니다.

    다음 시간에...

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.