[Oracle|오라클] 구분자로 자르기 (Split)

프로그래밍을 할때처럼 오라클 쿼리에서도 Split을 할수 있는 방법을
찾아보니 대부분 함수로 되어있다. 아래는 간단히 쿼리도 해결할수 있다.

아래 예제는 구분자(|)를 기준으로 'A|B|C|D' 를 Split하는 예제이다.

 -- Oracle 10g 이상에서 (정규식 함수사용)
 SELECT distinct regexp_substr(A.TXT, '[^|]+', 1, LEVEL) TXT
CONNECT BY LEVEL <= length(regexp_replace(A.TXT, '[^|]+',''))+1
  --Oracle 8i 이상에서
 SELECT substr(A.TXT,
              instr(A.TXT, '|', 1, LEVEL) + 1,
              instr(A.TXT, '|', 1, LEVEL + 1) - instr(A.TXT, '|', 1, LEVEL) - 1) TXT
   FROM (SELECT '|' || 'A|B|C|D' || '|' TXT FROM dual) A
CONNECT BY LEVEL <= length(A.TXT) - length(REPLACE(A.TXT, '|')) - 1




아래는 위의 쿼리를 응용하여 구분자의 컬럼(Column)을 행(Row)으로 바꾸는 쿼리이다.


     , (
        SELECT distinct regexp_substr(AA.TXT, '[^|]+', 1, LEVEL) TXT
          FROM (SELECT replace(wm_concat(distinct AAA.TXT),',','|') TXT
                        FROM TEMP_TABLE AAA) AA
     CONNECT BY LEVEL <= length(regexp_replace(AA.TXT, '[^|]+',''))+1

       ) B
 WHERE instr('|' || A.TXT || '|',  '|' || B.TXT || '|') > 0



출처 : http://gent.tistory.com/10



20 jQuery Scrollbar plugin with examples

In this Article we are providing best jQuery scrollbar plugin with examples.Due to increasing popularity of custom scrollbar we are providing a list of lightweight ,stylish,flexible  and easy to use scrollbar in jQuery which work consistently across all modern browsers.These plugins make your site more attractive and gives a modern look.

1. NiceScroll : jQuery Scrolling plugin for desktop,mobile & touch devices

Nicescroll (as nice scroll for browsers) is a jquery (since 1.5) plugin, for nice scrollbars with a very similar ios/mobile style. It supports DIVs, IFrames and document page (body) scrollbars.Compatible with iOS devices as iPad. So you have scrollable divs for iPad.

NiceScroll : jQuery Scrolling plugin for desktop,mobile & touch devices

Read MoreDemo

2. nanoScroller a Lion-styled jQuery scrollbars

nanoScroller.js is a jQuery plugin that offers a simplistic way of implementing Mac OS X Lion-styled scrollbars for your website.

nanoScroller a Lion-styled jQuery scrollbars

Read MoreDemo

3. jQuery custom content scroller

Custom scrollbar plugin utilizing jquery UI that’s fully customizable with CSS. It features vertical/horizontal scrolling, mouse-wheel support (via Brandon Aaron jquery mouse-wheel plugin), scroll easing and adjustable scrollbar height/width.

jQuery custom content scroller

Read MoreDemo

4. Tiny Scrollbar – A lightweight jQuery plugin

Tiny Scrollbar can be used for scrolling content. It was built using the JavaScript jQuery library. Tiny scrollbar was designed to be a dynamic lightweight utility that gives web designers a powerful way of enhancing a websites user interface.

Tiny Scrollbar – A lightweight jQuery plugin

Read MoreDemo

5. Scrollbar Visibility with jScrollPane

Sometimes it can be very useful to hide the scrollbar of elements in a website and only show it when the user really needs it. The real-time activity feed in Facebook is an example for such a behavior.

Scrollbar Visibility with jScrollPane

Read MoreDemo

6. jScrollPane – custom cross-browser scrollbars

jScrollPane is a jQuery plugin which provides you with custom scrollbars which work consistently across all modern browsers. You can style the scrollbars using simple CSS and they degrade gracefully where JavaScript is disabled.jScrollPane is designed to be flexible but very easy to use.

jScrollPane – custom cross-browser scrollbars

Read MoreDemo

7. Scrollbar Paper

Scrollbar Paper does not replace browser’s default scrollbar.Instead, it covers it with a custom scrollbar, like paper on a wall: that is why it is called Scrollbar Paper.

Scrollbar Paper in jQuery

Read MoreDemo

8. jQuery Scrollbars v2

jQuery plugin. Fully themable and adjustable scrollbars. Automatically adjusts if scrollbars are not required. Fallback to regular scrollbars if JavaScript is disabled.

jQuery Scrollbars v2

Read MoreDemo

9. ShortScroll – A jQuery UI Google Wave style scroll bar

Scroll bar in Google Wave was the best UI feature in the whole app. It added functionality and style making much better than the browser default scroll bar. So I thought that I would create a scroll bar like it as a jQuery UI widget.

ShortScroll – A jQuery UI Google Wave style scroll bar

Read MoreDemo

10. Vertical scrollbar using jQuery UI slider

The code assumes a div with fixed height (#scroll-pane or .scroll-pane in my examples) which contains the content for scrolling. The script wraps the contents of the div to be scrolled in another div (.scroll-content) which is used positioned absolutely, and then the top value of #scroll-content is changed via the slider to make the content scroll up and down. The scrollbar itself is positioned within #scroll-pane, using absolute positioning on the right hand side, but it can go anywhere you like.

Vertical scrollbar using jQuery UI slider

Read MoreDemo

11. Plugin Scrollbar.js

This plugin has only one purpose. That create a scrollbar in a desired item to display a content larger than that of visible space. It caters for those (and those) who want to see the browser’s scrollbar. Management Sroll wheel is also included in this plugin, but is deactivated.Many things are easily configured, the size and position of the scrollbar, button. It is also possible to define multiple styles.

Plugin Scrollbar.js

Read MoreDemo

12. iScroll 4 : Scrolling Features for Mobile Webkit

iScroll finally received a complete rewrite. Now it’s smoother than ever and adds some new important features: pinch/zoom, pull down to refresh, snap to elements and more custom events for a higher level of hackability.

iScroll 4 : Scrolling Features for Mobile Webkit

Read MoreDemo

13. jScrollbar : Scrollbar for scrolling contents with jQuery UI

Make your own scrollbar design with jScrollbar.jScrollbar is can be full CSS skinnable (you can use images instead) and can be combined with the mousewheel.

jScrollbar : Scrollbar for scrolling contents with jQuery UI

Read MoreDemo

14. jQuery ScrollBar Widget : jqWidgets

jQuery ScrollBar Widget : jqWidgets

Read MoreDemo

15. jQuery plugin to style scrollbars (cross-browser compatible)

jQuery plugin to style scrollbars (cross-browser compatible)

Read MoreDemo

16. Gmail style Scrollbar Using jQuery and CSS

Scrollbar looks like in new Gmail theme. The code written in jQuery and CSS.

Gmail style Scrollbar Using jQuery and CSS

Read MoreDemo

17. Facebook/Twitter style Scrollbar Using jQuery and CSS

The Facebook and Twitter have their own scrollbars styles. Are you looking for the same thing? Here is the code which is written in jQuery and CSS.

Facebook/Twitter style Scrollbar Using jQuery and CSS

Read MoreDemo

18. Scrollbars V2

Scrollbars V2 is a jQuery plugin that allows you to theme any elements with the simple CSS you already know. It feature filled yet lightweight, the perfect combination to add that little spark to your special creation.

jquery Scrollbars V2

Read MoreDemo

19. RollBar – jQuery ScrollBar Plugin

RollBar plugin was created with idea to replace standard browser scrollbars and make them customizable to fit perfectly in almost any site design. This plugin can be used not only as replacement of native browser scrollbars, but even to create slideshows with external controls. Among other features RollBar can auto adjust to window size, recognize touch events on Android and iOS devices and respond to custom jquery events to scroll content.

RollBar – jQuery ScrollBar Plugin

Read MoreDemo

Best jQuery website design gallery

출처 : http://www.jqueryrain.com/2012/07/jquery-scrollbar-plugin-examples/

Java 8 Nashorn Tutorial

Java 8 Nashorn Tutorial

Learn all about the Nashorn Javascript Engine with easily understood code examples. The Nashorn Javascript Engine is part of Java SE 8 and competes with other standalone engines like Google V8 (the engine that powers Google Chrome and Node.js). Nashorn extends Javas capabilities by running dynamic javascript code natively on the JVM.

In the next ~15 minutes you learn how to evaluate javascript on the JVM dynamically during runtime. The most recent Nashorn language features are demonstrated with small code examples. You learn how to call javascript functions from java code and vice versa. At the end you're ready to integrate dynamic scripts in your daily java business.

Baby Nashorn

UPDATE - I'm currently working on a JavaScript implementation of the Java 8 Streams API for the browser. If I've drawn your interest check out Stream.js on GitHub. Your Feedback is highly appreciated.

Using Nashorn

The Nashorn javascript engine can either be used programmatically from java programs or by utilizing the command line tool jjs, which is located in $JAVA_HOME/bin. If you plan to work with jjs you might want to put a symbolic link for simple access:

$ cd /usr/bin
$ ln -s $JAVA_HOME/bin/jjs jjs
$ jjs
jjs> print('Hello World');

This tutorial focuses on using nashorn from java code, so let's skip jjs for now. A simple HelloWorld in java code looks like this:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("print('Hello World!');");

In order to evaluate javascript code from java, you first create a nashorn script engine by utilizing the javax.script package already known from Rhino (Javas legacy js engine from Mozilla).

Javascript code can either be evaluated directly by passing javascript code as a string as shown above. Or you can pass a file reader pointing to your .js script file:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Nashorn javascript is based on ECMAScript 5.1 but future versions of nashorn will include support for ECMAScript 6:

The current strategy for Nashorn is to follow the ECMAScript specification. When we release with JDK 8 we will be aligned with ECMAScript 5.1. The follow up major release of Nashorn will align with ECMAScript Edition 6.

Nashorn defines a lot of language and API extensions to the ECMAScript standard. But first let's take a look at how the communication between java and javascript code works.

Invoking Javascript Functions from Java

Nashorn supports the invocation of javascript functions defined in your script files directly from java code. You can pass java objects as function arguments and return data back from the function to the calling java method.

The following javascript functions will later be called from the java side:

var fun1 = function(name) {
    print('Hi there from Javascript, ' + name);
    return "greetings from javascript";

var fun2 = function (object) {
    print("JS Class Definition: " + Object.prototype.toString.call(object));

In order to call a function you first have to cast the script engine to Invocable. The Invocable interface is implemented by the NashornScriptEngine implementation and defines a methodinvokeFunction to call a javascript function for a given name.

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("fun1", "Peter Parker");

// Hi there from Javascript, Peter Parker
// greetings from javascript
// class java.lang.String

Executing the code results in three lines written to the console. Calling the function printpipes the result to System.out, so we see the javascript message first.

Now let's call the second function by passing arbitrary java objects:

invocable.invokeFunction("fun2", new Date());
// [object java.util.Date]

invocable.invokeFunction("fun2", LocalDateTime.now());
// [object java.time.LocalDateTime]

invocable.invokeFunction("fun2", new Person());
// [object com.winterbe.java8.Person]

Java objects can be passed without loosing any type information on the javascript side. Since the script runs natively on the JVM we can utilize the full power of the Java API or external libraries on nashorn.

Invoking Java Methods from Javascript

Invoking java methods from javascript is quite easy. We first define a static java method:

static String fun1(String name) {
    System.out.format("Hi there from Java, %s", name);
    return "greetings from java";

Java classes can be referenced from javascript via the Java.type API extension. It's similar to importing classes in java code. As soon as the java type is defined we naturally call the static method fun1() and print the result to sout. Since the method is static, we don't have to create an instance first.

var MyJavaClass = Java.type('my.package.MyJavaClass');

var result = MyJavaClass.fun1('John Doe');

// Hi there from Java, John Doe
// greetings from java

How does Nashorn handle type conversion when calling java methods with native javascript types? Let's find out with a simple example.

The following java method simply prints the actual class type of the method parameter:

static void fun2(Object object) {

To understand how type conversations are handled under the hood, we call this method with different javascript types:

// class java.lang.Integer

// class java.lang.Double

// class java.lang.Boolean

MyJavaClass.fun2("hi there")
// class java.lang.String

MyJavaClass.fun2(new Number(23));
// class jdk.nashorn.internal.objects.NativeNumber

MyJavaClass.fun2(new Date());
// class jdk.nashorn.internal.objects.NativeDate

MyJavaClass.fun2(new RegExp());
// class jdk.nashorn.internal.objects.NativeRegExp

MyJavaClass.fun2({foo: 'bar'});
// class jdk.nashorn.internal.scripts.JO4

Primitive javascript types are converted to the appropriate java wrapper class. Instead native javascript objects are represented by internal adapter classes. Please keep in mind that classes from jdk.nashorn.internal are subject to change, so you shouldn't program against those classes in client-code:

Anything marked internal will likely change out from underneath you.


When passing native javascript objects to java you can utilize the class ScriptObjectMirrorwhich is actually a java representation of the underlying javascript object. ScriptObjectMirror implements the map interface and resides inside the package jdk.nashorn.api. Classes from this package are intended to be used in client-code.

The next sample changes the parameter type from Object to ScriptObjectMirror so we can extract some infos from the passed javascript object:

static void fun3(ScriptObjectMirror mirror) {
    System.out.println(mirror.getClassName() + ": " +

When passing an object hash to this method, the properties are accessible on the java side:

    foo: 'bar',
    bar: 'foo'

// Object: [foo, bar]

We can also call member functions on javascript object from java. Let's first define a javascript type Person with properties firstName and lastName and method getFullName.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.getFullName = function() {
        return this.firstName + " " + this.lastName;

The javascript method getFullName can be called on the ScriptObjectMirror viacallMember().

static void fun4(ScriptObjectMirror person) {
    System.out.println("Full Name is: " + person.callMember("getFullName"));

When passing a new person to the java method, we see the desired result on the console:

var person1 = new Person("Peter", "Parker");

// Full Name is: Peter Parker

Language Extensions

Nashorn defines various language and API extensions to the ECMAScript standard. Let's head right into the most recent features:

Typed Arrays

Native javascript arrays are untyped. Nashorn enables you to use typed java arrays in javascript:

var IntArray = Java.type("int[]");

var array = new IntArray(5);
array[0] = 5;
array[1] = 4;
array[2] = 3;
array[3] = 2;
array[4] = 1;

try {
    array[5] = 23;
} catch (e) {
    print(e.message);  // Array index out of range: 5

array[0] = "17";
print(array[0]);  // 17

array[0] = "wrong type";
print(array[0]);  // 0

array[0] = "17.3";
print(array[0]);  // 17

The int[] array behaves like a real java int array. But additionally Nashorn performs implicit type conversions under the hood when we're trying to add non-integer values to the array. Strings will be auto-converted to int which is quite handy.

Collections and For Each

Instead of messing around with arrays we can use any java collection. First define the java type via Java.type, then create new instances on demand.

var ArrayList = Java.type('java.util.ArrayList');
var list = new ArrayList();

for each (var el in list) print(el);  // a, b, c

In order to iterate over collections and arrays Nashorn introduces the for each statement. It works just like the foreach loop in java.

Here's another collection foreach example, utilizing HashMap:

var map = new java.util.HashMap();
map.put('foo', 'val1');
map.put('bar', 'val2');

for each (var e in map.keySet()) print(e);  // foo, bar

for each (var e in map.values()) print(e);  // val1, val2

Lambda expressions and Streams

Everyone loves lambdas and streams - so does Nashorn! Although ECMAScript 5.1 lacks the compact arrow syntax from the Java 8 lambda expressions, we can use function literals where ever lambda expressions are accepted.

var list2 = new java.util.ArrayList();

    .filter(function(el) {
        return el.startsWith("aaa");
    .forEach(function(el) {
    // aaa1, aaa2

Extending classes

Java types can simply be extended with the Java.extend extension. As you can see in the next example, you can even create multi-threaded code in your scripts:

var Runnable = Java.type('java.lang.Runnable');
var Printer = Java.extend(Runnable, {
    run: function() {
        print('printed from a separate thread');

var Thread = Java.type('java.lang.Thread');
new Thread(new Printer()).start();

new Thread(function() {
    print('printed from another thread');

// printed from a separate thread
// printed from another thread

Parameter overloading

Methods and functions can either be called with the point notation or with the square braces notation.

var System = Java.type('java.lang.System');
System.out.println(10);              // 10
System.out["println"](11.0);         // 11.0
System.out["println(double)"](12);   // 12.0

Passing the optional parameter type println(double) when calling a method with overloaded parameters determines the exact method to be called.

Java Beans

Instead of explicitly working with getters and setters you can just use simple property names both for getting or setting values from a java bean.

var Date = Java.type('java.util.Date');
var date = new Date();
date.year += 1900;
print(date.year);  // 2014

Function Literals

For simple one line functions we can skip the curly braces:

function sqr(x) x * x;
print(sqr(3));    // 9

Binding properties

Properties from two different objects can be bound together:

var o1 = {};
var o2 = { foo: 'bar'};

Object.bindProperties(o1, o2);

print(o1.foo);    // bar
o1.foo = 'BAM';
print(o2.foo);    // BAM

Trimming strings

I like my strings trimmed.

print("   hehe".trimLeft());            // hehe
print("hehe    ".trimRight() + "he");   // hehehe


In case you forget where you are:

print(__FILE__, __LINE__, __DIR__);

Import Scopes

Sometimes it's useful to import many java packages at once. We can use the classJavaImporter to be used in conjunction with the with statement. All class files from the imported packages are accessible within the local scope of the with statement:

var imports = new JavaImporter(java.io, java.lang);
with (imports) {
    var file = new File(__FILE__);
    // /path/to/my/script.js

Convert arrays

Some packages like java.util can be accessed directly without utilizing Java.type orJavaImporter:

var list = new java.util.ArrayList();

This code converts the java list to a native javascript array:

var jsArray = Java.from(list);
print(jsArray);                                  // s1,s2,s3
print(Object.prototype.toString.call(jsArray));  // [object Array]

And the other way around:

var javaArray = Java.to([3, 5, 7, 11], "int[]");

Calling Super

Accessing overridden members in javascript is traditionally awkward because javas superkeyword doesn't exist in ECMAScript. Luckily nashorn goes to the rescue.

First we define a super type in java code:

class SuperRunner implements Runnable {
    public void run() {
        System.out.println("super run");

Next we override SuperRunner from javascript. Pay attention to the extended nashorn syntax when creating a new Runner instance: The syntax of overriding members is borrowed from javas anonymous objects.

var SuperRunner = Java.type('com.winterbe.java8.SuperRunner');
var Runner = Java.extend(SuperRunner);

var runner = new Runner() {
    run: function() {
        print('on my run');

// super run
// on my run

We call the overridden method SuperRunner.run() by utilizing the Java.super extension.

Loading scripts

Evaluating additional script files from javascript is quite easy. We can load both local or remote scripts with the load function.

I'm using Underscore.js a lot for my web front-ends, so let's reuse Underscore in Nashorn:


var odds = _.filter([1, 2, 3, 4, 5, 6], function (num) {
    return num % 2 == 1;

print(odds);  // 1, 3, 5

The external script will be evaluated in the same javascript context, so we can access the underscore variable directly. Keep in mind that loading scripts can potentially break your own code when variable names are overlapping each other.

This problem can be bypassed by loading script files into a new global context:


Command-line scripts

If you're interested in writing command-line (shell) scripts with Java, give Nake a try. Nake is a simplified Make for Java 8 Nashorn. You define tasks in a project-specific Nakefile, then run those tasks by typing nake -- myTask into the command line. Tasks are written in javascript and run in Nashorns scripting mode, so you can utilize the full power of your terminal as well as the JDK8 API and any java library.

For Java Developers writing command-line scripts is easy as never before...

That's it

I hope this guide was helpful to you and you enjoyed our journey to the Nashorn Javascript Engine. For further information about Nashorn read herehere and here. A guide to coding shell scripts with Nashorn can be found here.

I recently published a follow up article about how to use Backbone.js models with the Nashorn Javascript Engine. If you want to learn more about Java 8 feel free to read my Java 8 Tutorialand my Java 8 Stream Tutorial.

The runnable source code from this Nashorn tutorial is hosted on GitHub. Feel free to fork the repository or send me your feedback via Twitter.

Keep on coding!

출처 : http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/

자바스크립트 클로저(Closure)에 대해서...

자바스크립트에는 클로저( Closure)라는 개념이 있습니다.(랭귀지에 따라 클로저가 있는 언어도 있고 그렇지 않은 언어도 있습니다.) 오랫동안 잘 이해하고 있다가 어느정도 이해는 되었지만 아직 몸에 익지 않았다가 최근에 두번이나 클로저로 해결할 문제를 누가 물어와서 정리를 합니다.

클로저는 자신의 범위(Scope) 밖에 있는 변수들에 접근할 수 있는 함수를 의미합니다.

사실 이 말만 가지고는 잘 감이 오지 않고 보통 자바스크립트내에서는 함수의 생명주기는 끝이났지만 함수내의 변수를 내부함수가 참조하고 있기 때문에 유지되어 접근할수 있는 함수를 클로저라고 합니다.

<input type="button" id="btn1"/>
<input type="button" id="btn2"/>
<input type="button" id="btn3"/>
<input type="button" id="btn4"/>

위와 같이 버튼이 4개 있고 각 버튼을 클릭했을때 각 버튼당 1,2,3,4가 찍히게 하고 싶다고 하겠습니다. 당연히 가장 쉬운 방법은 각 버튼에 인라인으로onclick="alert('1')" 처럼 각 버튼당 파라미터를 주는 것이 쉽겠지만 이럴 경우 요즘 일반적인 구조와 동작을 불리하는 Unobtrusive Javascript에도 맞지 않고 유지보수에도 별로 좋지 않습니다. 

일반적으로 사람들이 위와같은 구현을 하기 위해서 가장 먼저 시도하는 코드는 아래와 같을 것입니다.

window.onload = function() {
    for(var i=1; i < 5; i++ ) {
        document.getElementById("btn" + i).addEventListener("click", function() {
        }, false);

모두는 아니겠지만 보통 위와같은 코드를 시도하리라고 생각하고 정상적으로 동작할 것을 기대하지만 위 코드는 제대로 동작하지 않습니다. for문을 돌면서 각 버튼에 click이벤트리스너를 등록하고 각 루프에서의 i를 alert으로 보여줍니다. 이렇게 할경우 의도한 것은 1,2,3,4의 alert()을 의도한것이지만 alert()에 넘겨준 파라미터는 i의 값이 아닌 i의 참조이기 때문에 실제 버튼을 클릭하면 모든 버튼을 클릭할 때 i의 최종값이 5가 모두 찍혀버립니다. 

이 상황이 클로저가 적합한 상황인데 클로저를 사용하는 것은 이해만 하면 그렇게 어렵지 않습니다.

window.onload = function() {
    for(var i=1; i < 5; i++ ) {
        (function(m) {
            document.getElementById("btn" + m).addEventListener("click", function() {
            }, false);

위와 같이 작성합니다. for문안에 실행할 구문을 익명함수( (function() {})와 같은 형태)로 만들고는 i를 파라미터로 넘기면서 실행시켜버립니다.(익명함수에 (i)를 붙혀서 바로 실행시켰습니다.) 이렇게 하면 익명함수안의 내부변수인 m에 i의 값이 할당되어 버리고 구조상은 실행뒤에 소멸되어야 하지만 클로저로 인하여 각 값으로 할당된 멤버변수를 각 이벤트리스너에서 그대로 사용할 수 있게 됩니다. 위 코드로 실행하면 각 버튼을 클릭시 1,2,3,4의 원하던 값이 찍히게 됩니다.

덧) 그냥 예제코드이기 때문에 표준인 addEventListener만을 사용했습니다. IE에서 돌려보실 계획이라면 attachEvent를 사용하셔야 합니다.

덧2) 제가 클로저의 개념을 아주 명확히 파악하지 못한관계로 설명이 명확치 않았습니다. 위 소스에 대한 명확한 설명은 아래 댓글에 odyss님이 해주셨으므로 참고해주시기 바랍니다. 공부를 더 열심해야겠군요. ㅠㅠ

출처 : http://blog.outsider.ne.kr/506