ajax로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

ajax로 검색한 결과
등록일:2008-04-02 13:51:47
작성자:
제목:Javascript 외부 js 파일의 include 제어를 위한 XMLHttpRequest 의 활용


이 내용은 오래전부터 관심을 가지고 간간히 생각해오다가 어제 갑자기 생각난 부분인데, 예전에 dojo툴킷을 쓸 때 비슷한 활용을 본 것 같아서 방금 dojo 툴킷 소스를 받아 열어보니, 역시나.... 기본적인 구현 아이디어가 같다. 이걸 좋아해야 하나.. 말아야 하나. 여하튼 유사한 구조를 따름을 미리 밝혀둔다. 여튼 이해의 차원에서 글을 적어본다.

대부분의 언어에서는 자신이 사용할 기능이 선언된 다른 파일을 부르는 명령이 존재한다.
php에는 include / require 가 있고, java 에는 import가 있다. (둘이 성격이 같다는 이야기는 아니다.)

그 러나 javascript 에는 include 문이 없다. 그래서 한 js 파일(a.js)에서 다른 js 파일(b.js)에 구현된 스크립트를 가져다 쓰기 위해서는 해당 js 파일을 호출한 html 페이지에서 a.js 와 b.js 모두를 호출해주어야 한다.
이는 실제로 사용할 대상에만 관심을 두는 원칙에 위배된다.

따 라서 여타의 js를 include 하는 방법이 필요하다. dojo의 경우 이러한 문제를 해결하기 위해 다음과 같은 선언의 형태로 활용할 수 있도록 만들어졌다. 아래의 예제는 dojo 툴킷 중 TabContainer의 로딩 예제이다.

<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.9.0/dojo/dojo.xd.js" 
        djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
   dojo.require("dojo.parser");
   dojo.require("dijit.layout.ContentPane");
   dojo.require("dijit.layout.TabContainer");
   dojo.require("dijit.form.Button");
</script>

특정 js 파일에서 다른 js 파일을 참조하기 위해서는 필요한 js를 먼저 로딩할 수 있어야 한다.
이러한 방법에는 몇 가지가 알려져 있다.

  1. script 엘리먼트를 만들어서 현  문서에 추가한다. (A)
    var scr = document.createElement("script");
    scr.src = "a.js";
    document.getElementsByTagName("head")[0].appendChild(scr);

  2. document.write / innerHTML을 이용한 직접 태그를 추가한다. (B)
    document.write("<script type='text/javascript' src='b.js'><"+"/script>");
  3. 기타 등등.. (현재 기억 안남)

그러나 위의 방법 중 어떠한 것을 사용해도 수행의 순서를 원하는대로 제어할 수는 없다.
파싱은 기본적으로 다음과 같은 순서로 진행된다. 설명에 사용될 call.js 에는 위에서 설명한 스크립트를 로딩하는 루틴이 모두 포함되어 있다고 가정한다.

  1. html 페이지를 순차적으로 파싱한다.
  2. html 페이지에서 <script src="call.js">태그를 만나면 call.js 파일을 읽어들인다.
  3. call.js 에서 위에 설명한 방법으로 스크립트를 로딩하는 루틴 A를 만나면 call.js 파싱이 모두 끝난 후 A에서 지정한 파일을 읽어들인다.
  4. call.js 내에서 루틴 B를 만나면 html 페이지를 모두 파싱한 후에야 B에서 지정한 js 파일을 읽어들인다.

call.js :
(A 루틴)
(B 루틴)
window.alert("call.js");

a.js :
window.alert("a.js");

b.js :
window.alert("b.js");

라고 각각 쓰여져 있으면,  alert이 나타나는 순서는 call.js, a.js, b.js 순서이다. 아무리 A루틴과 B루틴이 call.js 를 표시하는 루틴보다 앞에 있지만, 파싱 순서상 절대 앞에 나오지 않는다.

즉, 위의 방법으로는 어떤 방법을 써도 브라우저는 먼저 현 페이지의 스크립트를 파싱하고 진행한다.

수행제어를 위한 유일한 돌파구는 SJAX 이다 (비동기가 ajax니까... ;; 동기식은 S(ynchronous)JAX ;;;)
아래 코드는 IE6, FF2.0에서 테스트되었다.
(참고로, dojo 소스를 보아하니 ipv6관련 지원 문제로 uri 파싱도 수정이 가해져야 하는 듯하다. 오마이갓.)

활용은 다음과 같은 형태로 한다.
eval(require_once("/some_path/some.js", true));

해결해야 할 과제.

  1. 어떻게 하면 eval을 쓰지 않게 할 수 있는지.

해결된 과제

  1. require 대상 js 파일의 경로를 이 js 파일로부터 어떻게 하면 상대경로로 잡을 수 있는지.

function require(jsFile, alwaysReload) {
    var url = "http://" + location.host + jsFile;
    var xhr = null;
    var jsSource = "";
 
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }

    if( xhr ){
        xhr.open('get', jsFile, false);
        xhr.send(null);
       
        jsSource = xhr.responseText;
    }
 
 return jsSource;
}

function require_once(jsFile, alwaysReload) {
    if (typeof(document.required_list) == "undefined") {
        document.required_list = new Array();
    }
 
    var isExist = false;
    for (var i = 0; i < document.required_list.length; i++) {
        if (document.required_list[i] == jsFile) {
            isExist = true;
            break;
        }
    }
 
    if (!isExist) {
        document.required_list.push(jsFile);
        var param = (alwaysReload) ? "?hash=" + Math.random() : "";
        return require(jsFile + param, require_once);
    } else {
        return "";
    }
}




XMLHttpRequest를 사용한다고 해서 특별히 성능상의 문제가 발생하지는 않는다. 동기식 통신의 부하는 어차피 <script src="..."> 태그를 썼을때와 동일하다. HTML파서는 서버로부터 HTML을 수신받고 파싱하다가 이 태그를 만나면 해당 src에 선언된 주소에서 파일을 가져오는데, 이 파일을 다 가지고 와서 파싱해야지만 다음 엘리먼트를 파싱한다. 외부 js 호출과 소스 파싱은 절대 비동기가 아니다. 즉, 거의 동일한 성능상의 부하를 가진다.

 

출처 : http://blog.gloridea.net/tag/include