현재 업무는 함수형 프로그래밍을 지향하다 보니 함수들만 주야장천 찍어냈습니다. 그러던 중 오랜만에 필요에 의해 클래스를 작성하게 되었고 싱글톤 패턴을 적용을 해보는 기회가 되었습니다. 이론으로만 보던 싱글톤 패턴을 보니 반갑기도 하고 해서 간단히 서칭 한 내용을 정리해보려고 합니다.
싱글톤 패턴 singleton pattern이란?
애플리케이션에서 하나의 인스턴스만을 생성하고, 이를 전역적으로 사용하는 디자인 패턴
싱글톤 패턴은 객체지향 디자인 패턴 중 하나로, 어떤 클래스의 인스턴스가 오직 하나만 만들어져야 하는 상황에서 사용됩니다. 이 패턴을 사용하면 인스턴스를 여러 개 만들어서 발생할 수 있는 문제를 방지할 수 있습니다.
인스턴스를 여러 개 만들면 발생할 수 있는 문제
인스턴스를 여러 개 만들어서 발생할 수 있는 문제에는 크게 두 가지가 있습니다.
- 자원의 낭비
- 객체를 생성할 때, 메모리와 같은 자원을 사용하게 됩니다. 객체가 중복 생성되면 이러한 자원들이 불필요하게 소모되어 시스템의 성능 저하나 다운으로 이어질 수 있습니다.
- 어려운 객체의 일관성(consistency) 보장
- 예를 들어, 하나의 인스턴스에서 변경된 상태가 다른 인스턴스에 반영되지 않는다면, 여러 인스턴스가 서로 다른 상태를 가지고 있는 경우가 있습니다. 상황을 예로 들자면, 어떤 애플리케이션이 데이터베이스에 접근해야 하는데, 다수의 인스턴스가 존재하면, 이러한 데이터베이스 접근에 대한 충돌이 발생할 수 있습니다.
하나의 인스턴스에서 변경된 상태가 다른 인스턴스에 반영되지 않으면, 데이터베이스에 대한 일관성이 없어질 수 있습니다. 이러한 일관성이 없으면, 예상하지 못한 결과를 초래할 수 있습니다.
또 다른 예시로는, 하나의 인스턴스에서 변경된 설정이 다른 인스턴스에 반영되지 않는 경우가 있습니다. 예를 들어, 서버 설정이 변경되었을 때, 이를 적용하려면 모든 인스턴스에 대해 일일이 설정을 변경해주어야 합니다. 이 과정에서 실수가 발생하면, 예기치 못한 결과가 발생할 수 있습니다.
- 예를 들어, 하나의 인스턴스에서 변경된 상태가 다른 인스턴스에 반영되지 않는다면, 여러 인스턴스가 서로 다른 상태를 가지고 있는 경우가 있습니다. 상황을 예로 들자면, 어떤 애플리케이션이 데이터베이스에 접근해야 하는데, 다수의 인스턴스가 존재하면, 이러한 데이터베이스 접근에 대한 충돌이 발생할 수 있습니다.
이를 해결하기 위해서는 인스턴스를 하나만 생성하고, 이를 여러 곳에서 참조하여 사용하는 것이 필요합니다.
싱글톤 패턴은 이러한 문제를 해결하기 위해 객체의 인스턴스가 하나만 생성되도록 보장합니다. 이를 통해 자원의 낭비를 방지하고, 객체의 일관성을 보장할 수 있습니다.
전역 변수를 사용하지 않아도 여러 곳에서 쉽게 접근할 수 있는 인스턴스를 만들 수 있습니다.
데이터베이스 연결과 같은 리소스를 공유해야 하는 상황에서 싱글톤 패턴을 사용할 수 있습니다. 이렇게 하면 연결을 매번 새로 만들 필요가 없어지며, 메모리 사용량도 줄일 수 있습니다.
바로 예시 코드를 보면서 정리를 해보도록 하겠습니다. 아래와 같이 TypeScript를 이용해 보편적인 싱글톤 패턴 형태를 작성해 보았습니다.
class Singleton {
private static instance: Singleton;
private constructor() {}
static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
public doSomething(): void {
console.log("Something was done.");
}
}
const singleton = Singleton.getInstance();
singleton.doSomething(); // Something was done.
const anotherSingleton = Singleton.getInstance();
console.log(singleton === anotherSingleton); // true
위 코드에서 Singleton 클래스는 private 생성자를 갖고 있으며, getInstance() 메서드를 통해 유일한 인스턴스를 생성하거나 반환합니다. 이 메서드에서는 클래스 변수 instance가 null인 경우에만 새로운 인스턴스를 생성합니다. 그렇지 않은 경우에는 이미 생성된 인스턴스를 반환합니다.
이렇게 구현된 싱글톤 패턴은 singleton과 anotherSingleton이 같은 인스턴스인지 확인하는 로직으로 테스트하게 됩니다. getInstance() 메서드를 호출할 때마다 같은 인스턴스를 반환하기 때문에, 두 변수는 항상 같은 객체를 참조하게 됩니다.
간략히 싱글톤 패턴이 무엇인지 알아보았고 예시도 보았으니, 싱글톤 패턴의 장단점을 명확히 나눠서 확인하도록 하겠습니다.
싱글톤 패턴의 장단점
장점
- 인스턴스 제한
- 싱글톤 패턴을 사용하면 클래스의 인스턴스가 오직 하나만 만들어지기 때문에, 다른 곳에서 인스턴스를 만들 수 없습니다. 이를 통해 개발자는 여러 인스턴스가 만들어져서 발생할 수 있는 문제를 방지할 수 있습니다.
- 전역 변수 대체
- 싱글톤 패턴을 사용하면 전역 변수를 사용하지 않아도 객체를 쉽게 접근할 수 있습니다. 이는 코드의 유지보수성을 높이고, 다른 개발자들과 협업할 때 객체의 역할과 범위를 명확하게 이해하게 됩니다.
- 객체 생성 불필요
- 싱글톤 패턴을 사용하면 인스턴스가 이미 생성되어 있다면, 객체를 다시 생성하지 않고 그대로 사용할 수 있습니다. 이는 객체 생성에 필요한 리소스를 아낄 수 있으며, 애플리케이션의 성능을 향상할 수 있습니다.
단점
- 테스트가 어려울 수 있음
- 싱글톤 패턴은 전역 변수를 사용하는 것과 유사하기 때문에, 테스트 작성이 어려울 수 있습니다. 객체가 전역으로 사용되기 때문에, 다른 객체와 의존성을 갖는 경우가 많아질 수 있으며, 이를 해결하기 위해서는 의존성 주입과 같은 기법을 사용해야 합니다.
- 상태 공유
- 싱글톤 패턴은 전역 변수를 사용하는 것과 마찬가지로, 여러 곳에서 사용되기 때문에 객체의 상태가 바뀔 경우 다른 곳에서도 영향을 받게 됩니다. 이를 해결하기 위해서는 객체의 상태를 변경하지 않는 불변성(immutability)을 고려하거나, 동기화(synchronization)를 고려해야 합니다.
- 멀티스레딩 문제
- 싱글톤 패턴은 멀티스레딩 환경에서 동작할 때 문제를 일으킬 수 있습니다. 여러 스레드에서 동시에 인스턴스를 생성하려는 경우, 여러 개의 인스턴스가 생성될 수 있기 때문입니다. 이를 해결하기 위해서는 인스턴스 생성에 대한 동기화(synchronization)를 고려해야 합니다.
- 객체의 책임 범위
- 싱글톤 패턴은 객체의 책임 범위가 커질 수 있습니다. 단일 책임 원칙(Single Responsibility Principle, SRP)을 지키기 위해서는, 객체가 너무 많은 역할을 맡지 않도록 하는 것이 중요합니다. 하지만 싱글톤 패턴을 사용하면, 객체가 여러 곳에서 사용되기 때문에, 객체의 책임 범위를 제한하는 것이 어렵습니다.
지금까지 싱글톤 패턴에 대해 간단하게 적어보았습니다.
싱글톤 패턴은 객체지향 디자인 패턴 중 하나로, 인스턴스가 하나만 생성되는 것을 보장하여 객체의 생명주기를 관리하는 패턴이라고 합니다. 이를 통해 여러 인스턴스가 생성되는 문제를 방지하고, 전역 변수를 대체할 수 있습니다. 하지만 싱글톤 패턴은 객체의 책임 범위가 커지고, 멀티스레딩 환경에서 문제를 일으킬 수 있기 때문에, 적절한 상황에서 사용해야 합니다. 이를 고려하여 패턴을 적용하면, 좀 더 안정적이고 유지보수성이 좋은 코드를 작성할 수 있을 것 같습니다.
이론으로만 보던 디자인 패턴들을 하나둘씩 적용해 보면서 "패턴"이라고 칭하는 이유가 있다는 것을 한 번 더 알게 되었네요. 디자인 패턴들을 주입식으로 공부하는 것이 아닌 실제로 적용을 해보면서 익히도록 해야겠습니다.
'Backend > 개발 방법론 & 디자인 패턴' 카테고리의 다른 글
[Rate Limiting] Token Bucket 알고리즘 (2) | 2024.10.27 |
---|---|
API 디자인 패턴 (0) | 2023.12.13 |
DTO (Data Transfer Object)의 설계법 (0) | 2023.12.12 |
[Methodologies] Monorepo(모노레포)란? (0) | 2023.02.24 |
[Design Pattern] Factory Pattern (0) | 2022.08.05 |