본문 바로가기

3.구현/HTML5&Javascript

[jquery] jQuery 플러그인 제작을 위한 기초

들어가기

jQuery는 한때 정말 많이 사용했던 라이브러리이다. reack나 vue.js가 나오면서 사용이 뜸해지기는 했지만, 아직도 사용되는 툴이다. jQuery는 플러그인 확장 기능을 제공하고 있다. 이를 이용한 여러 추가 기능이나 컨포넌트 제작에 많이 사용되었다.

작성자: ospace114@empal.com, http://ospace.tistory.com/

기존에 사용하는 방식

jQuery를 사용해서 DOM 객체을 찾고 스타일 변경할 경우 아래처럼 많이 사용한다.

$('a').css('color', 'red');

모든 링크 태그에 대해서 color라는 스타일에 red 값을 할당한다. 이전에는 모든 링크 테그를 찾고 루프를 통해 하나씩 스타일을 적용해야했지만, jQuery을 사용하면 루프없이 바로 적용할 수 있다.

기본적인 활용

위의 스타일을 매번 적용하기 귀찮기 때문에 함수로 만들 수 있다. 물론 일반적인 함수를 만들서 사용할 것이다.

function warning(el) {
  el.css('color', 'red');
}
warning($('a'));

이렇게 해도 되지만 jQuery에 함수를 추가해서 활용하는 더 효과적이다.

$.fn.warning = function() {
  this.css('color', 'red');
};
$('a').warning();

기존 jQuery 활용하는 방법처럼 더 깔끔하고 가독성도 더 좋다.

연속적으로 적용

jQuery는 찾은 대상에 대해서 작업을 연속적으로 처리할 수 있다.

$.fn.warning = function() {
  this.css('color', 'red');
  return this;
};
$('a').warning().addClass('warned');

warning()에서 마지막에 return이 추가되었다. 그러면 이후에 연속적인 작업이 가능하다. 마지막 코드에서 링크 태그가 있는 대상에 대해서 warning()을 수행하고 다시 greeified 클래스를 추가할 수 있게 된다.

$ 별칭과 스코프

jQuery에서 가장 대표적인 표현으로 $을 사용한다. 거의 대부분 $를 사용한다면 jQuery를 인식한다. 그러나 $ 변수가 jQuery에서 매우 유명하지만 변수 충돌 가능성이 존재한다. 또한 플러그인 제작을 해서 별도 라이버리 파일로 배포할 경우 $ 변수를 사용할 수 없게 된다. 이런 부분을 해결할 수 있는 부분인 private 변수로 선언해서 사용하면 된다. 실제 사용 예를 보자.

(function($) {
  let color = 'red';
  $.fn.warning = function() {
    this.css('color', color);
    return this;
  };
}(jQuery));

함수로 감싸서 처리 처리하는 모습을 보여준다. 이렇게 함수로 감싸면서 캡슐화처럼 처리할 수 있게 된다. private 함수를 정의해서 사용할 수 있다.

(function($) {
  $.fn.warning = function() {
    this.css('color', color);
    debug();
    return this;
  };
  function debug() {
    //...
  }
}(jQuery));

함수 확장 최소화

jQuery의 $.fn에는 다양한 기능이 추가되어 있다. 그렇기에 같은 이름을 사용할 가능성이 크고 차후 확장을 고려해 가급적 추가를 최소화하도록 만드는게 좋다.

(function($) {
  $.fn.openPopup = function() { ... };
  $.fn.closePopup = function() { ... };
})(jQuery));

위 처럼 필요한 함수를 매번 추가하는 것 보다 비슷하거나 동일한 목적을 가졌다면 함수 하나만 추가해서 사용하기를 권장한다.

(function($) {
  $.fn.popup = function(action) {
    if (action === 'open') {
      // open
    } else if (action === 'close') {
      // close
    }
  };
})(jQuery));

each() 사용

jQuery 객체에는 여러 DOM 객체가 포함될 수 있다. 이런 여러 DOM 객체에 대해서도 개별적으로 처리하는 방법이 있다.

$.fn.myFunction = function() {
  return this.each(function() {
    // 각 객체 처리
  });
};

each()에서 객체가 한개 또는 여러개 인 경우에 대해서 알아서 처리해준다. 우리가 할 부분은 각 객체에 대해 처리하는 코드만 추가해주면 된다. 상당히 간편하게 여러 객체에 대해서도 개별적으로 처리할 수 있다. 주의할 부분은 each()에 의해서 처리할 때 this을 사용해서 객체 참조한다. 이 객체는 jQuery 객체가 아니라 DOM 객체이다.

옵션 처리

DOM 객체에 대해 작업할 때에 옵션을 넘겨서 다양한 기능을 설정할 수 있게 하는게 좋다. 이는 플러그인 개발할 때에 알아두면 도움이 된다.

(function($) {
  $.fn.warning = function(options) {
    let settings = $.extends({
      color: 'red',
      backgroundColor: 'white'
    }, options);

    return this.css({
      color: settings.color,
      backgroundColor: settings.backgroundColor
    });
  };
}(jQuery));

warning()에서 변수 options으로 옵션을 받을 수 있게 했다. 그리고 $.extends()에 의해서 현재 설정된 값과 options 변수를 합친다. 현재 설정된 값이 기본 값으로 활용되어 option에 값이 없을 경우 적용된다고 보면 된다. 마짐가으로 css()에서 스타일이 적용된다. 물론 css()에 직접 settings을 넘길 수도 있지만, 다른 속성값도 포함될 수 있기에 하나씩 적용했다.

실제 적용한 예를 보면

$('div').warning({color:'orange'});

이 정도가 되면 warning()을 다르게 변경해야될지 모르겠다. ㅡ.ㅡ;;;
옵션을 사용한 콜백기능도 지원할 수 있다. 콜백 함수를 잘 사용하면 확장하기 좋은 기술이다.

$.fn.myFunc = function(options) {
  let settings = $.extend({}, $.fn.myFunc.defaults, options);
   settings.onCallback.call();
}
$.fn.myFunc.defaults = {
  onCallback = function() {}
};

값을 문자열로 표현 지양

사람에 따라 모호하게 받아들일 수 있는 표현은 지양한다. 예를 들어 시간의 크기를 "short", "long" 처럼 표현할 수 있다. 물론 보기에는 좋아 보일 수 있지만 어떤 값을 사용했는지 알고 싶다면 값을 찾아봐야한다. 그렇기에 숫자형태로 표현하는게 좋다.

switch(delay) {
case 'short':
  //...
  break;
case 'long':
  //...
  break;
}

jQuery 객체를 생성

DOM 객체를 생성해서 사용하는 경우가 많다. 이때 jQuery에서 일반적인 HTML 형태로 추가해서 사용할 수도 있지만 jQuery 객체로 추가해서 사용하는걸 추천한다. 이는 다양한 옵션을 활용할 수 있기 때문이다.

$('<div class="foo_option" style="color=red;"></div>).append('body');

한 줄로 깔끔하고 직관적으로 보일 수 있다. 추후 확장이나 관리 측면에서는 아래 방식을 추천한다.

var defaults = { css: { ... } };
$('<div>').addClass('foo_option')
          .css(defaults.css)
          .appendTo(body);

간단한 응용

지금까지 다룬 내용을 간단하게 응용하는 예제를 보자. 이번 예제는 링크에서 href 속성을 추출해서 링크 뒤에 괄호로 감싸서 덧붙이는 작업이다. href에 있는 링크 주소를 보여주는 기능이다.

(function($) {
  $.fn.showLinkLocation = function() {
    this.filter('a').each(function() {
      let obj = $(this);
      obj.append('(' + ${link.attr('href') + ')');
    });
    return this;
  }
}(jQuery));

filter()은 현재 대상에서 조건에 만족하는 객체만 추출한다. 이는 링크 태그가 아닐 경우나 여러 객체가 썩여있을 경우에 고려했다. each()에 의한 개별 객체는 DOM 객체이므로 이를 jQuery로 만들어준다. 그리고 사용 예를 보자.

$('a').showLinkLocation();

그러면 링크가 다음 처럼 변경이 된다.

<!-- 적용 전 -->
<a href="page.html">Foo</a>
<!-- 적용 후 -->
<a href="page.html">Foo(page.html)</a>

showLinkLocation()을 좀더 최적화된 버전으로 변경해보자. append()를 잘 활용하면 손쉽게 대상 뒤에 원하는 문자열을 추가할 수 있다.

(function($) {
  $.fn.showLinkLocation = function() {
    this.filter('a').append(function() {
      return '(' + this.href + ')';
    });
    return this;
  }
}(jQuery));

이전에 attr()은 jQuery 객체이므로 사용할 수 있었고, 여기서는 일반 DOM 객체이므로 href을 사용했다.

마무리

아직도 많이 사용하고 있는 jQuery는 구조적으로도 참고할만한 아이디어가 많은 라이브러리이다. 이전에 vue.js에서 jQuery을 사용하려는 노력이 있는것을 보아도 쉽게 사라지지 않을 것 같다. 물론 vue.js에서는 jQuery 사용은 제약이 있고 생각보다 사용하기 쉽지 않다.

부족한 글이지만 여러분에게 도움이 되었으면 합니다. 모두 즐거운 코딩생활되세요. ^^ ospace.

참조

[1] How to Create a Basic Plugin, https://learn.jquery.com/plugins/basic-plugin-creation/

[2] Advanced Plugin Concepts, https://learn.jquery.com/plugins/advanced-plugin-concepts/

반응형