2010/08/31 - [Review/IT] - jquery 플러그인 만들기 (1)
jquery 플러그인 만들기 (1) 편에 이은 연재글입니다.

이전에 만들었던 플러그인에는 작은 단점이 있다. 바로 범용성이 떨어진다는 것인데, 플러그인은 어떤 환경에서 쓰일지 모르기 때문에 보편적으로 만들어야 한다.

간혹 jquery와 prototype.js 등의 프레임워크를 동시에 사용하는 환경이 있는데, 이런 경우 jquery의 $ 를 다른 표현으로 사용하기도 한다. 하지만 우리가 만들어놓은 플러그인은 $ 를 사용하기 때문에 충돌이 날 수 있다.

해결책으로 자신이 만든 플러그인 메소드를 래핑하는 방법이 있다.

우선 형식은 다음과 같다. (function() { statement })() 
자신이 만든 메소드를 유효범위로 감싸면서 내부의 변수와 함수들을 private 하게 만드는 것이다.

(function() { statement })()  빨간색으로 되어 있는 부분을 하나의 함수명 이라고 생각하면 좀 더 쉽다.
function() 이 될텐데, 이는 마찬가지로 인자를 넘길 수 있다는 뜻이 된다.
(function() { statement }) == function 

우리는 일전에 아래와 같은 플러그인을 만들었다.
$.fn.Alert = function() {
	return alert(this[0].id);
}
이걸 유효범위로 만들기 위해 아래와 같이 수정한다.
(function($) {
    $.fn.Alert = function() {
	return alert(this[0].id);
    }
})(jQuery);
이렇게 되면 $ (여기서는 jQuery) 변수를 익명함수의 인자값으로 넘기고, 익명함수는 jQuery 를 $로 받아서 플러그인에서는 계속 $를 사용할 수 있다.


신고
Posted by onionmen

댓글을 달아 주세요
















 
jQuery 에 대한 기본적인 문법적 이해가 있다는 가정하에 문서를 작성합니다.

약 1년간 jQuery를 사용하면서 jQuery가 제공하는 자바스크립트 사용의 편의성에도 매우 감탄했지만, 정말 매력적이었던 부분은 플러그인에 대한 지원이었다.

한동안 남들이 만들어놓은 플러그인 들을 고맙게 가져다 썼지만, 어느 시점에서 부터 요구사항에 맞는 플러그인을 찾기가 쉽지 않았다. (이는 우리 사이트에서 jQuery를 필요로 하는 부분이 그만큼 많아졌다는 것에 대한 반증이기도 하다.) 

요구사항에 맞춰서 UI를 만들다 보니 기존에 사용하던 플러그인을 대충 수정하면서 사용했지만, 점점 더 높아지는 요구사항에 아예 플러그인을 새로 만드는게 더 나아보였다.

겸사겸사 간단하게 플러그인을 만드는 방법을 작성해볼까 한다.

기본적으로 jQuery를 사용함에 있어서 사용하는 플러그인의 타입은 크게 아래 두 종류 이다.
  1. $('div').plugin_name();
  2. $.plugin_name();
1번은 셀렉터를 이용하여 메소드체인을 생성할 수 있고, 2번은 그냥 function 이다.


1. $('div').plugin_name(); 를 만들어보자.
jquery.test-plugin.js
$.fn.Alert = function() {
	return alert(this[0].id);
}





div tag를 셀렉터로 하여 정보를 출력하는 간단한 플러그인이다.
위와 같이 작성하면 간단하게 끝난다.

위 메소드에서 두가지를 살펴볼 수 있는데, 하나는 this 이고, 나머지 하나는 그 this를 리턴하는 것이다.
this는 예상하는대로 div 엘리먼트에 대한 참조이고, this를 리턴하는 이유는 메소드체인을 사용하기 위함이다.


this 에 대한 프로퍼티를 확인해보면, 할당된 Method 들이 있고, 이 div 엘리먼트에 대한 프로퍼티를 담고있는 배열( [0] )이 있다. 
div 엘리먼트가 하나라고 가정할 수 없으니, 배열로 엘리먼트를 구분하는 것이다. (현재는 html 상의 div가 한개 뿐이므로, 배열도 한개만 나온다. div 엘리먼트가 여러개라면 배열 또한 그에 상응하게 나타난다.)

jquery의 강점중 하나는 메소드 체인을 사용할 수 있다는 것인데, 예를 들어서 $("div").Alert().fadeOut(); 과 같은 코드를 사용할 수 있다는 것이다.

메소드 체인이 끊어지지 않게 하기 위해서는 jquery 객체 (여기서는 this) 가 리턴되어 유지되는 것이 중요하다.

$.fn.Alert = function() {
	return this.each(function(i,k) {
		alert(k.id);
	});
}
그리고 div 와 같은 엘리먼트들은 배열(오브젝트) 이기 때문에 each 와 같은 순환문을 통하여 "사용하고 리턴될 수" 있어야 한다.


2. $.plugin_name(); 를 만들어보자.
jquery.test-plugin2.js
$.Alert = function() {
	alert("plugin-test");
}

1번과 비교해서 fn 부분이 제거되고, return 되는 부분도 없다. 그냥 일반적인 함수 작성하듯 만들면 된다.(함수니까!) 하나의 기능만을 담당하는 것이라면 문제는 없다.

이는 아래와 같이 사용된다.



신고
Posted by onionmen

댓글을 달아 주세요


클로저는 실무에서 자바스크립트로 개발을 하다보면 자신도 모르게 사용했던 개념이다. 클로저는 몰라도 예제코드를 보면 "아하, 그게 클로저야?" 라고 되묻는 사람들이 꽤 많을 것이다.

아래 코드를 보자.

var closureTest = function() {
	var closureVar = "closure test";

	return function() {
		alert(closureVar);
	}
}

closureTest 라는 함수는 closure test 라는 문자열을 출력하는 익명함수를 리턴한다. 그리고 위 코드를 수행하면 정상적으로 closure test 메시지가 alert창으로 뜬다.

위 코드가 왜 이상한지 모르겠는 사람은 클로저에 대한 이해가 충분하거나, 아니면 자바스크립트에 대한 이해가 불충분한 사람일 것이다.

기본적으로 closureVar 변수는 closureTest 에 속한 지역변수 이기 때문에 다른 외부함수에서 호출하는 것이 불가능하다. 변수를 호출하기 위한 방법으로는 지역변수로 선언된 closureVar 변수를 전역변수로 바꿔 선언하는 방법이 있다. 

그런데 자바스크립트에서는 굳이 이렇게 하지 않아도, 함수에 속한 지역변수를 다른 함수가 호출하게 하는 것이 가능하다. 이게 바로 클로저다. 좀 더 정확하게 이야기 하면, 클로저란 자신이 생성된 함수의 context에 직접 접근(참조) 할 수 있는 것이다.

위 코드를 좀 더 쉽게 풀어보면 아래와 같다.

var closureTest = function() {
	var closureVar = "closure test";

	return closureTest2();
}

var closureTest2 = function() {
	alert(closureVar);
}

하지만 위 코드는 제대로 동작을 하지 않는다. closureVar 변수가 closureTest 함수에 선언되었기 때문에, closureTest2 함수에서 접근할 수 없기 때문이다. 

위 코드를 동작시키기 위해선 closureVar 변수를 전역변수로 새로 선언해야 한다.

var closureVar = "";
var closureTest = function() {
	closureVar = "closure test";

	return closureTest2();
}

var closureTest2 = function() {
	alert(closureVar);
}
하지만 변수가 많아진다면 이 모든 변수를 전역변수로 할당해야 하는데, 코드도 어려워지고(지저분해지고) 개발자도 힘이 든다. 변수를 모두 전역변수로 선언하지 말고, 클로저를 잘 이해하여 써먹어보자.


신고
Posted by onionmen

댓글을 달아 주세요

  1. Favicon of http://coolmoo.net BlogIcon 나비오 2010.07.21 23:24 신고  댓글주소  수정/삭제  댓글쓰기

    이해하고 싶지만 당췌 봐도 모르겠다는...
    제가 정말로 무식하죠ㅜㅜ
    저도 오늘 자바 책 하나 사긴 했는데 걱정이 앞서네요

  2. Favicon of http://pam.ncity.net/wp BlogIcon pam 2010.10.24 12:42 신고  댓글주소  수정/삭제  댓글쓰기

    큰 깨닫음 얻고 갑니다. 크..

  3. 지나가던이 2010.12.02 11:21 신고  댓글주소  수정/삭제  댓글쓰기

    "함수에 속한 지역변수를 다른 함수가 호출하게 하는 것이 가능하다. 이게 바로 클로저다."
    라는 설명은 그냥 내부함수에서 외부함수의 변수를 접근할수 있다. 즉 scope, 유효범위에 대한것 같네요 ^^;
    "클로져는 자신의 외부에 선언된 변수를 참조가 아닌, 복사본으로 가지는 함수"라고 봄이 맞지않나 싶네요
    http://asrada2001.tistory.com/201 여기를 참고하시면 더 이해가 빠를듯합니다

  4. 느네 2011.04.24 10:32 신고  댓글주소  수정/삭제  댓글쓰기

    좋은정보 얻고 갑니다~
    출처 밝히고 내용좀 퍼갈께요 ㅎㅎ

IE9의 개발자 테스트 버전이 출시되었습니다. (바로가기링크)

주요이슈로는 HTML5 지원, CSS3 지원, 속도향상, 자바스크립트 엔진 교체 등이 있습니다.


자바스크립트의 엔진을 Webkit SunSpider 로 교체하여 획기적인 웹서핑 속도향상이 예상됩니다. IE8 버전에 비해서 여섯배정도 성능 향상이 있다고 나오는데요, 아마 정식 버전에서는 더 빨라질 것 같습니다. IE8도 이전 버전들에 비해서 정말 많은 렌더링 성능의 향상이 있었던 제품인데, IE9과 IE7, IE6 과는 어느정도 차이가 날까요. 

그 외에도 당연히 지원되야 하는 것들을 지원한다고 광고하고 있습니다. 웹개발자 입장에서는 반갑기도 하면서 또 힘들기도 하네요. 국내에서 IE6만이라도 사라져준다면 감사하겠는데 말이죠.

올해 안에 정식버전이 출시되었으면 좋겠네요.

IE9는 비스타 SP2 이상에서 동작합니다. GPU를 사용하기 때문이라고 하네요.
프리뷰페이지는 크롬에서 모든 데모가 활성화 되고, IE8에서는 일부 데모만 확인할 수 있습니다.
신고
Posted by onionmen

댓글을 달아 주세요


웹 사이트 최적화 기법: UI 개발자를 위한 필수...
카테고리 컴퓨터/IT
지은이 스티브 사우더스 (아이티씨, 2008년)
상세보기

200페이지도 안되지만 꽤나 유용한 책이다.
아래는 책에서 이야기 하고 있는 내용을 다시 정리할겸 요약한 내용이다.

1. HTTP 요청을 줄여라.
- 웹페이지에 접근하면 웹브라우저(익스플로러, 파이어폭스등) 에 보여지는 모든 화면들이 HTTP 요청에 의해서 나타나는 것이다. HTML 코드는 물론이고 이미지 하나하나 모두 HTTP 요청이다.
아래 이미지 에서 보이는 것 처럼 GET 방식을 통한 HTTP 요청에 대한 응답이다.

각 요청마다 짧게는 0.008초에서 길게는 3초까지의 요청에 대한 시간이 나타나고 있는데, HTTP 요청이 줄어들면 줄어든 만큼 당연히 이 시간도 짧아지기 때문에 웹페이지 로딩속도가 짧아진다.

2. CDN을 사용하라.
브라우저가 웹서버에 요청을 하게 되면 웹서버가 살아있는한 응답을 한다. 보통 서버가 위치한 곳과 응답을 요청한 곳과의 거리에 따라서 응답속도가 달라지는데 물론 이 응답속도는 이 둘의 위치가 가까울수록 더 빠르다. (A와 B가 어떤 대화를 하는데, 이 둘이 직접적으로 이야기는 못하고, 중간에 꼭 어떤 사람을 거쳐야 한다면, 다섯명을 거치는것이 빠를지, 열명을 거치는것이 빠를지 생각해보면 쉽겠다.)

A라는 업체의 서버가 서울에 있다. 이 서버에 대한 응답요청을 제주도 에서 하는것보다 서울에서 하는게 빠르다는거다.
그런데 이 A라는 업체가 제주에서 응답요청을 하는 사람에게 좀 더 빠른 응답속도를 제공하기 위해서 제주에 서버를 두는건 일종의 낭비이다. 그래서 이런 역할을 CDN이 해주는 것이다.

물론 거의 대부분이 유료이다.

3. 헤더에 만료기한을 추가해라
이는 곧 브라우저캐시를 사용하라는 말이다. 사용자가 웹페이지에 접근할 때마다 매번 이미지를 새로받고, HTML을 새로 받는다면 사용자에겐 시간이 낭비되고, 서비스 제공업자에겐 트래픽이 낭비된다. 그래서 사용자브라우저에게 이 페이지는 앞으로 한달간 변경이 되지 않을 테니 서버에서 새로 가져갈 필요가 없다고 알려주는 것이다.
이렇게 되면 HTTP요청이 줄기 때문에 응답시간이 절약되고, 여기에 서버에서 데이터가 전송되지 않기 때문에 트래픽이 줄어든다. 사용자는 온라인으로 데이터를 가져오지 않고, 자신의 컴퓨터에서 가져오기 때문에 서비스이용속도가 올라간다.

4. 데이터를 압축해라.
gzip 컴포넌트를 사용하여 데이터를 압축한다.
참고자료 링크

5. 스타일시트의 위치
스타일 시트는 head 태그 사이에 넣어라. 다른곳에 스타일시트가 위치할 경우 페이지 로딩이 점진적이지 않고 멈춘 후 한꺼번에 보여진다.

6. 스크립트는 아래에 넣어라
페이지 하단에 스크립트를 위치시키는 것이 웹페이지 로딩에 빠르다고 한다.
하지만 난 head 사이에 넣고 있다.

7. CSS Expression을 피하라.
background-color: expression( (new Date()).getHours()%2 ? "#FFF" : "#000" );
IE에서는 위와같은 표현식이 가능하다. 하지만 쓰지말라고 한다. 어차피 쓸일이 없을것 같다.

8. 자바스크립트와 스타일시트는 외부파일로 빼라.

9. DNS조회를 줄여라.
결국 외부도메인 참조하는 것을 줄이라는것. keep-alive를 사용한 적절한 캐시도 좋다.

10. 자바스크립트를 최소화 해라
압축등을 사용해서 자바스크립트의 용량을 줄여라. 물론 CSS도 줄일수 있으면 줄여라.

11. 리다이렉션을 줄여라
리다이렉션할 주소 끝에 "/" 슬래시를 붙이지 않는다면 슬래시(/)을 붙여서 리다이렉트가 발생한다. 그 외에도 document.location 과 같은 자바스크립트 코드의 사용을 줄여라.

12. 중복스크립트를 없애라.
자바스크립의 코드의 중복을 제거하라. 모듈화 하여 적절하게 사용하라. 프로그램의 크기가 커져서 관리가 어려울 경우 별도의 hash 함수를 만들어서 스크립트를 관리하라. <- php 창시자인 rasmus 는 html코드를 php가 생성하는 것에 대해 부정적이었다. 어느 것이 좀 더 효율적인지는 직접 체크해봐야 할듯하다.

13. ETag를 설정하라.(또는 삭제하라.)
ETag는 웹서버와 브라우저간의 캐시유효성을 체크하는 메커니즘이다. 대부분은 기본설정을 이용하면 되지만 여러대의 웹서버를 가진 웹어플리케이션의 경우는 기본설정이 성능저하의 요인이 된다.
설정을 변경하든가 삭제하라. 아파치의 경우는 설정파일에 FileETag none 한줄을 추가해주면 된다고 한다.


위 13가지 내용들은 파이어폭스 플러그인인 YSlow를 사용하여 체크해볼 수 있다.있다.
신고
Posted by onionmen

댓글을 달아 주세요

  1. Favicon of http://jagto.tistory.com BlogIcon 작토 2012.12.12 14:55 신고  댓글주소  수정/삭제  댓글쓰기

    컴퓨터쪽 전문가가 아니면 좀 어려운 내용이네요..;; 지금 제 사이트가 느려서 고민중이에요 ㅠ

    • Favicon of http://onionmen.kr BlogIcon onionmen 2012.12.12 22:59 신고  댓글주소  수정/삭제

      안녕하세요. 반갑습니다. ^^
      작토님 블로그에 들어가보니, 평균 블로그 로딩시간이 5~6초 정도 되더군요.

      간략하게나마 확인 해보니 페이스북 위젯에서 약 2초 정도 딜레이가 생깁니다.

      그 외에도 플러그인들 몇몇개가 사이트 로딩을 지연시키는 요인이 되고 있네요.

      티스토리는 별도 서버설정을 할 수 없으므로 속도를 향상시킬 수 있는 방법은 플러그인을 제거하고, 스킨을 가벼운 것으로 바꾸는 것입니다.

      블로그 초반에 사진들이 많이 나오는데, 그것도 사이트 로딩에 1초 정도 딜레이를 주고 있습니다.

      우선 페이스북 위젯만 제거해도 큰 성능 향상이 있을것으로 보이네요. ^^

4년~5 년 전만 해도, 게시판에 글을 쓸 때 폰트의 크기를 키우거나, 색상을 변경하고 싶으면, 사용자가 직접 HTML 태그를 사용해서 글을 작성해야 했습니다. 그나마도 게시판에서 HTML을 지원해 줘야 가능한 일이었습니다. 그러다가 점점 기술이 발전해 나가고, 사용자의 편의를 신경 쓰게 되니, ActiveX를 사용한 웹게시판이 포털사이트를 중심으로 등장했습니다. 귀여운 아이콘도 넣을 수 있도록 말이죠. 하지만 최근 반ActiveX 지향적인 바람이 불면서, MS IE에서만 동작하는 이러한 게시판에 대한 원성이 높아지고 있습니다. ActiveX를 도입했던 많은 곳에서 이제 ActiveX 를 제거하고, javascript를 사용한 에디터 게시판으로 전향했습니다. 별도의 프로그램을 설치하지 않아도 되는 rich 게시판은 사용자에게 유용하게 사용될 수 있습니다. 물론 이전에도 이런 기술은 존재 하였고, 몇몇 곳에서 이미 도입하여 사용하고 있었지만, 조명을 받기 시작한 건 얼마 되지 않았습니다.

본 포스팅에서 크로스브라우징이 가능한 RICH Editor를 제작해보도록 하겠습니다.

보통 게시판을 제작할 때, 글 내용을 입력하는 부분은 <textarea> 라는 태그를 사용합니다. 하지만 <textarea>는 text 외에 어떤 html도 입력할 수 없고, 입력하더라도 단지 입력만 될 뿐 외관상 아무런 영향을 미치지 않습니다. 그래서 이 부분은 frame 의 designMode 라는 DOM을 사용하여 처리하게 됩니다. 그럼 코드를 작성해 보도록 하겠습니다.

<html>

    <head>

        <title>simple rich editor</title>

    </head>

    <body>

        <iframe id="richEditor"></iframe>

    </body>

</html>

Html 코딩이 끝났습니다. 추가한 것은 iframe 태그가 전부입니다. 이 상태로 화면을 확인해 봐도 아무것도 할 수 없으니 다음 코드를 작성해 보겠습니다.

<head>

<title>simple rich editor</title>

<script langauge="javascript">

function load()

{

    document.frames['richEditor'].document. designMode = "On";

    }

</script>

</head>

<body onload="load();">

    <iframe id="richEditor"></iframe>

</body>

페이지가 열린 후 iframe 안에 내용을 편집 가능하게 하려면 designMode 가 on 이 되어야 합니다. 그러기 위해서 <body> 안에 onload 이벤트를 사용하여, 페이지가 로드 되면 자동으로 designmode를 on 시키는 코드를 넣었습니다.

이제 코드를 작성하고 Explorer 를 실행시켜 동작시켜보면 Iframe안에 글씨를 써넣을 수 있게 됩니다. 그런데 위 코드는 파이어폭스(FF)에서는 제대로 실행이 되지 않는다는 큰 문제가 있습니다. 애써서 자바스크립트로 새로 코딩하는데, FF에서 제대로 실행되지 않으면 ActiveX를 사용하는 것과 큰 차이점이 없겠지요?

크로스 브라우징을 위해 코드를 조금 개선시켜 보겠습니다.

function load()

{

    if (document.getElementById('richEditor').contentDocument)

    {

        return document.getElementById('richEditor').contentDocument.designMode = "On";

    }

    else

    {

        return document.frames['richEditor'].document.designMode = "On";

    }

}

나머지 부분은 그대로 놔두고, 자바스크립트 부분만 바꾼 모습입니다. 이러면 IE와 FF 모두 잘 동작하는 모습을 볼 수 있습니다. 코드가 지저분해 보이니 리펙토링을 조금 해보면.

function load()

{

    getIFrameID("richEditor").designMode = "On";

}

function getIFrameID(aID)

{

    if (document.getElementById(aID).contentDocument)

    {

        return document.getElementById(aID).contentDocument;

    }

    else

    {

        return document.frames[aID].document;

    }

}

이렇게 해서 조금은 깔끔한 코드가 완성되었습니다.....만, 오히려 더 지저분해진 느낌입니다. 그냥 재사용성을 위함 이라고 해두죠. ^^;;;

이제 글씨들의 스타일을 변경할 수 있는 버튼들을 만들어 넣을 차례입니다.

Html:

<input type="button" value="굵게" onClick="doCommand('bold');"/>

선택된 곳을 굵게 표시할 수 있는 버튼을 만들었습니다. onClick 이벤트로 클릭하면 doCommand 가 실행됩니다.

Javascipt:

function doCommand(command, args)

{

    getIFrameID('richEditor').execCommand(command,false,args);

    document.getElementById('richEditor').contentWindow.focus()

}

doCommand 메소드 입니다. 좀 전에 리펙토링 하면서 만들었던 getIFrameID 메소드와 execCommand 메소드를 사용합니다.

execCommand메소드는 두개의 인자를 갖습니다. 다음 페이지를 참고 하세요.

doCommand(command, args)의 인자 값 중 처음 command는 굵게 만들지, 이텔릭체로 만들지, 언더라인을 그을지 등을 결정합니다. 두번째 args는 첫번째 인자에 따라서 결정되는데, 굵게 만들기와 같은 작업엔 사용하지 않고, 폰트종류나 크기를 결정할 때 입력합니다.

Html :

<input type="button" value="궁서" onClick="doCommand('fontname','궁서');"/>

위 코드를 추가하고 테스트를 해보면, 어떤 의미인지 잘 알 수 있을 것 입니다.

완성된 코드 입니다.

<html>

<head>

    <title>simple rich editor</title>

    <script langauge="javascript">

    function load()

    {

        getIFrameID("richEditor").designMode = "On";

    }

    function getIFrameID(aID)

    {

        if (document.getElementById(aID).contentDocument)

        {

            return document.getElementById(aID).contentDocument;

        }

        else

        {

            return document.frames[aID].document;

        }

    }

    function doCommand(command, args)

    {

        getIFrameID('richEditor').execCommand(command,false,args);

        document.getElementById('richEditor').contentWindow.focus()

    }

    </script>

</head>

<body onload="load();">

    <p>

        <input type="button" value="굵게" onClick="doCommand('bold');"/>

        <input type="button" value="궁서" onClick="doCommand('fontname','궁서');"/>

    </p>

    <iframe id="richEditor"></iframe>

</body>

</html>

다음에는 위 코드에, 기능을 좀 더 추가하고, 페이지의 값을 넘겨 스크립트언어에서 받는 방법을 소개해보도록 하겠습니다.

신고
Posted by onionmen

댓글을 달아 주세요

  1. Favicon of http://echo7995.tistory.com/ BlogIcon echo 2007.12.09 23:39 신고  댓글주소  수정/삭제  댓글쓰기

    난 아무짓도 안했어요 ㅠ

  2. Favicon of http://breathe77777.tistory.com BlogIcon 브리드 2007.12.10 19:39 신고  댓글주소  수정/삭제  댓글쓰기

    밥아저씨가 적절하게 들어가있네요^^;

이전버튼 1 이전버튼

블로그 이미지
손을 따뜻하게 만들어 주고 싶은 애인이 있습니다.
onionmen

달력

 « |  » 2017.12
          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            
DNS Powered by DNSEver.com

최근에 올라온 글

Yesterday117
Today100
Total1,624,889

티스토리 툴바