[개념 정리/디자인 패턴] 생성 패턴 - 싱글톤 패턴
생성 패턴 중 하나인 싱글톤 패턴에 대해 알아보자.
싱글톤 패턴 (Singleton pattern)
싱글톤 패턴은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴이다.
하나의 클래스를 기반으로 여러 개의 개별적인 인스턴스를 만들 수 있으나,
그렇게 하지 않고 하나의 클래스를 기반으로 단 하나의 인스턴스를 만들고,
이를 기반으로 로직을 구성하는데 쓰이며,
주로 데이터베이스 연결 모듈에 많이 사용된다.
장점
하나의 인스턴스를 기반으로 다른 모듈이 그 인스턴스를 공유하여 사용하기 때문에,
인스턴스 생성 비용이 낮다.
그렇기에 인스턴스 생성 비용이 높은 I/O 바운드* 작업에 많이 사용된다.
(*I/O 바운드: 네트워크 통신, 데이터베이스 연결, 파일 시스템, 디스크 연결 등)
단점
의존성이 높아지며,
이는 TDD(Test Driven Development) 진행 시 문제가 된다.
TDD 과정에서 단위 테스트가 주로 이루어지는데,
단위 테스트는 서로 독립적이어야 하며, 순서에 영향을 받지 않아야 한다.
그러나 싱글톤 패턴은 처음에 생성되는 하나의 인스턴스를 기반으로 구현하는 패턴이므로
테스트마다 독립적인 인스턴스를 만들기 어렵다.
예를 들어 데이터베이스 연결을 위한 인스턴스를 생성 과정이 있다면
데이터베이스를 활용한 기능 테스트는 연결보다 이후에 실행되어야 하는 등의
의존성과 순서 문제가 발생한다.
예시
아래는 자바스크립트의 싱글톤 패턴의 기본적인 예시이다.
class Singleton {
constructor() {
if(!Singleton.instance){
Singleton.instance = this
}
return Singleton.instance
}
getInstance() {
return this
}
}
const a = new Singleton()
const b = new Singleton()
console.log(a === b) //true
아래는 내가 프로젝트에서 MySQL 데이터베이스 연결 과정에서 사용한
싱글톤 패턴의 예시이다.
const appDataSource = new DataSource({
type: process.env.DB_TYPE,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
dateStrings: process.env.DB_DATESTRINGS,
});
const createLike = async (proudctId, userId) => {
try {
const createLike = await appDataSource.query(
`INSERT INTO likes(
product_id,
user_id
) VALUES (?,?)
`,
[proudctId, userId]
);
return createLike;
} catch (err) {
throw new DatabaseError('DATABASE_ERROR');
}
};
const deleteLike = async (proudctId, userId) => {
try {
const deleteLike = await appDataSource.query(
`DELETE FROM likes
WHERE product_id =?
AND user_id =?
`,
[proudctId, userId]
);
return deleteLike;
} catch (err) {
throw new DatabaseError('DATABASE_ERROR');
}
};
new DataSource()로 데이터베이스와 연결하여 appDataSource라는 인스턴스를 생성하여
이후 여러 함수에서 해당 인스턴스를 이용해 query를 보내고 있다.
참고: inflearn 강의 'CS 지식의 정석 - 큰돌'