javascript singleton (자바스크립트 싱글턴)

|
출처 : http://ohgyun.com/248

좋은 정보 감사합니다.. ^^

--------------------------------------------------------------------------------------------------------------
발생일: 2009.12.24

문제:
독립적인 기능을 하는 자바스크립트 클래스를 하나 만들었다.
이 클래스를 싱글턴으로 사용하고 싶다.

또한, 일반적인 getInstance() 라는 스태틱 메서드를 사용하는 대신,
바로 생성자를 호출해서 객체를 만들도록(내부적으로 싱글턴 인스턴스를 리턴) 하려고 한다.

어떻게 하면 자바스크립트에서 생성자만으로 싱글턴을 구현할 수 있을까?


해결책:
한참을 고민해봤다.
이런 방법으로 구현해보면 어떨까?

클래스의 생성자에 대한 유효범위를 제한해두고,
그 유효범위 안에서 window 속성의 클래스 생성자(래퍼)를 다시 정의한다.
(일종의 프록시 패턴이라고 할 수도 있겠다)
window 속성의 클래스 생성자에서는 클래스의 유일한 인스턴스를 만들어 리턴하도록 싱글턴을 구현한다.
즉, 외부에서 클래스 생성자를 호출해서 객체를 만들 때에는,
window 속성의 생성자를 호출하게 되므로 생성자만으로 싱글턴을 구현할 수 있다.


아래 실제 구현 예제를 이해하기 위해 몇 가지 자바스크립트 언어에 대한 선수 지식이 필요하다.

javascript 언어 특징 보기




간단한 실제 구현 모습은 아래와 같다.

    (function() { // (a) 익명함수로 유효범위를 제한한다.
   
        // (b) window 속성의 생성자를 정의한다.
        // 외부에서 생성자를 호출할 때에는 이 생성자가 호출된다.
        window.Singleton = function(name) {
            // (d) 객체가 생성되어 있지 않을 경우, 새 객체를 _instance 에 담는다.
            if (_instance == null) {
                _instance = new Singleton(name);
            }
            return _instance;
        }
   
        // (c) 유일한 싱글턴 인스턴스
        var _instance = null;
       
        // (e) 실제 객체 생성자
        // 외부에서 이 생성자에 접근할 수 없다.
        var Singleton = function(name) {
            this.name = name;
        }
       
    })();


실제 객체의 생성자는 (e) 부분이다.

외부에서 이 객체의 생성자에 접근하지 못하도록 익명함수(anonymous function)로 생성자를 감싸준다.
이 부분이 (a) 부분이 되겠다.

(c) 와 같이 유일한 싱글턴 인스턴스를 담을 변수를 선언해준다. 전역변수와 같이 선언되어 있지만,
이 변수 역시 생성자와 같은 유효범위에 있기 때문에 외부에서는 접근하지 못한다.

이제 외부에서 이 객체를 생성할 수 있도록 (b)와 같이 window 속성에 같은 이름으로 생성자를 구현해준다.
window.Singleton 은 window 속성이기 때문에 외부에서도 호출이 가능하며,
window prefix 없이 바로 new Singleton() 과 같이 호출이 가능하다.
(외부에서 new Singleton(); 을 호출했을 때 (e) 부분의 실제 함수가 호출되는 게 아니다.)
또한, window.Singleton 객체가 유효범위 밖에서 _instance 를 참조할 수 있는 건, 클로저(closure) 때문이다.

window 속성의 객체 생성자(b)에서는 (d)에서와 같이 싱글턴 부분을 구현한다.
_instance 가 존재하지 않을 경우, 새 객체를 생성해 할당하고, 그렇지 않을 경우 이미 존재하는 객체를 리턴한다.

이와 같이 구현하면 외부에서 new Singleton() 을 호출했을 때,
(실제 객체의 wrapper 격인) window.Singleton() 생성자가 호출되며,
window.Singleton 생성자 내에서 싱글턴 객체를 리턴하게 된다.

아래와 같이 호출해보면, new Singleton() 을 통해 싱글턴 객체가 생성되는 것을 확인할 수 있다.

    // 여기서 호출되는 Singleton 생성자는 window.Singleton 이다.
    var s1 = new Singleton('aaa');
    alert(s1.name); // aaa 출력
   
    var s2 = new Singleton('bbb'); // 이미 생성된 객체가 리턴된다.
    alert(s2.name); // aaa 출력



다소 번거롭긴 하지만, 이 방법을 통해 실제 생성자에 대한 접근을 제한할 수 있고,
new 키워드를 통해 싱글턴 객체를 리턴하도록 구현할 수 있다.
(굳이 패턴으로 나누어 생각하려고 한다면, 싱글턴 + 프록시 패턴 정도겠다. )

일반적인 패턴처럼, getInstance() 를 통해 싱글턴 객체를 생성하고 싶을 경우,
같은 방법으로 익명함수 내에서 window.Singleton 안에 getInstance() 를 정의해주면 되겠다.

기타 다른 방법들도 있지만,
기존 생성된 객체를 유지하는 한도 내에서 유용하게 사용할 수 있을 것이라 생각한다.



* 참고:
검색해보니 싱글턴을 구현하는 다른 방법들에 대한 좋은 자료들이 많다.

    1. How to make a singleton in javascript
이 포스트에서는 static getInstance() 메서드를 통해 싱글턴 객체를 생성하는 방법에 대해 설명되어 있다.
가장 알아보기 쉽고 기본적인 방법이니 참고해보도록 하자.
이 포스트에서는 자바스크립트 모듈 패턴을 통해 싱글턴 객체 생성자를 구현했다.
constructor 이름을 통해 이미 만들어진 객체를 싱글턴으로 만드는 전역 메서드 구현에 대한 방법도 있다.
좋은 내용이 많으니 꼭 읽어보자.
약간 다른 방법. 이 포스트도 참고해보자.


그 외,자바스크립트의 유효범위와 클로저에 대해 잘 이해가 안될 경우, 아래 포스트를 참고하자.
And

네이버 OpenAPI 를 AJAX 방식으로 쓰기위한 JSP 프록시 만들기

|
출처 : http://cyzest.tistory.com/8

우선 글을 쓰기에 앞서 해당 구현방법은 철저히 개인적인 방법임을 밟히는 바이다.
(이방법이 최적의 방법 혹은 정석이 될수 없음을 미리 알리는 바이다.)

요즘 네이버나 다음과 같은 여러 포탈 사이트에서 오픈API를 제공하고 있다.
거의 모든 오픈API의 방식이 개인키를 부여하여 특정주소를 요청하면 XML로 결과를 리턴해주는 방식이다.

AJAX 에서의 자바스크립트는 기본적으로 XMLHttpRequest 객체의 open()메소드와 send()메소드를 이용해서 해당 uri의 xml을 요청할 수 있다.

하지만 자바스크립트의 보안제약사항에 따라 XMLHttpRequest 객체는 해당 페이지를 로딩한 서버 외에는 연결할 수 없게 되어있다.
그래서 오픈API요청을 자바스크립트에서 바로 사용할수가 없다.

이것을 해결하기 위해선 여러방법이 있겠지만 그중에서 나는 서버에서 해당 오픈API요청을 대신하고 결과를 보여주는 프록시페이지를 만들어 보기로 했다.

해당 구현방법을 알아보기위해 인터넷의 넓은 바다를 항해한 결과,
아파치 자카르타 프로젝트의 commons HttpClient API를 이용하여 구현하는 방법을 찾게 되었다.

모든 구현을 완료하고 페이지를 실행해보았지만 문제가 생겼다.
좀더 삽질을 하고난후 commons logging APIcommons codec API도 필요하다는것을 알게되었다.
(logging, codec 이 왜 필요한지는 아직 알수없었다. 디버깅과정에서 ClassNotFound 가 뜨는 것들을 추가해주다가 알게되었다.)
(초보의 무식함이다 =..= 만약 아직도 안되고있었다면 계속 삽질을? ;;;)

proxy.jsp

<%@ page language="java" pageEncoding="utf-8"%>
<%@ page import="org.apache.commons.httpclient.HttpClient" %>
<%@ page import="org.apache.commons.httpclient.methods.GetMethod" %>
<%@ page import="org.apache.commons.httpclient.HttpStatus" %>

<%
 request.setCharacterEncoding("utf-8");

 String url = "오픈API요청URI";
 HttpClient client = new HttpClient();
 GetMethod method = new GetMethod(url);
 
 try{
  int statusCode = client.executeMethod(method);
  out.clearBuffer();
  response.reset();
  response.setStatus(statusCode);
  if(statusCode == HttpStatus.SC_OK){
   String result = method.getResponseBodyAsString();
   response.setContentType("text/xml; charset=utf-8");
   out.println(result);

  }
 }finally{
  if(method != null) method.releaseConnection();
 }
%>


나는 네이버 실시간 음악 순위를 리턴받아 보았다.
(get방식으로 파라미터값을 받을수있도록 jsp를 구현한 상태이다.)

http://cyzest.cafe24.com/open/rank/proxy_rank.jsp?query=music


이제 자바스크립트의 XMLHttpRequest 객체에서의 open() 메소드에서는 오픈API주소가 아닌 proxy.jsp 의 주소를 요청하면 되는 것이다.

http://cyzest.cafe24.com/open/rank


이제 해당 오픈API의 결과를 유용하게 이용하도록 구현하는 것은 사용자의 몫이 될것이다. :)

And

[펌][교통] 저렴한 일본일주,JAL 재팬 세이버

|
티스토리 메인에 뜬 포스트를 통해 좋은 정보 발견 ^^
갠적으로는... 1년마다 1~2개월정도의 휴가가 있음 좋겠다능... ^^

http://twalk.tistory.com/226
And