프로그래밍/Javascript

고급 jQuery 마스터하기: 성능 최적화, 라이브러리 통합, UI 활용 가이드

shimdh 2025. 2. 17. 10:02
728x90

1. jQuery 성능 최적화: 빠르고 효율적인 웹 애플리케이션을 위한 핵심 전략

웹 애플리케이션의 성능은 사용자 경험에 직접적인 영향을 미치므로 최적화는 매우 중요한 과제입니다. 이 섹션에서는 jQuery 코드를 최적화하여 더 빠르고 효율적으로 작동하도록 만드는 핵심 전략들을 살펴봅니다.

1.1 선택자 최적화: DOM 검색 효율성 극대화

jQuery의 강력한 기능 중 하나는 CSS 선택자와 유사한 방식으로 DOM 요소를 선택할 수 있다는 것입니다. 하지만 복잡한 선택자는 성능 저하의 원인이 될 수 있으므로, 효율적인 선택자 사용이 중요합니다.

  • ID 선택자 우선 사용: ID는 HTML 문서 내에서 고유해야 하므로, ID 선택자(#myElement)는 가장 빠르고 효율적인 DOM 검색 방법입니다.
  • 클래스 선택자 적극 활용: $('.myClass')와 같은 클래스 선택자는 태그 선택자보다 빠르며, 특히 복잡한 DOM 구조에서 유용합니다.
  • 불필요한 탐색 최소화: $('div > p.myClass')와 같이 부모 요소부터 자식 요소를 찾는 방식은 성능 저하를 유발할 수 있습니다. $('.myClass')처럼 필요한 요소만 직접 선택하는 것이 효율적입니다.
  • 구체적인 예제:
    • 비효율적: $('ul > li.active > a') - 전체 DOM 트리를 여러 번 탐색합니다.
    • 효율적: $('.active > a') - .active 클래스를 가진 요소만 먼저 찾은 후 그 자식 요소 중 a 태그를 찾습니다.
    • 비효율적: $('div#container input[type="text"]') - 불필요하게 태그 선택자와 속성 선택자를 혼합했습니다.
    • 효율적: $('#container').find('input[type="text"]') - ID 선택자로 빠르게 범위를 좁힌 후 find()를 사용합니다.
    • 비효율적: $('.item:first') - 모든 .item 요소를 찾은 후 첫 번째 요소를 선택합니다.
    • 효율적: $('.item').first() - .item 요소 중 첫 번째 요소만 빠르게 선택합니다.

1.2 캐싱: 반복적인 DOM 접근 최소화로 성능 향상

DOM 요소에 반복적으로 접근하는 것은 성능 저하의 주된 요인 중 하나입니다. 한 번 찾은 요소는 변수에 저장(캐싱)하여 재사용함으로써 불필요한 DOM 접근을 최소화하고 성능을 향상시킬 수 있습니다.

  • 기본 예제:
// 캐싱을 사용하지 않은 경우 (비효율적)
$('#myElement').addClass('active');
$('#myElement').hide(); // 매번 #myElement를 다시 찾습니다.

// 캐싱을 사용한 경우 (효율적)
var $myElement = $('#myElement'); // #myElement를 한 번만 찾아서 변수에 저장합니다.
$myElement.addClass('active');
$myElement.hide(); // 변수를 사용하여 접근합니다.
  • 체이닝 및 캐싱 활용 예제:
// 캐싱과 체이닝을 함께 활용 (효율적)
var $myDiv = $('#myDiv').addClass('highlight').show(); // 체이닝으로 여러 작업을 한 번에 처리하고 캐싱합니다.
$myDiv.find('p').text('Hello World!'); // 캐싱된 변수를 활용합니다.
  • 이벤트 핸들러 내 캐싱 예제:
// 이벤트 핸들러 내에서 캐싱 (효율적)
var $listItems = $('.list-item'); // 한 번만 요소를 찾아서 캐싱합니다.
$listItems.on('click', function() {
    $listItems.removeClass('selected'); // 캐싱된 변수를 사용하여 모든 항목의 클래스를 제거합니다.
    $(this).addClass('selected'); // 클릭된 요소에만 클래스를 추가합니다.
});

1.3 이벤트 위임: 효율적인 이벤트 처리로 성능 개선

수많은 요소에 이벤트 핸들러를 바인딩해야 할 때, 각 요소에 개별적으로 바인딩하는 것은 비효율적이며 성능 저하를 초래합니다. 이벤트 위임은 부모 요소에 이벤트 핸들러를 하나만 바인딩하고, 자식 요소에서 발생하는 이벤트를 효율적으로 처리하는 기법입니다.

  • 이벤트 위임의 장점:

    • 이벤트 핸들러의 개수를 줄여 메모리 사용량을 줄이고 성능을 향상시킵니다.
    • 동적으로 추가되는 요소에도 자동으로 이벤트 핸들러가 적용됩니다.
  • 예제:

// 비효율적인 방법: 각 .child 요소에 이벤트 핸들러를 개별적으로 바인딩합니다.
$('.child').on('click', function() {
    $(this).toggleClass('active');
});

// 효율적인 이벤트 위임: #parent 요소에 이벤트 핸들러를 하나만 바인딩하고, .child 요소에서 발생하는 이벤트를 처리합니다.
$('#parent').on('click', '.child', function() {
    $(this).toggleClass('active');
});
  • 동적 요소에 대한 이벤트 위임 예제:
// 동적으로 추가되는 li 요소에도 이벤트 핸들러가 자동으로 적용됩니다.
$('#myList').on('click', 'li', function() {
    console.log($(this).text());
});
  • 특정 자식 요소에 대한 이벤트 위임 예제:
// #container 내의 .hoverable 요소에 대해서만 이벤트 위임을 적용합니다.
$('#container').on('mouseenter mouseleave', '.hoverable', function(event) {
    if (event.type === 'mouseenter') {
        $(this).addClass('hover');
    } else {
        $(this).removeClass('hover');
    }
});

1.4 배치 업데이트: DOM 조작 최소화로 렌더링 성능 향상

DOM 조작은 브라우저의 리플로우(reflow)와 리페인트(repaint)를 발생시켜 성능 저하를 유발합니다. 효율적인 렌더링을 위해 가능한 한 많은 변경 사항을 모아서 한 번에 적용하는 배치 업데이트를 사용하는 것이 좋습니다.

  • 기본 예제:
var $container = $('#container');

// 비효율적인 방법: append()를 여러 번 호출하여 매번 DOM을 업데이트합니다.
$container.append('<div>New Element 1</div>');
$container.append('<div>New Element 2</div>');
$container.append('<div>New Element 3</div>');

// 효율적인 배치 업데이트: HTML 문자열을 생성하고, append()를 한 번만 호출하여 DOM을 업데이트합니다.
var newElements = '';
newElements += '<div>New Element 1</div>';
newElements += '<div>New Element 2</div>';
newElements += '<div>New Element 3</div>';
$container.append(newElements);
  • createDocumentFragment()를 사용한 효율적인 DOM 조작:
// 가상의 DOM 트리 조각을 생성합니다.
var fragment = document.createDocumentFragment();
for (var i = 0; i < 100; i++) {
    var newElement = document.createElement('div');
    newElement.textContent = 'Item ' + (i + 1);
    fragment.appendChild(newElement); // 가상의 DOM에 요소를 추가합니다.
}
$('#myContainer').append(fragment); // 실제 DOM에는 한 번만 추가합니다.
  • CSS 클래스를 활용한 효율적인 스타일 변경:
// CSS 클래스를 사용하여 여러 스타일 변경을 한 번에 적용합니다.
$('#myElement').removeClass('old-styles').addClass('new-styles');

1.5 필요한 경우만 재렌더링: 불필요한 리플로우 방지로 성능 최적화

CSS 스타일이나 속성 변경은 브라우저의 레이아웃 재계산(리플로우)을 유발합니다. 꼭 필요한 부분만 수정하여 불필요한 재렌더링을 최소화하는 것이 중요합니다.

  • 리플로우 최소화 예제:
// 불필요한 리플로우가 발생하는 비효율적인 예시
$('#myElement').css('width', '100px'); // 리플로우 발생
$('#myElement').css('height', '200px'); // 또 다시 리플로우 발생

// 리플로우를 최소화하는 효율적인 예시: 한 번에 여러 스타일을 적용하여 리플로우를 한 번만 발생시킵니다.
$('#myElement').css({
    'width': '100px',
    'height': '200px'
});

// requestAnimationFrame을 사용하여 변경 사항을 다음 프레임으로 연기하여 리플로우를 최소화할 수 있습니다.
requestAnimationFrame(function() {
    $('#myElement').css('width', '100px');
    $('#myElement').css('height', '200px');
});
  • 스타일 변경 후 위치 정보 가져오기 예제:
// 요소의 위치를 가져오기 전에 스타일 변경을 완료하여 불필요한 리플로우를 방지합니다.
$('#myElement').css('left', '50px');
var leftPos = $('#myElement').position().left; // 스타일 변경 이후 위치를 가져옵니다.
  • display: none을 활용한 리플로우 최소화 예제:
// display: none 으로 요소를 숨긴 상태에서 조작하면 리플로우가 발생하지 않습니다.
$('#hiddenElement').hide();
// ... 요소 조작 ...
$('#hiddenElement').show();

2. jQuery와 다른 라이브러리의 통합: 강력하고 유연한 웹 애플리케이션 개발

현대 웹 애플리케이션은 다양한 기능을 구현하기 위해 여러 JavaScript 라이브러리를 함께 사용하는 경우가 많습니다. jQuery와 다른 라이브러리를 효과적으로 통합하면, 각 라이브러리의 장점을 활용하여 더욱 강력하고 효율적인 웹 애플리케이션을 구축할 수 있습니다.

2.1 통합의 필요성: 시너지 효과 창출

  • 기능 확장: 특정 작업에 최적화된 라이브러리를 활용하여 애플리케이션의 기능을 확장할 수 있습니다. 예를 들어, 데이터 시각화를 위해 D3.js를, 복잡한 UI 컴포넌트 관리를 위해 React나 Vue.js를 사용할 수 있습니다.
  • 코드 재사용: 이미 존재하는 코드나 검증된 플러그인을 활용하여 개발 시간을 단축하고 효율성을 높일 수 있습니다.
  • 유지보수 용이성: 각 라이브러리가 특정 역할을 담당하도록 분리하여 코드를 구조화하고 유지보수를 쉽게 할 수 있습니다.

2.2 주요 라이브러리 소개: 특징 및 장점

  • React: 사용자 인터페이스를 구축하기 위한 컴포넌트 기반의 JavaScript 라이브러리입니다. 가상 DOM을 사용하여 효율적인 렌더링을 제공하며, 컴포넌트 기반 아키텍처로 재사용성과 유지보수성이 뛰어납니다.
  • Vue.js: 사용자 인터페이스를 구축하기 위한 점진적 프레임워크입니다. 데이터 바인딩과 컴포넌트 시스템을 제공하며, 배우기 쉽고 유연하여 소규모 프로젝트부터 대규모 애플리케이션까지 적용 가능합니다.
  • D3.js: 데이터를 기반으로 문서를 조작하는 데이터 시각화 라이브러리입니다. SVG, Canvas, HTML을 사용하여 데이터를 시각적으로 표현하며, 강력한 데이터 바인딩과 유연한 API를 제공합니다.

2.3 jQuery와 React 통합: 실전 예제

React는 상태 관리와 UI 렌더링에 중점을 두지만, 기존의 jQuery 플러그인을 활용해야 할 경우가 있습니다. useEffect 훅을 사용하여 React 컴포넌트 내에서 jQuery 코드를 실행할 수 있습니다.

  • 기본적인 jQuery 사용 예제:
import React, { useEffect } from 'react';
import $ from 'jquery'; // jQuery를 임포트합니다.

const MyComponent = () => {
    useEffect(() => {
        // 컴포넌트가 마운트된 후 실행됩니다.
        $('#myElement').fadeIn(); // jQuery를 사용하여 #myElement를 페이드 인 효과로 나타냅니다.

        // 클린업 함수 (컴포넌트가 언마운트될 때 실행됩니다.)
        return () => {
          // 예: $('#myElement').off('click'); // 이벤트 핸들러 제거
        };
    }, []); // 빈 배열을 의존성 배열로 전달하면, 이 훅은 컴포넌트가 마운트될 때 한 번만 실행됩니다.

    return <div id="myElement" style={{ display: 'none' }}>Hello from React with jQuery!</div>;
};

export default MyComponent;
  • jQuery UI Datepicker 사용 예제:
// React 컴포넌트 내에서 jQuery UI datepicker 사용
import React, { useRef, useEffect } from 'react';
import $ from 'jquery';
import 'jquery-ui/ui/widgets/datepicker'; // jQuery UI datepicker 위젯 임포트
import 'jquery-ui/themes/base/all.css'; // jQuery UI 테마 CSS 임포트

const DatePickerComponent = () => {
    const datepickerRef = useRef(null); // input 요소에 대한 참조를 생성합니다.

    useEffect(() => {
        // 컴포넌트가 마운트된 후 jQuery UI datepicker를 초기화합니다.
        $(datepickerRef.current).datepicker();
    }, []);

    return <input type="text" ref={datepickerRef} />; // ref를 통해 input 요소에 접근합니다.
};

export default DatePickerComponent;
  • jQuery 플러그인 사용 예제:
// jQuery 플러그인을 사용하는 React 컴포넌트
import React, { useRef, useEffect } from 'react';
import $ from 'jquery';
import 'some-jquery-plugin'; // jQuery 플러그인을 임포트합니다.

const MyPluginComponent = () => {
    const elementRef = useRef(null); // 요소에 대한 참조를 생성합니다.

    useEffect(() => {
        // 컴포넌트가 마운트된 후 jQuery 플러그인을 적용합니다.
        $(elementRef.current).somePlugin({ /* options */ });
    }, []);

    return <div ref={elementRef}></div>; // ref를 통해 요소에 접근합니다.
};

export default MyPluginComponent;

2.4 jQuery와 Vue.js 통합: 실전 예제

Vue.js는 데이터 바인딩과 DOM 업데이트를 자동으로 처리하지만, 직접적인 DOM 조작이 필요한 경우 jQuery를 사용할 수 있습니다.

  • 기본적인 jQuery 사용 예제:
<template>
    <div id="app">
        <button @click="showMessage">Show Message</button>
        <div id="message" style="display:none;">Hello from Vue with jQuery!</div>
    </div>
</template>

<script>
import $ from 'jquery'; // jQuery를 임포트합니다.

export default {
    methods: {
        showMessage() {
            $('#message').slideDown(); // jQuery를 사용하여 #message를 슬라이드 다운 효과로 나타냅니다.
        }
    }
};
</script>
  • ref를 사용한 jQuery 접근 예제:
<template>
    <div id="app">
        <input type="text" ref="myInput" />
    </div>
</template>

<script>
import $ from 'jquery';

export default {
    mounted() {
        $(this.$refs.myInput).focus(); // Vue 인스턴스의 mounted 훅에서 jQuery를 사용하여 input 요소에 포커스를 줍니다.
    }
};
</script>
  • jQuery 애니메이션 사용 예제:
<template>
  <div id="app">
    <button @click="animate">Animate</button>
    <div ref="myElement" style="width: 100px; height: 100px; background-color: red;"></div>
  </div>
</template>

<script>
import $ from 'jquery';

export default {
  methods: {
    animate() {
      $(this.$refs.myElement).animate({ // Vue 인스턴스 내에서 jQuery animate를 사용하여 애니메이션 효과를 적용합니다.
        width: '200px',
        height: '200px'
      }, 1000);
    }
  }
};
</script>

2.5 성능 고려사항: 통합 시 주의할 점

jQuery와 다른 라이브러리를 함께 사용할 때는 성능 저하가 발생하지 않도록 주의해야 합니다.

  • 불필요한 DOM 접근 최소화: 캐싱 기법을 활용하여 DOM 접근을 최소화합니다.
  • 작업 묶기: .css() 메서드 체이닝과 같이 가능한 한 많은 작업을 하나의 함수 호출로 묶어서 처리합니다.
  • 이벤트 위임: 이벤트 위임을 사용하여 이벤트 핸들러의 개수를 줄이고 성능을 향상시킵니다.
  • 라이브러리 간 충돌 주의: 각 라이브러리가 DOM을 조작하는 방식이 다를 수 있으므로, 충돌이 발생하지 않도록 주의해야 합니다. 예를 들어, React의 가상 DOM과 jQuery의 직접적인 DOM 조작이 충돌할 수 있습니다.
    • React에서 jQuery 사용 시 주의사항: React에서 jQuery로 DOM을 조작할 때는 ref를 사용하여 직접 DOM 노드를 참조하고, React의 라이프사이클 메서드 내에서 조작하는 것이 좋습니다. 이를 통해 React의 가상 DOM과의 충돌을 방지할 수 있습니다.
    • Vue에서 jQuery 사용 시 주의사항: Vue에서 jQuery를 사용할 때는 가급적 Vue의 디렉티브와 메서드를 활용하고, 꼭 필요한 경우에만 jQuery를 사용하는 것이 좋습니다. Vue의 반응형 시스템과의 충돌을 피하기 위해 DOM 조작을 최소화해야 합니다.

3. jQuery UI: 풍부하고 인터랙티브한 사용자 인터페이스 구축

jQuery UI는 jQuery를 기반으로 구축된 UI 라이브러리로, 다양한 위젯, 효과, 테마를 제공하여 웹 애플리케이션의 사용자 인터페이스를 풍부하고 인터랙티브하게 만들어줍니다.

3.1 jQuery UI 소개: 구성 요소 및 특징

  • 위젯 (Widgets): 버튼, 대화상자, 탭, 아코디언, 프로그레스바 등과 같이 사전에 정의된 UI 구성 요소들을 제공하여, 일관성 있고 효율적인 UI 개발을 가능하게 합니다.
  • 효과 (Effects): fadeIn, fadeOut, slideUp, slideDown 등과 같은 애니메이션 효과를 쉽게 추가할 수 있는 다양한 메서드를 제공하여, 사용자 경험을 향상시킵니다.
  • 테마 (Themes): CSS를 통해 손쉽게 스타일링 할 수 있는 테마 시스템을 제공합니다. ThemeRoller를 사용하여 사용자 정의 테마를 만들 수도 있어, 애플리케이션의 디자인을 쉽게 변경하고 통일성을 유지할 수 있습니다.

3.2 기본 설치 및 설정: 시작하기

jQuery UI를 사용하려면, jQuery와 jQuery UI 라이브러리를 HTML 문서에 포함해야 합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>jQuery UI 예제</title>
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>

<!-- 여기에 내용을 추가합니다 -->

<script>
// 여기에 JavaScript 코드를 추가합니다.
</script>

</body>
</html>

3.3 주요 위젯 사용법: 실전 예제

a) 버튼 (Button): 다양한 스타일과 기능의 버튼 생성

jQuery UI의 button() 메서드를 사용하면 기본 HTML 버튼을 스타일링하여 더 매력적이고 다양한 기능을 가진 버튼으로 만들 수 있습니다.

<button id="myButton">Click Me!</button>
<input type="submit" value="Submit Button" id="submitButton">
<a href="#" id="anchorButton">Anchor Button</a>

<script>
$(function() {
    $("#myButton").button(); // #myButton을 jQuery UI 버튼으로 변환합니다.
    $("#submitButton").button(); // submit 타입의 input 버튼도 jQuery UI 버튼으로 변환합니다.
    $("#anchorButton").button(); // 앵커 태그도 jQuery UI 버튼으로 변환합니다.
});
</script>
  • 라디오 버튼 그룹 예제:
<div id="radio">
    <input type="radio" id="radio1" name="radio"><label for="radio1">Choice 1</label>
    <input type="radio" id="radio2" name="radio" checked="checked"><label for="radio2">Choice 2</label>
    <input type="radio" id="radio3" name="radio"><label for="radio3">Choice 3</label>
</div>

<script>
$(function() {
    $("#radio").buttonset(); // 라디오 버튼 그룹을 jQuery UI 버튼셋으로 변환합니다.
});
</script>
  • 아이콘이 포함된 버튼 예제:
<button id="iconButton" aria-label="Search"><span class="ui-icon ui-icon-search"></span>Search</button>

<script>
$(function() {
    $("#iconButton").button({
      icon: "ui-icon-gear", // 버튼에 톱니바퀴 아이콘을 추가합니다.
      showLabel: false // 레이블을 숨깁니다.
    });
});
</script>

b) 대화상자 (Dialog): 사용자 인터랙션을 위한 모달 창

dialog() 메서드를 사용하면 사용자에게 정보를 전달하거나 입력을 받는 모달 대화상자를 만들 수 있습니다.

<div id="dialog" title="Dialog Title">
    <p>This is a dialog box.</p>
</div>

<button id="openDialog">Open Dialog</button>

<script>
$(function() {
    $("#dialog").dialog({
        autoOpen: false, // 페이지 로드 시 자동으로 열리지 않도록 설정합니다.
        modal: true, // 모달 대화상자로 설정합니다. (대화상자 뒤의 배경을 클릭할 수 없게 합니다.)
        buttons: {
            "OK": function() {
                $(this).dialog("close"); // "OK" 버튼을 클릭하면 대화상자를 닫습니다.
            },
            "Cancel": function() {
                $(this).dialog("close"); // "Cancel" 버튼을 클릭하면 대화상자를 닫습니다.
            }
        }
    });

    $("#openDialog").button().on("click", function() {
        $("#dialog").dialog("open"); // #openDialog 버튼을 클릭하면 대화상자를 엽니다.
    });
});
</script>
  • 크기 조절 가능한 대화상자 예제:
<div id="resizableDialog" title="Resizable Dialog">
  <p>This dialog is resizable.</p>
</div>

<script>
$(function() {
    $("#resizableDialog").dialog({
        resizable: true // 대화상자의 크기를 조절할 수 있도록 설정합니다.
    });
});
</script>
  • 폼이 포함된 모달 대화상자 예제:
<div id="modalForm" title="Create new user">
  <form>
    <fieldset>
      <label for="name">Name</label>
      <input type="text" name="name" id="name" value="John Doe" class="text ui-widget-content ui-corner-all">
      <label for="email">Email</label>
      <input type="text" name="email" id="email" value="john.doe@example.com" class="text ui-widget-content ui-corner-all">
      <label for="password">Password</label>
      <input type="password" name="password" id="password" value="************" class="text ui-widget-content ui-corner-all">

      <!-- Allow form submission with keyboard without duplicating the dialog button -->
      <input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
    </fieldset>
  </form>
</div>

<button id="createUser">Create new user</button>

<script>
$(function() {
    $("#modalForm").dialog({
        autoOpen: false,
        modal: true,
        buttons: {
            "Create": function() {
                // 폼 데이터 처리 로직을 여기에 추가합니다.
                $(this).dialog("close");
            },
            Cancel: function() {
                $(this).dialog("close");
            }
        }
    });

    $("#createUser").button().on("click", function() {
        $("#modalForm").dialog("open");
    });
});
</script>

c) 드래그 앤 드롭 (Draggable & Droppable): 직관적인 요소 이동 기능

draggable()droppable() 메서드를 사용하면 요소를 드래그하여 다른 요소 위에 놓을 수 있는 직관적인 드래그 앤 드롭 기능을 구현할 수 있습니다.

<div id="draggable" style="width: 100px; height: 100px; background-color: red; cursor: move;"></div>

<div id="droppable" style="width: 200px; height: 200px; background-color: #ccc; border: 1px solid black;">
    Drop here!
</div>

<script>
$(function() {
    $("#draggable").draggable(); // #draggable 요소를 드래그 가능하게 만듭니다.

    $("#droppable").droppable({
        drop: function(event, ui) {
            // #draggable 요소가 #droppable 요소 위에 놓였을 때 실행됩니다.
            $(this)
                .addClass("ui-state-highlight") // #droppable 요소에 하이라이트 효과를 추가합니다.
                .find("p")
                .html("Dropped!"); // #droppable 요소 안의 텍스트를 변경합니다.
        }
    });
});
</script>
  • 드롭 유효성 검사 예제:
<div id="draggable2" style="width: 100px; height: 100px; background-color: blue; cursor: move;"></div>

<script>
$(function() {
    $("#draggable2").draggable({ revert: "invalid" }); // 드롭되지 않으면 원래 위치로 돌아갑니다.
    $("#droppable").droppable({
        accept: "#draggable2" // #draggable2 요소만 허용합니다.
    });
});
</script>
  • 이미지 갤러리와 휴지통 예제:
<style>
  #gallery { float: left; width: 65%; min-height: 12em; }
  .gallery.custom-state-active { background: #eee; }
  .gallery li { float: left; width: 96px; padding: 0.4em; margin: 0 0.4em 0.4em 0; text-align: center; }
  .gallery li h5 { margin: 0 0 0.4em; cursor: move; }
  .gallery li a { float: right; }
  .gallery li a.ui-icon-zoomin { float: left; }
  .gallery li img { width: 100%; cursor: move; }

  #trash { float: right; width: 32%; min-height: 18em; padding: 1%; }
  #trash h4 { line-height: 16px; margin: 0 0 0.4em; }
  #trash h4 .ui-icon { float: left; }
  #trash .gallery h5 { display: none; }
</style>

<div id="gallery" class="gallery ui-helper-reset ui-helper-clearfix">
  <h5>Gallery</h5>
  <ul>
    <li class="ui-widget-content ui-corner-tr">
      <h5 class="ui-widget-header">Image 1</h5>
      <img src="https://via.placeholder.com/96x72" alt="Image 1" width="96" height="72">
      <a href="https://via.placeholder.com/500x300" title="View larger image" class="ui-icon ui-icon-zoomin">View larger</a>
      <a href="#" title="Delete this image" class="ui-icon ui-icon-trash">Delete image</a>
    </li>
    <li class="ui-widget-content ui-corner-tr">
      <h5 class="ui-widget-header">Image 2</h5>
      <img src="https://via.placeholder.com/96x72" alt="Image 2" width="96" height="72">
      <a href="https://via.placeholder.com/500x300" title="View larger image" class="ui-icon ui-icon-zoomin">View larger</a>
      <a href="#" title="Delete this image" class="ui-icon ui-icon-trash">Delete image</a>
    </li>
  </ul>
</div>

<div id="trash" class="ui-widget-content ui-state-default">
  <h4><span class="ui-icon ui-icon-trash"></span>Trash</h4>
</div>

<script>
$(function() {
    // 이미지 갤러리에서 휴지통으로 드래그 앤 드롭
    $("#gallery li").draggable({
        cancel: "a.ui-icon", // 아이콘 클릭은 드래그를 취소합니다.
        revert: "invalid", // 유효하지 않은 곳에 놓이면 원래 위치로 돌아갑니다.
        containment: "document",
        helper: "clone",
        cursor: "move"
    });

    // 휴지통에 이미지를 놓을 수 있도록 설정
    $("#trash").droppable({
        accept: "#gallery > li",
        classes: {
            "ui-droppable-active": "ui-state-highlight"
        },
        drop: function(event, ui) {
            deleteImage(ui.draggable);
        }
    });

    // 이미지를 삭제하는 함수
    function deleteImage($item) {
        $item.fadeOut(function() {
            var $list = $("ul", $("#trash")).length ?
                $("ul", $("#trash")) :
                $("<ul class='gallery ui-helper-reset'/>").appendTo($("#trash"));

            $item.find("a.ui-icon-trash").remove();
            $item.append("<a href='#' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>");
            $item.appendTo($list).fadeIn(function() {
                $item
                    .animate({ width: "48px" })
                    .find("img")
                    .animate({ height: "36px" });
            });
        });
    }

    // 휴지통에서 갤러리로 이미지 복원
    $("#trash").on("click", "a.ui-icon-refresh", function(event) {
        recycleImage($(this).closest("li"));
        event.preventDefault();
    });

    function recycleImage($item) {
        $item.fadeOut(function() {
            $item
                .css("width", "96px")
                .find("img")
                .css("height", "72px")
                .end()
                .find("a.ui-icon-refresh")
                .remove()
                .end()
                .find("a.ui-icon-zoomin")
                .end()
                .appendTo("#gallery ul")
                .fadeIn();
        });
    }

    // 이미지 크게 보기
    $("#gallery").on("click", "a.ui-icon-zoomin", function(event) {
        viewLargerImage($(this).closest("li"));
        event.preventDefault();
    });

    function viewLargerImage($link) {
        var src = $link.attr("href"),
            title = $link.siblings("img").attr("alt"),
            $modal = $("<div>");

        $modal.append($("<img>", {
            src: src,
            alt: title,
            css: {
                width: "100%"
            }
        }));

        $modal.dialog({
            title: title,
            width: 540,
            modal: true
        });
    }
});
</script>

3.4 커스터마이징 및 테마 적용하기: 일관된 디자인 구현

jQuery UI는 CSS를 사용하여 스타일을 변경할 수 있으며, 다양한 테마를 제공합니다. jQuery UI ThemeRoller에서 원하는 테마를 선택하고 다운로드하여 적용할 수 있습니다.

  • ThemeRoller 활용 예제: ThemeRoller에서 "Start designing"을 클릭하고 "Roll Your Own" 탭에서 직접 색상, 폰트, 아이콘 등을 변경하여 자신만의 테마를 만들 수 있습니다.
  • 개별 위젯 스타일 수정 예제: 다운로드한 테마의 CSS 파일에서 특정 위젯의 스타일만 수정하고 싶다면, 해당 위젯의 클래스 이름을 찾아서 스타일을 변경하면 됩니다. 예를 들어, 버튼의 배경색을 바꾸고 싶다면 .ui-button 클래스의 background 속성을 수정하면 됩니다.
728x90