Delphi에서 gRPC로 Google Cloud Translation 사용하기

· 컴포넌트

Google Cloud Translation v3은 백 개가 넘는 언어 간에 텍스트를 번역하고, 텍스트의 언어를 대신 감지할 수 있습니다. 이 서비스는 gRPC를 통해 제공되며, sgcWebSockets Enterprise는 TsgcGRPCClient 위에 구축된 형식화된 Translation gRPC 클라이언트를 함께 제공합니다. Protocol Buffers를 직접 조립하는 대신, 요청 객체를 채우고, 메서드 하나를 호출하고, 형식화된 응답에서 번역된 텍스트를 바로 읽습니다. 이 글에서는 작동 방식을 살펴보고 번들로 제공되는 데모의 실제 Delphi 코드를 보여줍니다.

작동 방식

gRPC는 HTTP/2 위에 프레이밍된 Protocol Buffers이므로, Translation 클라이언트는 sgcWebSockets HTTP/2 스택 위에 위치합니다. TLS로 443 포트의 translate.googleapis.com을 가리키는 TsgcHTTP2Client를 만들어 TsgcGRPCClient에 할당하면, gRPC 컴포넌트가 메시지 프레이밍, 헤더, 스트림 처리를 대신 수행합니다.

Translation 유닛 sgcGRPC_Google_Translation은 v3 API를 반영하는 형식화된 메시지 클래스를 추가합니다. 번역을 위한 TsgcGRPCTranslationTranslateTextRequest...TranslateTextResponse, 언어 감지를 위한 DetectLanguage 쌍, 언어 나열을 위한 GetSupportedLanguages 쌍입니다. 각 요청은 자신을 protobuf로 직렬화하는 ToBytes 메서드를 제공하고, 각 응답은 답변을 파싱하는 LoadFromBytes 메서드를 제공합니다. 그 바이트를 gRPC 클라이언트의 Call 메서드에 전달하고 결과를 다시 읽습니다.

인증

Cloud Translation은 Google 서비스 계정 토큰이 필요합니다. 데모는 서비스 계정 JSON 키(클라이언트 이메일, 개인 키 id, 개인 키, 프로젝트 id)로 인증하여 Bearer 토큰을 획득한 다음, 모든 호출에 따라가도록 gRPC 메타데이터로 추가합니다.

GetGRPCClient.DefaultMetadata.Clear;
GetGRPCClient.DefaultMetadata.Add('authorization', 'Bearer ' + FToken);

한 가지 주목할 세부 사항: 자체 서명된 서비스 계정 JWT는 audience에 바인딩되므로, translate.googleapis.com에서 수락되려면 토큰이 Translation 엔드포인트를 대상으로 해야 합니다. 데모는 토큰을 요청하기 전에 JWT.API_Endpointhttps://translate.googleapis.com/로 설정합니다.

클라이언트 설정하기

HTTP/2 전송과 gRPC 클라이언트는 한 번 함께 연결됩니다. Translation 서비스는 와이어에서 protobuf를 기대하므로, 채널 콘텐츠 타입은 grpcProto입니다.

uses
  sgcHTTP2_Client, sgcGRPC_Types, sgcGRPC_Client,
  sgcGRPC_Google_Translation;

FHTTP2Client := TsgcHTTP2Client.Create(nil);
FHTTP2Client.Host := 'translate.googleapis.com';
FHTTP2Client.Port := 443;
FHTTP2Client.TLS  := True;

FGRPCClient := TsgcGRPCClient.Create(nil);
FGRPCClient.Client := FHTTP2Client;
FGRPCClient.ChannelOptions.ContentType  := grpcProto;
FGRPCClient.ChannelOptions.Compression  := grpcNoCompression;

텍스트 번역하기

번역하려면 TsgcGRPCTranslationTranslateTextRequest를 채웁니다. Parent 리소스 경로를 설정하고, 하나 이상의 문자열을 Contents에 추가하고, 소스 및 타겟 언어 코드와 MIME 타입을 설정합니다. ToBytes로 직렬화하여 정규화된 서비스 이름 및 메서드와 함께 Call에 전달합니다. 부모 경로는 v3 형식 projects/<project-id>/locations/global을 따릅니다.

var
  oRequest: TsgcGRPCTranslationTranslateTextRequest;
  oResponse: TsgcGRPCResponse;
begin
  oRequest := TsgcGRPCTranslationTranslateTextRequest.Create;
  try
    oRequest.Parent := 'projects/' + txtProjectId.Text + '/locations/global';
    oRequest.Contents.Add(txtSourceText.Text);
    oRequest.SourceLanguageCode := txtSourceLang.Text;   // e.g. 'en'
    oRequest.TargetLanguageCode := txtTargetLang.Text;   // e.g. 'es'
    oRequest.MimeType := 'text/plain';

    oResponse := GetGRPCClient.Call
      ('google.cloud.translation.v3.TranslationService', 'TranslateText',
      oRequest.ToBytes);
  finally
    oRequest.Free;
  end;
end;

응답은 TsgcGRPCResponse로 돌아옵니다. StatusCodegrpcOK일 때, 원시 Data 바이트를 형식화된 응답에 로드하고 각 번역을 읽습니다. 각 TranslationTranslatedText를 담고 있으며, 소스 언어가 자동 감지된 경우 DetectedLanguageCode도 담고 있습니다.

var
  oResponse: TsgcGRPCTranslationTranslateTextResponse;
  i: Integer;
begin
  oResponse := TsgcGRPCTranslationTranslateTextResponse.Create;
  try
    oResponse.LoadFromBytes(aData);
    for i := 0 to oResponse.TranslationCount - 1 do
    begin
      DoLog('Translated: ' + oResponse.Translation(i).TranslatedText);
      if oResponse.Translation(i).DetectedLanguageCode <> '' then
        DoLog('Detected: ' + oResponse.Translation(i).DetectedLanguageCode);
    end;
  finally
    oResponse.Free;
  end;
end;

언어 감지하기

소스 언어를 모를 때는 번역은 제쳐두고 DetectLanguage를 호출합니다. 부모 경로와 검사할 ContentTsgcGRPCTranslationDetectLanguageRequest를 만든 다음, 후보 언어를 다시 읽으며, 각각 LanguageCodeConfidence 값을 가집니다.

oRequest := TsgcGRPCTranslationDetectLanguageRequest.Create;
try
  oRequest.Parent := GetParentPath;
  oRequest.Content := txtSourceText.Text;
  oRequest.MimeType := 'text/plain';

  oResponse := GetGRPCClient.Call
    ('google.cloud.translation.v3.TranslationService', 'DetectLanguage',
    oRequest.ToBytes);
finally
  oRequest.Free;
end;

감지 응답을 파싱하면 각 후보에 대한 언어 코드와 신뢰도 점수를 얻습니다.

oResponse := TsgcGRPCTranslationDetectLanguageResponse.Create;
try
  oResponse.LoadFromBytes(aData);
  for i := 0 to oResponse.LanguageCount - 1 do
    DoLog('Language: ' + oResponse.Language(i).LanguageCode +
      ' (confidence: ' + FloatToStr(oResponse.Language(i).Confidence) + ')');
finally
  oResponse.Free;
end;

지원되는 언어 나열하기

세 번째 작업인 GetSupportedLanguages는 서비스가 지원하는 모든 언어를 반환합니다. 표시 이름을 보여줄 언어를 DisplayLanguageCode로 설정하면, 각 항목은 LanguageCode와 사람이 읽을 수 있는 DisplayName, 그리고 소스 또는 타겟으로 사용할 수 있는지 여부를 나타내는 플래그와 함께 돌아옵니다.

oRequest := TsgcGRPCTranslationGetSupportedLanguagesRequest.Create;
try
  oRequest.Parent := GetParentPath;
  oRequest.DisplayLanguageCode := 'en';

  oResponse := GetGRPCClient.Call
    ('google.cloud.translation.v3.TranslationService',
    'GetSupportedLanguages', oRequest.ToBytes);
finally
  oRequest.Free;
end;

제공 범위

Translation gRPC 클라이언트는 sgcWebSockets Enterprise 에디션의 일부이며 Delphi와 C++Builder 전반에 걸쳐 Windows, macOS, Linux, iOS, Android에서 실행됩니다. 서비스 계정 로딩과 세 가지 작업을 모두 갖춘 완전하고 바로 실행 가능한 샘플은 Demos\21.GRPC\12.Translation에 있으며, 기반이 되는 gRPC 클라이언트는 gRPC Client 제품 페이지에 문서화되어 있습니다.

질문이나 의견이 있으신가요? 문의하기. 코드를 작성한 사람들로부터 답변을 받게 됩니다.