Google Translate API V3(beta)

Naver Papago Translate NMT

Detecting(언어감지)

짧은 텍스트(30)

15

1.9

긴 텍스트(500+)

1초 미만

0.1초 미만

Translate(번역)

짧은 텍스트(30)

15

1.9~ 2.3

긴 텍스트(500+)

1초 미만

0.1초 미만

Detecting + Translate

짧은 텍스트(30)

30

3~ 5

긴 텍스트(500+)

1~ 3

0.1~ 0.3

NOTE

* 짧은 글 번역시 실행속도는 호출 횟수에 비례

(구글 API의 경우 트래픽 속도에 따라 빨라졌다 느려졌다 함)

 

* db 저장 값을 번역하여 출력 시 텍스트를 대체하는 것이므로

번역할 언어를 한글이라 가정, detecting 과정 생략 시 시간 2배 절약

 

* 구글, 파파고 모두 처음 번역과 두 번째 이상 번역 속도 차이 2배 이상

(처음 5초가 걸리더라도 두 번째 부터는 1~2초 이내에 실행됨)

 

* 정확도는 구글이 조금 더 정확하며, 변환 언어를 더 많이 지원함 (V2V3 속도차이 거의 X)

가격

무료

30500,000자 제한(1일 환산 시 16,666)

110,000자 제한

과금

1,000,000자 당 20USD

1,000,000자 당 20,000


'Java' 카테고리의 다른 글

facebook graph api로 게시글 가져오기  (1) 2019.09.23
google translate api v3 사용법  (1) 2019.09.16
java spring pwa fcm web push 구현  (2) 2019.09.10
Object 클래스에 대해  (0) 2018.11.04
자바 표준 입력 클래스 Scanner 사용법  (1) 2018.11.04
자바 상속  (0) 2018.10.17
자바 싱글톤 클래스(Singleton class)  (3) 2018.10.16
자바 Wrapper Class  (0) 2018.10.15


GCP(google cloud platform) 생성 및 설정은 생략한다.

https://cloud.google.com/gcp/getting-started/?hl=ko 여기를 참고할것!


모든 코드 및 내용은

https://cloud.google.com/translate/docs/quickstart-client-libraries-v3 여기를 참고했음.


번역 함수 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    static String translateText(String text, String sourceLanguageCode, String targetLanguageCode) {
 
        try (TranslationServiceClient translationServiceClient = TranslationServiceClient.create()) {
 
 
 
        LocationName locationName = LocationName.newBuilder().setProject("").setLocation("").build();
 
 
 
        TranslateTextRequest translateTextRequest = TranslateTextRequest.newBuilder()
 
            .setParent(locationName.toString())
 
            .setMimeType("text/plain")
 
            .setSourceLanguageCode(sourceLanguageCode)
 
            .setTargetLanguageCode(targetLanguageCode)
 
            .addContents(text)
 
            .build();
 
 
 
        TranslateTextResponse response = translationServiceClient.translateText(translateTextRequest);
 
        return response.getTranslationsList().get(0).getTranslatedText();
 
 
 
        } catch (Exception e) {
 
              throw new RuntimeException("Couldn't create client.", e);
 
        }
 
    }
 
 
cs


GOOGLE API 문서에서와 조금 다른 부분이 존재한다.

7번째 줄 setProject에는 project id를 넣고, setLocation에는 global이라고 고정값을 넣었다.

retrun 값도 호출 함수에 맞게 String으로 변경하였다.

특이하게도 번역함수에 sourceLanguageCode를 넣어야한다.

번역할 String의 언어를 명시해주어야 한다. (하지 않아도 되지만 짧은 텍스트인 경우 오류가 간헐적으로 발생)


때문에 언어 코드를 detect하는 함수를 아래와 같이 작성한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    static String detectLanguageOfText(String text) {
        try (TranslationServiceClient translationServiceClient = TranslationServiceClient.create()) {
 
        LocationName locationName = LocationName.newBuilder().setProject("").setLocation("").build();
        DetectLanguageRequest detectLanguageRequest = DetectLanguageRequest.newBuilder()
            .setParent(locationName.toString())
            .setMimeType("text/plain")
            .setContent(text)
            .build();
 
        DetectLanguageResponse response = translationServiceClient.detectLanguage(detectLanguageRequest);
        return response.getLanguages(0).getLanguageCode();
 
        } catch (Exception e) {    
            throw new RuntimeException("Couldn't create client.", e);
        }
    }
cs


4번째 줄에도 똑같이 project id와 "global"을 작성한다.

이 함수의 반환값은 코드값(String)으로 변경되었다.


이제 함수를 호출하는 방법이다.


1
2
3
4
5
6
7
8
9
10
11
12
        String text = "HELLO";
        String from = detectLanguageOfText(text);
        String to = request.getParameter("lang");
        
        System.out.println("TRANSLATE STRING : " + text);
        System.out.println("TRANSLATE LANGUAGE FROM : " + from);
        System.out.println("TRANSLATE LANGUAGE TO : " + request.getParameter("lang"));
        
        if(from.equals(to))
            System.out.println("TRANSLATE RESULT : " + text);
        else
            System.out.println("TRANSLATE RESULT : " + translateText(text, from, to));
cs



희한하게도 FROM LANGUAGE와 TO LANGUAGE가 같은 경우 에러를 반환한다.

이를 방지하기위해 9번째 코드를 추가하였다.



에러 해결

API 호출시 500에러 (CREDENTIALS 어쩌고...)가 발생하여

API 문서의 SET 명령어를 통해 환경변수를 등록했지만 그대로 오류 발생


내 PC -> 우클릭 시스템 -> 고급 시스템 설정 -> 고급 -> 환경변수 -> 사용자 변수에 새로 생성

변수이름 : GOOGLE_APPLICATION_CREDENTIALS

변수 값 : 생성한 비밀 키 json 경로


수동으로 환경 변수를 설정해주었다면 PC 재시작 필요





구글 FCM 프로젝트 등록은 https://yeolco.tistory.com/85 를 참고하세요.

안드로이드 기준으로 작성되어있으니 프로젝트 생성까지만 따라하시고 오세요.


0. maifest.json

PWA 프로젝트 기준으로 작성되었기 때문에 mainfest.json내에

{

"gcm_sender_id": "103953800507"

}

를 추가해줍니다.

아이디는 위 아이디 그대로 사용하시면 됩니다.

(자신의 프로젝트의 sender id를 작성하면 오류발생합니다.)



1. 스크립트 영역(프론트)

<script src="https://www.gstatic.com/firebasejs/6.6.0/firebase-app.js"></script>

<script src="https://www.gstatic.com/firebasejs/5.10.1/firebase-messaging.js"></script>


<script>

// Your web app's Firebase configuration

var firebaseConfig = {

apiKey: "AIzaSyAnAp-nWTe4_N8piai73nfsl50lotYneu4",

authDomain: "cms-test-4f739.firebaseapp.com",

databaseURL: "https://cms-test-4f739.firebaseio.com",

projectId: "cms-test-4f739",

storageBucket: "",

messagingSenderId: "1095403590845",

appId: "1:1095403590845:web:b675f1753fc15ca0ab93d4"

};

// Initialize Firebase

firebase.initializeApp(firebaseConfig);

console.log("FCM INIT DONE");

</script>


프로젝트 설정 부분에서

이 부분을 그대로 복사한 후

푸시 메세지 사용을 위해

<script src="https://www.gstatic.com/firebasejs/5.10.1/firebase-messaging.js"></script>

를 추가해줍니다.


프론트 단(js)에서 적절한 위치(이벤트)에 토큰을 등록해줍니다.

const messaging = firebase.messaging();

messaging.usePublicVapidKey(applicationServerPublicKey);

Notification.requestPermission().then((permission) => {

if (permission === 'granted') {

console.log('Notification permission granted.');

// TODO(developer): Retrieve an Instance ID token for use with FCM.

messaging.getToken().then((currentToken) => {

if (currentToken) {

var data = { 

'token' : currentToken

};

$.ajax({

url: '/insertPushToken.do',

type: 'POST',

data: data,

success: function(data) {

console.log('RESULT', data);

},

error: function(err) {

console.log('ERROR', err);

}

});

} else {

console.log('No Instance ID token available. Request permission to generate one.');

}

}).catch((err) => {

console.log('An error occurred while retrieving token. ', err);

showToken('Error retrieving Instance ID token. ', err);

setTokenSentToServer(false);

});

else {

console.log('Unable to get permission to notify.');

}

});

1) applicationServerPublicKey는 FCM 콘솔에서 키 쌍 생성해서 넣어줍니다.

2) $.ajax 부분은 db에 토큰을 저장하는 부분입니다.

개인적으로 구현해서 사용하시면 됩니다. (혹시 필요하시면 댓글)


2. 자바(백엔드) 영역

// 푸시보내기 TEST

String FCM_URL = "https://fcm.googleapis.com/fcm/send";

String server_key = "AAAA_wskVL0:APA91bEd...............................kropWYS";

String tokenId = "e6vkJHnCd6s:.................................U_nYts_01-XNhzV";

String result = "";

URL url = new URL(FCM_URL);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();


conn.setUseCaches(false);

conn.setDoInput(true);

conn.setDoOutput(true);


conn.setRequestMethod("POST");

conn.setRequestProperty("Authorization", "key=" + server_key);

conn.setRequestProperty("Content-Type", "application/json");


JSONObject json = new JSONObject();


try {

json.put("to", tokenId.trim());

JSONObject data = new JSONObject();

data.put("url", "https://test.com");

data.put("icon", "test.png"); 

json.put("data", data);

JSONObject info = new JSONObject();

info.put("title", "푸시 테스트 중입니당"); 

info.put("body", "삐뽀삐뽀");

json.put("notification", info);

} catch (JSONException e1) {

e1.printStackTrace();

}


try {

OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());

wr.write(json.toString());

wr.flush();


BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));


String output;

System.out.println("Output from Server .... \n");

while ((output = br.readLine()) != null) {

System.out.println(output);

}

result = "succcess";

} catch (Exception e) {

e.printStackTrace();

result = "failure";

}

System.out.println("GCM Notification is sent successfully : " + result);

1. FCM_URL : 고정값입니다.

2. server_key : 동그라미 친 부분입니다.

3.  tokenId : 위에 프론트단에서 ajax로 디비에 넣은 토큰입니다.

저도 귀찮아서 그냥 하드코딩했어요 (이 부분은 디비에서 불러오면 됩니다.)


아 참고로 지금 단일 푸시 테스트 코드입니다.

여러명에게 보내는건 추후에 구현하고 올려드릴게요!


10/1 수정-----------------------------------------------------------------------------------


** 푸시 여러명에게 한번에 보내기


실제 프로젝트에서 수백~수천명에게 푸시를 보내야 하기 때문에

위 코드를 반복문으로 활용했을 경우 해당 코드에서 반복문을 돌면서(동기) 오랜시간 로딩이 걸린다.


fcm에서 여러명에게 푸시를 보내는 기능을 지원한다.

https://firebase.google.com/docs/cloud-messaging/http-server-ref

위 링크에서 다운스트림 json 부분을 확인한다.


위 단일 전송 코드에서 json.put("to", 토큰) 부분을 주석처리하고

아래와 같이 "registration_ids"를 추가한다.

=> json.put("registration_ids", tokens);


tokens는 배열(List)로 구성되어있다.

토큰들이 담긴 배열을 추가하면 된다.


처리 속도는 단일 메시지 보단 느리지만 300명 정도 테스트했을때 1초 이내로 실행되는것을 확인했다.


----------------------------------------------------------------------------------------------


4. Service worker.js (서비스워커)

firebase push 사용시 서비스워커 js 파일을 만들어야합니다.

index와 같은 루트단에 firebase-messaging-sw.js 파일 생성하고 아래와 같이 작성합니다.

(토씨하나도 틀리면 오류나요)

var push_url;


// Functional: PUSH

self.addEventListener('push', event => {

var push_data = eval("(" + event.data.text() + ")");

push_url = push_data.data.url;

const title = push_data.notification.title;

const options = {

    body: push_data.notification.body,

    icon: push_data.data.icon

};


event.waitUntil(self.registration.showNotification(title, options));

});


// Push Notification Click

self.addEventListener('notificationclick', function(event) {

console.log('Notification click Received.', push_url);


event.notification.close();


if(push_url != null) {

event.waitUntil(

clients.openWindow(push_url)

);

}

});

1) self.addEventListener('push', event => : 푸시 받는 부분입니다. 

서버에서 푸시를 정상적으로 보내도 여기서 오류나면 못받습니다.

2) self.addEventListener('notificationclick', function(event)  : 푸시 notification 눌렀을때 처리할 이벤트입니다.


작동화면



'Java' 카테고리의 다른 글

facebook graph api로 게시글 가져오기  (1) 2019.09.23
구글, 파파고 번역 API 성능 비교  (1) 2019.09.18
google translate api v3 사용법  (1) 2019.09.16
Object 클래스에 대해  (0) 2018.11.04
자바 표준 입력 클래스 Scanner 사용법  (1) 2018.11.04
자바 상속  (0) 2018.10.17
자바 싱글톤 클래스(Singleton class)  (3) 2018.10.16
자바 Wrapper Class  (0) 2018.10.15

to Top