Javascript jQuery

하나의 웹페이지에서 여러 jQuery 버전을 동시에 사용하기

하나의 웹 페이지에서 여러 jQuery 버전을 사용해야 하는 일은 매우 드뭅니다. 그러나 레거시 코드와 신규 작성된 코드가 혼재된 경우, 서로 다른 버전의 jQuery를 기반으로 하는 컴포넌트를 활용하는 경우에는 이러한 일이 발생하기도 합니다. 이 까다로운 요구사항을 만족하기 위해서는 2가지 문제를 해결해야 합니다.

 

문제와 해결책

첫 번째 문제는 변수 덮어쓰기입니다. jQuery는 임베드하는 순간, 전역변수 $에 함수를 할당합니다. 따라서 두 번째 jQuery 버전을 임베드하면, 첫 번째로 임베드했던 jQuery의 $ 변수를 덮어쓰게 될 것입니다.

이 문제는 손쉬운 해결책이 있습니다. 바로 jQuery가 제공하는 noConflict()라는 함수입니다. 이 함수는 jQuery가 전역변수 $에 대한 제어권을 포기하고 할당을 해제하게 합니다. 따라서 한 버전의 jQuery를 이용하여 소스코드를 실행한 후, 다음 버전의 jQuery를 임베드하기 전에 noConflict() 함수를 실행하면, 또다른 버전의 jQuery로 전역변수 $가 할당되어 다음 소스코드를 실행할 수 있습니다.

두 번째 문제는 비동기 임베드입니다. jQuery를 임베드하면 이는 비동기적으로 실행되기 때문에, 해당 파일의 로딩이 끝나는 시점을 제어할 수 없습니다. 한 버전의 jQuery가 임베드 되어서 소스코드를 실행하고 있는데, 두 번째 버전의 jQuery의 임베드가 완료되면, noConflict() 함수가 사용되기도 전에 jQuery의 버전이 바뀔 수 있습니다. 따라서 비동기적으로 임베드 되는 jQuery를 순차적으로 임베드할 수 있는 방안이 필요합니다.

이를 위해서는 async와 await를 이용할 수 있습니다. aync 속성의 함수에서 await 지시자를 사용하면, 비동기 처리가 끝날 때까지 다음 행의 소스코드를 실행하지 않고 기다리게 합니다.

 

간단한 순차처리 구현

위 해결책들을 이용하여, 여러 jQuery 버전을 이용하도록 구현한 가장 간소한 형태의 소스코드는 아래와 같습니다.

(async () => {
    await import('//code.jquery.com/jquery-3.6.0.min.js?1');            
    $('#dv1').text('First');
    $.noConflict();

    await import('//code.jquery.com/jquery-1.12.4.min.js?2');
    $('#dv2').text('Second');
    $.noConflict();

    await import('//code.jquery.com/jquery-2.2.4.min.js?3');
    $('#dv3').text('Third');
    $.noConflict();

    await import('//code.jquery.com/jquery-3.6.0.min.js?4');
    $('#dv4').text('Fourth');
    $.noConflict();
})();

이 코드는 매 블럭마다 3가지 과정을 수행합니다.

  1. import()로 jQuery를 임베드하고, await 지시자를 이용하여 해당 파일의 로딩이 끝날 때까지 기다립니다.
  2. jQuery를 사용하는 소스코드를 실행합니다.
  3. noConflict()로 Global Scope에 할당된 변수 $를 할당해제합니다.

이와 같이 구현하면 소스코드 실행을 위해 사용한 특정 버전의 jQuery 전역변수 $를, 다음 소스코드를 실행하기 전에 할당해제할 수 있습니다. 그러나 import() 할 때마다 jQuery 파일이 로딩되기 때문에, 동일한 버전의 jQuery를 사용하는 소스코드도 각각 jQuery를 임베드하는 점은 개선할 필요가 있습니다.

 

Javascript Class로의 구현

아래는 임베드의 중복을 막고자, Javascript Class로 이를 구현한 것입니다. 각 버전의 jQuery를 사용하는 소스코드를 콜백함수로 받아 배열에 담아 놓았다가, execute() 메서드를 실행하면 1번만 해당 버전의 jQuery를 임베드하고 담아놓은 콜백 함수를 하나씩 실행하는 과정으로 이루어집니다.

class jQueryExecutor {
    static callbacks = {1:[], 2:[], 3:[]};
    
    static add(jQueryVersion, callback) {
        this.callbacks[jQueryVersion].push(callback);
    }
    
    static async executeVersion(key, version) {
        if (this.callbacks[key].length > 0) {
            await import('//code.jquery.com/jquery-' + version + '.min.js');
            
            for(let fn of this.callbacks[key]) {
                fn();
            }
            
            $.noConflict();
        }
    }
    
    static async execute() {
        await this.executeVersion(1, '1.12.4');
        await this.executeVersion(2, '2.2.4');
        await this.executeVersion(3, '3.6.0');
    }
}
jQueryExecutor.add(3, () => {
    $('#dv1').text('First');
});

jQueryExecutor.add(1, () => {
    $('#dv2').text('Second');
});

jQueryExecutor.add(2, () => {
    $('#dv3').text('Third');
});

jQueryExecutor.add(3, () => {
    $('#dv4').text('Fourth');
});

jQueryExecutor.execute();

Leave a Reply

Your email address will not be published. Required fields are marked *