JavaScript에서 싱글톤을 구현하는 방법

6720 단어
이 기사에서는 Singleton이 무엇이며 JavaScript에서 이를 구현하는 모든 방법을 살펴봅니다.

Singleton은 두 가지 문제를 해결하는 디자인 패턴입니다. 단일 스레드 응용 프로그램이 주어진 클래스의 인스턴스를 하나만 갖도록 합니다. 두 번째 문제는 일부 클래스 인스턴스 또는 객체에 대한 전역 액세스 포인트가 필요할 때입니다. 때때로 개발자는 한 가지 문제만 해결하더라도 일부 개체를 싱글톤으로 호출합니다.

다음은 싱글톤을 사용할 수 있는 몇 가지 경우입니다.
  • true의 단일 소스로서의 전역 앱 상태 - Redux, Mobx 상태 관리자는 상태에 대한 전역 액세스를 제공합니다
  • 일부 논리를 캡슐화하고 API 호출을 수행하기 위해 세션 또는 토큰을 저장하는 API 서비스입니다.
  • 데이터베이스 또는 WebSocket 연결을 유지하기 위한 서비스이며 여기서는 주어진 싱글톤의 연결이 하나만 있는지 확인할 수 있습니다
  • .

    따라서 다음 패턴을 구현하는 방법을 살펴보겠습니다.

    JavaScript 내보내기/가져오기 모듈



    Singleton 클래스 자체는 JavaScript 엔터티나 기능이 아닙니다. 어떤 방식으로든 구현하는 접근 방식이나 패턴입니다. 모든 것은 프로젝트, 우리가 사용하는 기술 스택, 심지어 개발자의 기술에 따라 달라질 수 있습니다.

    일반적으로 특정 클래스를 중복 방지 없이 단일 인스턴스로 사용하는 경우에 동의할 수 있습니다. 특히 혼자 또는 소규모 팀과 함께 작업할 때 잘 작동할 수 있습니다. 그러나 더 큰 팀과 프로젝트에서는 이에 대해 알고 클래스의 인스턴스를 두 개 이상 가질 가능성 없이 싱글톤을 만들어야 합니다.

    JavaScript에서 싱글톤을 구현하는 가장 원시적이고 간단한 접근 방식은 export/import 구문을 사용하여 모듈에서 인스턴스를 내보내는 것입니다.

    
    class ApiService {}
    
    export const API = new ApiService();
    
    // and then somewhere in other files:
    
    import {API} from './api';
    


    파일에는 바로 사용할 수 있는 개체로 내보낼 수 있는 변수, 논리 및 메서드가 포함될 수 있습니다. 그러한 객체가 필요할 때 간단히 가져와서 사용합니다. 이 방법은 잘 작동하지만 대규모 프로젝트에서는 테스트를 위해 가짜 서비스 인스턴스를 관리하기 어렵거나 누군가 원시 클래스 ApiService를 가져와서 두 번째 인스턴스를 만들 수 있습니다.

    원시적인 특성에도 불구하고 이 접근 방식은 대부분의 프로젝트에서 여전히 사용됩니다.

    클래스 기반 싱글톤



    여기서는 새 인스턴스를 생성하는 대신 항상 동일한 인스턴스를 반환하는 싱글톤 클래스를 구현합니다. 설계상 생성자 호출은 항상 새 개체를 반환할 것으로 예상되기 때문에 이 동작은 일반 생성자로 구현할 수 없습니다.

    그러나 생성자에서 무언가를 반환하면 어떻게 될까요? 한 번 보자:

    class Store {
      someValue = 'foo'
    
      constructor() {
        return {
          anotherValue: 'bar'
        }
      }
    }
    
    const store = new Store()
    console.log(store.someValue) // undefined
    console.log(store.anotherValue) // bar
    


    생성자에서 객체를 반환하면 해당 객체가 클래스의 인스턴스로 반환되는 것을 볼 수 있습니다.

    이 트릭을 사용하여 클래스 필드에 인스턴스를 정의 및 저장하고 해당 값이 이미 존재하는 경우 반환할 수 있습니다.

    class WebSocketService {
      constructor() {
        if (WebSocketService._instance) {
          return WebSocketService._instance;
        }
    
        WebSocketService._instance = this;
      }
    }
    
    const socket1 = new WebSocketService();
    const socket2 = new WebSocketService();
    
    console.log(socket1 === socket2); // true
    


    함수 클로저에 인스턴스가 있는 클래스 기반 싱글톤


    _instance 필드는 계속 사용할 수 있고 수동으로 재정의할 수 있기 때문에 이전 예는 가장 정확하고 깨끗하지 않습니다.

    싱글톤을 구현하는 가장 효율적인 방법을 살펴보겠습니다. 접근 방식은 클래스를 반환할 래퍼 함수를 ​​만들고 이 함수를 닫을 때 인스턴스 필드를 만드는 것입니다.

    const GlobalStore = (() => {
      let instance = null;
    
      return class GlobalStore {
        constructor() {
          if(instance === null) {
            instance = this;
          }
          return instance;
        }
      }
    })();
    


    이 예제에서는 함수 클로저에 인스턴스를 넣습니다. 그런 다음 클래스 생성자에서 클래스의 인스턴스가 있는지 확인하고 없으면 인스턴스에 값을 할당하고 반환합니다.

    또한 래퍼 함수가 생성되고 즉시 호출되는 것을 볼 수 있으므로 외부에서 접근할 수 없는 클로저를 생성했으며 클래스는 클로저에서 값을 쉽게 읽고 재정의할 수 있습니다.

    이 접근 방식의 보너스로 클로저에 변수나 논리를 추가할 수 있으므로 인스턴스에서 액세스할 수 없는 실제 프라이빗 메서드를 얻을 수 있습니다.

    좋은 웹페이지 즐겨찾기