개발자 등록과정은 생략


페이스북에서 제공해주는 툴을 사용하면 간단히 토큰을 생성할 수 있다.

https://developers.facebook.com/tools/explorer


페이스북 비 로그인 상태에서 게시글 가져오는 방법


Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    @Resource MappingJackson2JsonView ajaxMainView;
    @RequestMapping(value="/facebookPageCrawling.do", method=RequestMethod.POST)  
    public ModelAndView facebookPageCrawling(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {        
        String token = "앱 아이디|앱 시크릿 아이디";
        String user_id = "회원 아이디";
        URL url = new URL("https://graph.facebook.com/" + user_id + "?fields=posts%7Bcreated_time%2Cmessage%2Cpicture%2Cpermalink_url%7D&access_token=" +  token); 
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); 
 
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); 
        String inputLine; 
        StringBuffer sb = new StringBuffer(); 
        
        while ((inputLine = in.readLine()) != null) { 
            sb.append(inputLine);
        } 
        in.close(); 
        String result = sb.toString();
 
        model.addAttribute("model", result);
        
        return new ModelAndView(ajaxMainView, model);
    }
cs


토큰에 | (백스페이스 아래에 있는 구분자) 를 기준으로 앱 아이디와 시크릿 아이이디를 토큰으로 사용한다.

앱과 시크릿 아이디는 https://developers.facebook.com/apps/ 에서 본인의 앱으로 들어가서

기본설정에 보면 나와있다.


회원 아이디는 위에 그래프 툴에서 확인 가능하다.


기호에 맞게 사용하면 끝


1, 17, 19, 21번째 줄은 화면에 출력하기 위해 js단으로 데이터를 보내는 코드이므로 본인 코드에 맞게 수정할것!


'Java' 카테고리의 다른 글

구글, 파파고 번역 API 성능 비교  (1) 2019.09.18
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


 

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

Object 클래스에 대해




안녕하세요 열코입니다.

이번시간에는 자바의 Object 클래스에 대해 알아보도록 하겠습니다.

일전에 Object 클래스에대해 언급했던적이 있는데, 자바의 모든 요소들은 클래스로 정의되어있으며,

직접 또는 간접적으로 Object 클래스에서 상속받은것이라고 언급한적이 있습니다.

자바의 모든 클래스의 부모 클래스인 Object 클래스에 대해 살펴보겠습니다.


Obejct 클래스는 java.lang 이라는 패키지(package) 내에 존재합니다.

또한 위에서 언급했듯이 모든 클래스의 부모 클래스이기 때문에 모든 클래스에서 Object 클래스의 메소드를 사용할 수 있습니다.

추가로 모든 메소드는 오버라이드(재정의) 하여 프로그램에서 적절히 사용가능합니다.

대표적인 Object 클래스의 메소드는 다음과 같습니다.


1. toString()

toString() 함수는 Object 클래스의 메소드로 객체를 String으로 변환하는데 사용됩니다.

다음과 같이 정의되어있습니다.


1
2
3
public String toString() {
    return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
cs


2. hashCode()

hashCode() 함수는 JVM으로 부터 모든 객체에 대해 고유번호(해시코드)를 생성, 반환합니다.

자바에서는 C/C++과 같이 객체의 주소값을 찾을 수 없기 때문에 이 해시코드를 사용합니다.

다음과 같이 사용할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class student
{
    static int addr = 100;
    int addr_num;
 
    student()
    {
        addr_num = addr;
        addr++;
    }
 
    public int hashCode() // 오버라이딩
    {
        return addr_num;
    }
    
    public static void main(String[] args)
    {
        student s = new student();
 
        System.out.println(s);
        System.out.println(s.toString);
    }
}
cs


3. equals()

eqauls() 함수는 매개변수로 주어진 객체를 this 객체와 비교합니다. (this 객체는 메소드를 호출한 객체를 의미합니다.)

보통 String 객체의 비교시 사용되며, 사용자 정의 클래스에서는 오버라이딩하여 사용하는것이 좋습니다.



4. getClass()

getClass() 함수는 this 객체의 실제 런타임 클래스를 가져옵니다.


1
2
3
4
5
6
7
8
9
public class semog
{
    public static void main(String[] args)
    {
        Object obj = new String("세모지");
        Class c = obj.getClass();
        System.out.println(c.getName()); // java.lang.String 
    }
}
cs


c 클래스의 getName()을 호출했는데 String 클래스가 반환되었습니다.

c 클래스는 obj객체의 클래스를 받아오며 obj 객체는 String 클래스 객체를 가지고 있습니다.

이에 대한 설명은 C/C++의 가상(virtual) 함수에 대한 내용을 확인하시면 됩니다.


5. finalize()

finalize() 함수는 객체가 가비지 컬렉터에 의해 수집되기 직전에 호출됩니다.

가비지 컬렉터 호출에 대해 대략 설명하면 객체에 대한 참조가 없다고 판단될 경우 JVM의 가비지 컬렉터가 호출됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class semog
{
    public static void main(String[] args)
    {
        semog s = new semog();
        s = null// 객체 참조가 없음
 
        System.gc(); // 가비지 컬렉터 호출
    }
    protected void finalize() // 오버라이딩
    {
        System.out.println("finalize 메소드 호출");
    }
}
cs


참고 : finalize() 함수는 해당 객체가 가비지 컬렉터를 여러번 수행했더라도 한번만 호출되게됩니다.

그외 메소드에 대해서는 자바 쓰레드 시간에 자세히 언급하도록 하겠습니다. :)



이상 '자바 object 클래스'에 대해 알아보았습니다.

질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

메인 페이지로 이동하시면 더 많은 자료를 볼 수 있습니다.




to Top