Kakao 번역 API와 .NET 음성 Speech를 이용한 번역 나래이터 만들기 2. 번역 라이브러리 만들기[C#]

안녕하세요. 언제나 휴일, 언휴예요.

이번 강의는 번역 나래이터 만들기 중에서 첫 번째 프로젝트인 번역기 라이브러리 제작입니다.

번역기 라이브러리는 Kakao 번역 API를 이용하여 구현합니다.

C# 클래스 라이브러리(.NET Framework) 프로젝트를 생성한 후에 파일 명을 KakaoTranslAPI.cs로 변경하세요.

지원 언어 형식을 열거형으로 정의

카카오 개발자센터에 가서 문서>번역>공통 가이드를 보시면 번역 지원 언어를 알 수 있어요. 이 중에서 표기 부분을 기록해 놓으세요.

카카오 언어 번역

지원 언어를 열거형으로 표현합시다. 라이브러리로 제작할 것입니다. 형식 접근 지정자를 public으로 명시할게요.

    ///
    /// 언어 정보 열거형
    /// 
    public enum LanguageInfo
    {
        kr, en, jp, cn, vi, id, ar, bn, de, es, fr, hi, it, ms, nl, pt, ru, th, tr, MAX_LI

    }

개발 가이드를 보면 번역을 요청할 때 번역할 내용, 소스 언어, 번역할 언어를 전달해 줍니다. 그리고 결과는 문장 단위로 번역하여 문자열 배열 형태의 json 문자열을 반환합니다.

번역 요청 클래스 정의 및 구현

요청에 사용할 siteurl과 쿼리 문자열 형태 및 결과 부분을 보고 만들어야 합니다. 해당 페이지는 개발 도중에 참고해야겠죠.

번역 API

 

KakaoTransAPI 클래스는 번역을 위한 네 가지 기능을 제공하는 정적 클래스로 정의합시다.

카카오 번역 API에서는 번역을 요청하면 입력 인자로 전달받은 쿼리에 개행문자를 기준으로 번역합니다.

그리고 결과는 문자열 하나가 아닌 문자열 컬렉션을 Json 문자열로 반환합니다.

여기에서는 반환 결과가 문자열과 문자열 컬렉션을 반환하는 형태를 모두 제공할 거예요.

제공할 메서드는 “질의, 소스 언어, 타겟 언어”를 입력 인자로 전달받아 번역하는 메서드 두 개를 제공할 거예요.

그리고 “질의”를 입력 인자로 전달받아 번역하는 두 개를 제공합시다.

“질의” 하나를 입력 인자로 받는 메서드는 소스 언어는 “한국어”, 타겟 언어는 “영어”로 번역 요청합니다.

    ///
    /// 카카오 음성 API - 정적 클래스
    /// 
    public static class KakaoTransApi
    {
        ///
        /// 검색 메서드
        /// 
        ///질의
        ///원본 언어
        ///타겟 언어
        /// 번역 결과(문자열 리스트)
        public static List Search(string query, LanguageInfo src_lang, LanguageInfo target_lang)
        {
            return null;
        }
        ///
        /// 검색 메서드
        /// 
        ///질의
        /// 번역 결과(문자열 리스트)
        public static List Search(string query)
        {
            return Search(query, LanguageInfo.kr, LanguageInfo.en);
        }
        ///
        /// 번역 메서드
        /// 
        ///질의
        ///원본 언어
        ///타겟 언어
        /// 번역 결과 문자열
        public static string Translate(string query, LanguageInfo src_lang, LanguageInfo target_lang)
        {
            return null;
        }
        ///
        /// 번역 메서드
        /// 
        ///질의
        /// 번역 결과 (문자열 리스트)
        public static string Translate(string query)
        {
            return Translate(query,LanguageInfo.kr, LanguageInfo.en);
        }
    }

먼저 Translate(query, src_lang, target_lang) 메서드에서는 Search 메서드를 호출하여 번역 결과를 얻어옵니다.

결과로 얻어온 문자열 컬렉션의 각 항목을 이어 붙여서 하나의 문자열로 만들어 반환합니다. String 클래스보다 StringBuilder 클래스의 효율이 높아서 이를 사용하여 만들었어요.

        ///
        /// 번역 메서드
        /// 
        ///질의
        ///원본 언어
        ///타겟 언어
        /// 번역 결과 문자열
        public static string Translate(string query, LanguageInfo src_lang, LanguageInfo target_lang)
        {
            List strs = Search(query, src_lang, target_lang);
            StringBuilder sb = new StringBuilder();
            foreach (string s in strs)
            {
                sb.Append(s);
            }
            return sb.ToString();
        }

결국 우리가 만들 메서드는 Search(query, src_lang, target_lang)입니다.

번역 요청할 사이트 주소와 입력 인자로 전달받은 값으로 쿼리 문자열을 만드세요.

//            string site = "https://kapi.kakao.com/v1/translation/translate";
// 카카오 번역 API 버전이 업그레이드 되면서 siteurl에 변경이 생겼습니다.
            string site = "https://dapi.kakao.com/v2/translation/translate";
            string rquery = string.Format("{0}?query={1}&src_lang={2}&target_lang={3}", site, query, src_lang, target_lang);

웹 요청 개체를 생성하고 발급받은 자신의 카카오 REST API 키를 헤더에 첨부합니다.

            WebRequest request = WebRequest.Create(rquery);
            string rkey = "[발급받은 자신의 카카오 REST API 키";
            string header = "KakaoAK " + rkey;
            request.Headers.Add("Authorization", header);

웹 결과를 요청합니다. 그리고 이를 선형적인 방법으로 Json 문자열을 읽습니다.

            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream, Encoding.UTF8);
            String json = reader.ReadToEnd();

Json 방식의 문자열을 분해하여 원하는 형식 데이터로 변환할 때 JavaScriptSerializer 형식 개체를 많이 사용합니다. 이를 위해 System.Web.Extentions 어셈블리를 참조 추가합니다.

이제 JavaScriptSerializer 형식 개체를 생성하세요. 그리고 결과를 동적 형식으로 역직렬화합니다.

            JavaScriptSerializer js = new JavaScriptSerializer();
            dynamic dob = js.Deserialize(json);

결과 중에 “translated_text” 항목을 얻어옵니다. 그리고 이들의 내부 요소 항목을 얻어옵니다.

             dynamic docs = dob["translated_text"];

docs에는 문자열 컬렉션이 올 수 있습니다. 컬렉션의 크기를 얻어옵니다. 그리고 각 항목을 문자열로 변환하여 결과 컬렉션에 보관합니다. 이번에는 내부 항목에 별다른 키워드가 없어서 인덱서에 0을 첨부합니다. ‘

            int length = ((object[])).Length;
            List strs = new List();
            for (int i = 0; i < length; i++)
            {
                strs.Add(docs[i][0]);
            }

            return strs;

다음은 KakaoTransAPI.cs 소스 코드입니다.

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web.Script.Serialization;

namespace WrapKakaoLib
{
    ///
    /// 언어 정보 열거형
    /// 
    public enum LanguageInfo
    {
        kr, en, jp, cn, vi, id, ar, bn, de, es, fr, hi, it, ms, nl, pt, ru, th, tr, MAX_LI

    }
    ///
    /// 카카오 음성 API - 정적 클래스
    /// 
    public static class KakaoTransApi
    {

        ///
        /// 검색 메서드
        /// 
        ///질의
        ///원본 언어
        ///타겟 언어
        /// 번역 결과(문자열 리스트)
        public static List Search(string query, LanguageInfo src_lang, LanguageInfo target_lang)
        {
//            string site = "https://kapi.kakao.com/v1/translation/translate";
// 카카오 번역 API 버전이 업그레이드 되면서 siteurl에 변경이 생겼습니다.
            string site = "https://dapi.kakao.com/v2/translation/translate";
            string rquery = string.Format("{0}?query={1}&src_lang={2}&target_lang={3}", site, query, src_lang, target_lang);
            WebRequest request = WebRequest.Create(rquery);
            string rkey = "4e6c9cb6d6cd8204c30079fbfd8c171a";
            string header = "KakaoAK " + rkey;
            request.Headers.Add("Authorization", header);

            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream, Encoding.UTF8);
            String json = reader.ReadToEnd();

            JavaScriptSerializer js = new JavaScriptSerializer();
            dynamic dob = js.Deserialize(json);
            dynamic docs = dob["translated_text"];
            int length = ((object[])docs).Length;
            List strs = new List();
            for (int i = 0; i < length; i++)
            {
                strs.Add(docs[i][0]);
            }

            return strs;
        }
        ///
        /// 검색 메서드
        /// 
        ///질의
        /// 번역 결과(문자열 리스트)
        public static List Search(string query)
        {
            return Search(query, LanguageInfo.kr, LanguageInfo.en);
        }
        ///
        /// 번역 메서드
        /// 
        ///질의
        /// 번역 결과 (문자열 리스트)
        public static string Translate(string query)
        {
            return Translate(query,LanguageInfo.kr, LanguageInfo.en);
        }
        ///
        /// 번역 메서드
        /// 
        ///질의
        ///원본 언어
        ///타겟 언어
        /// 번역 결과 문자열
        public static string Translate(string query, LanguageInfo src_lang, LanguageInfo target_lang)
        {
            List strs = Search(query, src_lang, target_lang);
            StringBuilder sb = new StringBuilder();
            foreach (string s in strs)
            {
                sb.Append(s);
            }
            return sb.ToString();
        }
    }
}

테스트 코드

다음은 테스트 코드입니다.

using System;
using System.Collections.Generic;
using System.Text;
using WrapKakaoLib;

namespace Kakao_번역_API_활용
{
    class Program
    {
        static void Main(string[] args)
        {
            string p =
                "진달래꽃\n" +
                "나 보기가 역겨워\n" +
                "가실 때에는\n" +
                "말없이 고이 보내 드리오리다.\n" +
                "영변에 약산\n" +
                "진달래꽃\n" +
                "아름 따다 가실 길에 뿌리오리다.";
            List strs = KakaoTransApi.Search(p);
            StringBuilder sb = new StringBuilder();
            foreach(string s in strs)
            {
                sb.Append(s+"\n");
                Console.WriteLine(s);
            }
            strs = KakaoTransApi.Search(sb.ToString(), LanguageInfo.en, LanguageInfo.kr);
            foreach (string s in strs)
            {
                sb.Append(s + "\n");
                Console.WriteLine(s);
            }

            Console.WriteLine(KakaoTransApi.Translate("안녕하세요."));
            Console.WriteLine(KakaoTransApi.Translate("I am a boy.",LanguageInfo.en,LanguageInfo.kr));
        }
    }
}