데스크톱과 모바일 운영체제를 더욱 가깝게 만들어 주는 푸시 연동 서비스 'Pushbullet'

Pushbullet (무료)

디바이스와 운영체제의 울타리를 넘어 데이터와 알림을 공유할 수 있는 'Pushbullet' 서비스

요즘 해외에서 이 서비스에 대한 반응이 뜨겁습니다. 텍스트나 사진을 다른 기기로 손쉽게 전송할 수 있을 뿐 아니라, 푸시 알림과 클립보드까지 토스해 주는 다재다능한 동기화 서비스입니다.

그 동안 각각의 용도에 특화된 앱은 많이 나았는데, 이처럼 여러 기능이 한솥에 꽉꽉 채워져 있는 서비스는 또 처음 보는 것 같습니다. Pushbullet 하나만 있으면 파일 전송에서부터 노트와 링크 전달, 클립보드 동기화, 푸시 알림 확인을 원스톱으로 해결할 수 있습니다. 이미 애플 유저들은 각종 '연속성(Continuity)' 기능으로 이런 편리함을 일부 누리고 있는데, Pushbullet은 두 운영체제를 포함해 윈도우와 안드로이드까지 폭넓게 지원하는 등 '이종' 기기 사용자들에게 인기를 끌만한 요소를 지니고 있습니다. 결정적으로 서비스 자체도 무료입니다.

데이터 동기화는 일단 인터넷을 경유하는 방식인데, 속도가 빠르고 안정적으로 작동해 로컬 네트워크에서 작업하는 것과 큰 차이가 나지 않습니다. 아이클라우드 사진이 왜 아직도 안 뜨나, 블루투스 장비가 왜 인식이 안 되나 하는 걱정을 할 필요가 없다는 얘기입니다.

그동안 블로그를 통해 가지각색의 데이터 전송 프로그램을 소개해 드렸는데, 여러모로 장점이 많아 가장 추천할 만합니다.

Pushbullet의 주요 기능을 한번 둘러봤습니다

1. 서비스를 이용하기에 앞서 사용하는 운영체제에 맞는 클라이언트를 내려받아야 합니다. 운영체제에 따라 배포처가 다 다른데, 공식 웹사이트의 다운로드 페이지를 이용하면 편리합니다.

• Pushbullet for iOS
• Pushbullet for Mac
• Pushbullet for Android
• Pushbullet for Windows 

2. 클라이언트를 실행하면 페이스북 또는 구글 계정으로 로그인하는 절차가 따라옵니다. ▼

3. 맥용 클라이언트는 크게 두 파트로 나뉘어져 있습니다.

메인 윈도우는 동기화 내역을 한데 모아보는 역할을 담당하고, 메뉴 막대 아이콘 클릭을 클릭했을 때 표시되는 팝업 창은 다른 기기로 텍스트나 사진, 파일을 전송할 때 사용됩니다. ▼

이제 본격적으로 메시지나 파일을 날려볼까요?

맥에서 아이폰으로

1. 우선 맥에서 아이폰으로 '텍스트'를 전달해 보겠습니다.

메뉴 막대 아이콘을 클릭하고 팝업 창에서 'To' 필드를 선택하면 같은 계정을 등록한 사용자의 모든 기기가 표시됩니다. 이 중에서 원하는 기기를 고른 뒤 전송할 텍스트를 입력하고 'Push' 버튼을 눌러주면 됩니다. ▼

5. 아이폰에 거의 실시간으로 푸시 메시지가 나타납니다. ▼

6. 사진이나 파일은 그냥 메뉴 막대 아이콘으로 던져 넣기만 하면 OK 입니다. ▼

아이폰에서 맥으로

반대로 아이폰에서 맥으로 메시지를 날려볼까요? 레이아웃이 조금 달라서 iOS 버전에서도 사용법이 크게 다르지 않습니다.

1. 화면 우측 상단에 있는 '+' 버튼을 누른 뒤 원하는 기기를 선택하고, 텍스트를 적어넣거나 파일을 첨부한 뒤 'Push It' 버튼을 누르면... ▼

2. 알림 메시지를 띄우며 텍스트나 사진이 날라왔다고 알려줍니다. 심플하죠? ▼

3. 알림 메시지를 클릭하면 메인 윈도우가 나타나면서 방금 전달받은 메시지를 자세히 훑어볼 수 있습니다. 파일이라면 바로 실행하거나 다운로드 폴더로 옮겨놓는 것도 가능합니다. ▼

이것도 편리!

IOS 기기에 뜬 푸시 알림을 맥에서 확인할 수 있다는 것도 활용하기에 따라 편리할 수 있는 기능입니다.

단, 모든 기기에서 사용할 수 있는 것은 아니며, 반드시 맥과 아이폰, 아이패드가 블루투스 LE를 지원하는 기종이어야 합니다. 환경설정에 들어가면 관련 옵션이 달려 있는데, 푸시 메시지를 받을 앱을 개별적으로 선택할 수 있게 했습니다. ▼

예를 들어, 배달통이나 지니뉴스는 iOS 버전만 나와 있고 맥 버전은 없습니다. 하지만 이 기능을 사용하면 iOS의 푸시 메시지를 맥에서도 확인할 수 있게 됩니다. 이건 애플의 연속성 기능보다 나아 보이죠? 하지만 지나치게 많은 알림 메시지는 집중력을 떨어뜨릴 수 있으므로 적당히 끊고 맺는 지혜가 필요할 것 같습니다.  ▼

한 기기의 클립보드가 다른 기기로 자동으로 연동되는 것도 편리한 기능입니다. Pushbullet이 실행 중일 때 텍스트를 복사하면 아이폰이나 아이패드에서도 해당 텍스트를 붙여넣을 수 있게 됩니다. 거의 실시간으로 말이죠. ▼

코멘트 & 다운로드

응용 프로그램 폴더에 설치된 앱을 여럿 줄일 수 있는 '다기능성'. 그리고 기기와 운영체제에 얽매이지 않는 '포용성'을 갖춘 멋진 솔루션입니다. 성능과 완성도, 사용의 편의성도 비슷한 용도로 소개해드린 Flickr, InstaShare, DeskConnect, AirDroid 보다 훨씬 더 나아 보입니다. 반응 속도가 좋고 동기화 속도가 빠르다는 점이 특히 맘에 듭니다.

아이폰과 맥, 안드로이드, 윈도우 등 여러 기기를 폭넓게 사용하는 분이라면 사용해 볼 가치가 충분하고, 직장 동료를 친구목록에 추가하면 하나의 업무용 메신저로도 활용할 수 있을 것 같습니다.

추천하기 조금 애매한 사용자는 애플 기기만 사용하는 분들입니다. OS X에 내장된 메모 앱이나 메시지 앱, 에어드롭, 아이클라우드 사진 동기화에 큰 불만이 없다면 굳이 사용할 필요는 없어 보이지만,  연속성 기능이 뜻대로 작동하지 않을 때가 있다는 것을 고려하면 이런 솔루션 하나 미리 갖춰두는 것도 나쁘지 않은 선택입니다.


출처 : http://macnews.tistory.com/3027


Do you know about Nicescroll 3?

스크롤의 모양을 변경할 수 있는 jquery plugin

http://nicescroll.areaaperta.com/

https://github.com/inuyaksa/jquery.nicescroll/tree/master/demo

jquery plugin 만들기

When writing jQuery plugins, you have many options for how you might structure your code.

Depending on the complexity of your plugin, you’ll probably want to allow users of your plugin to exert some level of control over how it operates. There are a few ways to do this, but I like to ensure that there are many ways even within a single plugin to allow the greatest level of flexibility.

Let’s start off with a basic and decidedly pointless plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(function(window, $){
  var Plugin = function(elem){
      this.elem = elem;
      this.$elem = $(elem);
    };

  Plugin.prototype = {
    init: function() {
      this.displayMessage();
      return this;
    },
    displayMessage: function() {
      alert('Hello World!');
    }
  };

  $.fn.plugin = function() {
    return this.each(function() {
      new Plugin(this).init();
    });
  };

  window.Plugin = Plugin;
})(window, jQuery);

If the first and last lines look unfamiliar to you, the plugin is wrapped in a self-executing anonymous function.

One thing to note is that even in this basic example, we’ve already allowed for a couple of use cases. The plugin logic is not nested inside a jQuery plugin. The jQuery plugin merely allows for easy instantiation of the Plugin object. If the user of your plugin prefers, she might prefer to instantiate it manually by calling the following:

1
2
var elem = document.getElementById('elem'),
    p = new Plugin(elem).init();

Calling the plugin this way allows continued access to the innards of the plugin. This might allow the creation of a custom interface to your plugin, for example. The user of your plugin might like to trigger another alert, like so:

1
p.displayMessage();

Currently, the plugin is extra useless. Let’s make it a little less so by allowing the message to be customised.

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
(function(window, $){
  var Plugin = function(elem, options){
      this.elem = elem;
      this.$elem = $(elem);
      this.options = options;
    };

  Plugin.prototype = {
    defaults: {
      message: 'Hello world!'
    },
    init: function() {
      this.config = $.extend({}, this.defaults, this.options);

      this.displayMessage();

      return this;
    },
    displayMessage: function() {
      alert(this.config.message);
    }
  };

  Plugin.defaults = Plugin.prototype.defaults;

  $.fn.plugin = function(options) {
    return this.each(function() {
      new Plugin(this, options).init();
    });
  };

  window.Plugin = Plugin;
})(window, jQuery);

As you can see, we’ve introduced a set of defaults within the plugin and allowed it to be extended globally or using an object literal either of the following ways:

1
2
3
4
5
6
7
8
9
10
11
//Set the message per instance:
$('#elem').plugin({
  message: 'Goodbye World!'
});

var p = new Plugin(document.getElementById('elem'), {
  message: 'Goodbye World!'
}).init();

//Or, set the global default message:
Plugin.defaults.message = 'Goodbye World!';

This was due to the wonderful jQuery utility method called ‘extend’. Extending a set of object literals merges the contents of each into the object specified as the first argument. As is the case with our plugin, the first item should be an empty object literal if you don’t want to override anything.

But what if we want to customise the message displayed on a per-element basis? I admit, with this example it makes little sense, but bear with me. At present, the message can be set globally, or it can be set per collection of elements. But if the user of your plugin wanted to override it easily for a small subset of elements, they’re out of luck. Let’s change that:

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
(function(window, $){
  var Plugin = function(elem, options){
      this.elem = elem;
      this.$elem = $(elem);
      this.options = options;
      this.metadata = this.$elem.data('plugin-options');
    };

  Plugin.prototype = {
    defaults: {
      message: 'Hello world!'
    },
    init: function() {
      this.config = $.extend({}, this.defaults, this.options, this.metadata);

      this.displayMessage();

      return this;
    },
    displayMessage: function() {
      alert(this.config.message);
    }
  }

  Plugin.defaults = Plugin.prototype.defaults;

  $.fn.plugin = function(options) {
    return this.each(function() {
      new Plugin(this, options).init();
    });
  };

  window.Plugin = Plugin;
})(window, jQuery);

We’ve set the ‘metadata’ property by getting the HTML5 data attribute ‘data-plugin-options’. Now, you can customise the plugin on an element basis like so:

1
<div id="elem" data-plugin-options='{"message":"Goodbye World!"}'></div>

Notice the subtle change in the usage of single and double quotation marks.

Now our useless plugin can be setup and instantiated in a myriad of ways to suit the end users needs.

When designing a plugin, it’s important to allow users to interact with it in a way that negates the need to change the original source code. Opening up the number of was in which the default configuration can be changed is the first step in that process.


출처 : http://markdalgleish.com/2011/05/creating-highly-configurable-jquery-plugins/


oracle) JDBC Client로 연결된 특정 사용자에 대해서 sql trace 설정

-- SQL TRACE 활성화

SELECT 'exec sys.dbms_system.set_sql_trace_in_session(' || sid || ', '|| serial# || ', TRUE);' AS text 

FROM v$session where username='userId' 

AND module = 'JDBC Thin Client';


-- SQL TRACE  비활성화

SELECT 'exec sys.dbms_system.set_sql_trace_in_session(' || sid || ', '|| serial# || ', FALSE);' AS text 

FROM v$session where username='userId

AND module = 'JDBC Thin Client';


-- SQL 10053 TRACE 활성화

SELECT 'exec SYS.DBMS_SYSTEM.SET_EV(' || sid || ',' || serial# || ',10053,12,'''');' AS text 

FROM v$session where username='userId

AND module = 'JDBC Thin Client';


-- SQL 10053 TRACE 비 활성화

SELECT 'exec SYS.DBMS_SYSTEM.SET_EV(' || sid || ',' || serial# || ',10053,0,'''');' AS text 

FROM v$session where username='userId

AND module = 'JDBC Thin Client';


-- DBMS SUPPORT를 이용한 SQL TRACE 활성화

SELECT 'exec sys.dbms_support.start_trace_in_session(' || sid || ',' || serial# || ',waits=>true, binds=>true);' AS text 

FROM v$session where username='userId

AND module = 'JDBC Thin Client';


-- DBMS SUPPORT를 이용한 SQL TRACE 비활성화

SELECT 'exec sys.dbms_support.stop_trace_in_session(' || sid || ',' || serial# || ');' AS text 

FROM v$session where username='userId

AND module = 'JDBC Thin Client';


* DBMS_SUPPORT가 설치되어 있지 않으면 설치해야 한다.

SQL> @$ORACLE_HOME/rdbms/admin/dbmssupp.sql

oracle) trace

- 실행계획과 autotrace 보다 강력한 튜닝도구

▣ SQL Trace 사용 방법 - 자기세션에서 트레이스

(1) 1단계 - alter 문 사용하여 SQL 문 실행하기

alter session set sql_trace=true;

select * from emp where empno=7900;

alter session set sql_trace=false;

(2) 2단계 - 트레이스 파일찾는 스크립트 실행(trc 파일의 이름이 출력된다)

select r.value || '/' || lower(t.instance_name) || '_ora_'

|| ltrim(to_char(p.spid)) || '.trc' trace_file

from v$process p, v$session s, v$parameter r, v$instance t

where p.addr = s.paddr

and r.name = 'user_dump_dest'

and s.sid = (select sid from v$mystat where rownum = 1) ;

(3) tkprof 사용하여 프로파일 파일 생성하기(DOS 명령어, report.prf를 생성한다.)

tkprof orcl_ora_4000.trc report.prf sys=no; 

(실습결과)

fig3-1.jpg 


(4) 이벤트 트레이스를 추가하는 방법 - 아래 명령어를 실행한 다음 (1),(2),(3) 과정 반복

alter session set events '10046 trace name context forever, level 8';

 

(실습결과)

fig3-5.jpg


 

▣ SQL Trace 설명

- Elapsed time = cpu time + wait time = reponse 시점 - call 시점

- call count

SELECT 문 = Parse + Execute + Fetch

DML 문 = Parse + Execute

- Fetch call = 레코드 건수 / ArraySize

(실습결과)

fig3-3.jpg 


(질의문 실행 흐름)

fig3-4.jpg 


▣ SQL Trace 사용 방법 - 다른세션에서 트레이스

(1) 9i에서

exec dbms_system.set_ev(145, 3, 10046, 12, '');

=> 시리얼 번호가 3인 145번 세션에서 레벨 12로 10046 이벤트 트레이스

(2) 10g

(시작)

begin

dbms_monitor.session_trace_enable(

session_id=>145, serial_num=>3,

waits=>TRUE, binds=>TRUE);

end;

(해제)

begin

dbms_monitor.session_trace_disable(

session_id=>145, serial_num=>3);

end;

(3) oradebug 명령어

oradebug help

oradebug setospid 3796

oradebug unlimit /* 트레이스 파일의 크기를 없앰 */

oradebug event 10046 trace name context forever, level 8

oradebug tracefile_name /* 트레이스 파일 이름 확인 */

oradebug event 10046 trace name context off /* 트레이스 해제 */

oradebug close_trace

▣ SQL Trace 사용 방법 - Service, Modele, Action 단위로 트레이스 걸기- 10g

- show parameter service_name;

- /* 서비스나 모듈 이름 보는 방법 */

select sid, service_name, module, action

from v$session

where service_name <> 'SYS$BACKGROUND';

(1) 세션에 거는 방법 - 세션 이름이 eCRM인 세션에 모두 트레이스 걸기

begin

dbms_monitor.serv_mod_act_trace_enable(

service_name=>'eCRM',

module_name=>dbms_monitor.all_modules,

action_name=>dbms_monitor.all_actions,

waits=>true, binds=>true);

end;

/

(트레이스 설정 확인)

select primary_id service_name, qualifier_id1 module, qualifier_id2 action,

waits, binds

from dba_enabled_traces;

(트레이스 해제)

begin

dbms_monitor.serv_mod_act_trace_disable(

service_name=>'eCRM',

module_name=>dbms_monitor.all_modules,

action_name=>dbms_monitor.all_actions);

end;

/

(2) 모듈에 거는 방법

(모듈 이름 바꾸기)

begin

dbms_application_info.set_module(

module_name=>'emp manager',

action_name=>'select emp');

end;

/

(확인)

select sid, service_name, module, action

from v$session

where service_name <> 'SYS$BACKGROUND';

(모듈에 걸기)

begin

dbms_monitor.serv_mod_act_trace_enable(

service_name=>'eCRM', module_name=>'emp manager',

action_name=>dbms_monitor.all_actions,

waits=>true, binds=>true);

end;

/

(트레이스 설정 확인)

select primary_id service_name, qualifier_id1 module, qualifier_id2 action,

waits, binds

from dba_enabled_traces;

(트레이스 해제)

begin

dbms_monitor.serv_mod_act_trace_disable(

service_name=>'eCRM', module_name=>'emp manager',

action_name=>dbms_monitor.all_actions);

end;

/

(실행 중 부분 모듈에 걸기)

..

dbms_application_info.set_action('update emp');

..

begin

dbms_monitor.serv_mod_act_trace_enable(

service_name=>'eCRM', module_name=>‘emp manager',

action_name=>'update emp',

waits=>true, binds=>true);

end;

/

select primary_id service_name, qualifier_id1 module, qualifier_id2 action,

waits, binds

from dba_enabled_traces;

(특정값으로 설정된 세션에만 트레이스 걸기)

- 설정

exec dbms_session.set_identifier('oraking');

- 트레이스 걸기

begin

dbms_monitor.client_id_trace_enable(

client_id=>'oraking',

waits=>false, binds=>false);

end;

/


출처 : http://bysql.net/index.php?document_srl=5030&mid=w201002