이 글은 Patterns.dev를 참고하여 작성한 시리즈 입니다.
Singleton Pattern
애플리케이션 전체에서 단일 인스턴스 공유
싱글턴 패턴은 한 번의 인스턴스화가 가능한 클래스로 글로벌하게 엑세스할 수 있습니다. 이 단일 클래스는 애플리케이션 전체에 공유할 수 있기 때문에 애플리케이션의 글로벌 상태를 관리하는 데 적합합니다.
먼저 Counter 클래스를 작성해보겠습니다. Counter 클래스는 다음과 같은 메소드를 제공합니다.
- getInstance: 인스턴스를 반환합니다.
- getCount: 현재 counter 값을 반환합니다.
- increment: 카운터를 1 증가시킵니다.
- decrement: 카운터를 1 감소시킵니다.
위 클래스는 싱글턴의 기준을 충족시키지 못합니다. 싱글턴은 한 번만 인스턴스화 할 수 있습니다. 위 클래스는 복수의 인스턴스를 생성할 수 있습니다.
인스턴스를 한 개만 생성할 수 있는 한 가지 방법은 instance를 담을 변수를 만드는 것입니다.
새로운 인스턴스를 생성할 때, instance를 담는 변수에 이미 값이 있다면(인스턴스를 이미 생성했다면) 사용자에게 알리기 위해 에러를 발생시킵니다.
이제 더 이상 여러 인스턴스를 만들 수 없습니다.
외부에서 Counter를 사용할 수 있도록 Object.freeze를 한 후 내보냅니다.
Object.freeze는 객체 속성의 불변성을 보장합니다. 이렇게 해서 Counter의 속성을 추가하거나 수정할 수 없으므로 싱글턴 클래스를 실수로 변경할 위험을 줄입니다.
Counter Singleton 완성
적용하기
다음과 같이 redButton.js, blueButton.js 파일을 만들어 확인해 볼 수 있습니다.
각각의 버튼 파일이 Counter를 증가시키고 증가된 counter 상태값이 공유되기 때문에 index.js에 결과가 2가 나오는 것을 확인할 수 있습니다.
장단점
인스턴스화를 한 번만으로 제한하면 메모리 공간을 절약할 수 있습니다. 애플리케이션 전체에서 참조되는 한 개의 인스턴스에 대해서만 메모리를 설정하면 됩니다.
싱글턴 인스턴스는 애플리케이션 전체에서 참조할 수 있어야합니다. 글로벌 변수(window, global)도 동일한 동작을 나타냅니다. 하지만 전역변수를 갖는 것은 일반적으로 잘못된 설계로 간주됩니다. 글로벌 범위 오염은 실수로 글로벌 변수 값을 덮어쓰게 되어 예상치 못한 많은 동작을 일으킬 수 있습니다.
일반적으로 코드 베이스의 특정부분은 글로벌 상태 값을 변경하는 반면 다른 부분은 해당 데이터를 소비(사용)합니다. 여기서 중요한 것은 실행순서 입니다. 사용할 데이터가 없을 때 실수로 먼저 데이터를 소비하고 싶지 않다는 것입니다. 글로벌 상태를 사용할 때 데이터의 흐름을 이해하는 것은 애플리케이션의 크기가 증가함에 따라 매우 까다로워 질 수 있으며, 수십개의 컴포넌트가 서로 의존합니다.
React에서의 상태관리
React에서는 싱글턴을 사용하는 대신 Redux나 React Context 같은 상태 관리 도구를 통해 글로벌 상태에 의존하는 경우가 많습니다. 이러한 글로벌 상태의 동작은 싱글턴의 동작과 비슷해 보이지만 이러한 툴은 싱글턴의 가변(변경가능)상태가 아닌 읽기 전용(readonly) 상태를 제공합니다. Redux를 사용하는 경우 컴포넌트가 dispatcher를 통해 action을 전송한 후 순수함수 reducer만 상태를 업데이트 할 수 있습니다.
이러한 툴을 사용하여 글로벌 상태를 유지하는 것의 단점이 마법처럼 사라지지 않지만 컴포넌트가 직접적으로 상태를 갱신할 수 없기 때문에 적어도 글로벌 상태가 의도한 대로 변경 되도록 할 수 있습니다.
Reference
'Web > Patterns' 카테고리의 다른 글
Observer Pattern (1) | 2022.06.21 |
---|---|
Proxy Pattern (JavaScript) (0) | 2022.06.07 |