본문 바로가기

기본 프로그래밍 지식

[기본 지식] 3. 디자인 패턴 - 싱글톤 패턴(Singleton Pattern)

반응형

디자인 패턴

  • 디자인 패턴이란 프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계등을 이용하여 해결할 수 있도록 하나의 '규약'형태로 만들어 놓은 것을 의미.

싱글톤 패턴

  • 싱글톤 패턴(singleton pattern)은 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴입니다. 
  • 보통 데이터베이스 연결 모듈에 많이 사용합니다. 
  • 하나의 인스턴스를 만들어 놓고 해당 인스턴스를 다른 모듈들이 공유하며 사용하기 때문에 인스턴스를 생성할 때 드는 비용이 줄어드는 장점이 있습니다.
  • 하지만 의존성이 높아진다는 단점이 있습니다. 

자바스크립트의 싱글톤 패턴

  • Javascript에서는 리터럴 {} 또는 new Object로 객체를 생성하게 되면 다른 어떤 객체와도 같지 않기 때문에 이 자체만으로 싱글톤 패턴을 구현할 수 있습니다. 
    //javascript
    const obj = {
    	a: 27;
    }
    const obj2 = {
    	a: 27;
    }
    console.log(obj === obj2);
    // false
  • 앞의 코드에서 볼 수 있듯이 obj와 obj2는 다른 인스턴스를 가집니다. 
    //javascript
    class Singleton {
    	constructor() {
    		if(!Singleton.instance) {
    			Singleton.instance = this;
    		}
    		return Singleton.instance;
    	}
    	getInstance() {
    		return this.instance;
    	}
    }
    
    const a = new Singleton();
    const b = new Singleton();
    console.log(a === b); 	// true
  • 앞의 코드는 Singleton.instance라는 하나의 인스턴스를 가지는 Singleton 클래스를 구현한 모습입니다. 이를 통해 a와 b는 하나의 인스턴스를 가집니다. 

데이터베이스 연결 모듈

  • 싱글톤 패턴은 데이터베이스 연결 모듈에 많이 쓰입니다. 
    //javascript
    const URL = 'mongodb://localhost:27017/kundolapp'
    const createConnection = url => ({"url" : url})
    class DB {
    	constructor(url) {
    		if(!DB.instance) {
    			DB.instance = createConnection(url)
    		}
            return DB.instance
    	}
        connect() {
    		return this.instance
    	}
    }
    const a = new DB(URL)
    const b = new DB(URL)
    console.log(a === b) // true
  • 이렇게 DB.insance라는 하나의 인스턴스를 기반으로 a, b를 생성하는 것을 볼 수 있습니다. 이를 통해 데이터베이스 연결에 관한 인스턴스 생성 비용 을 아낄 수 있습니다. 

자바에서의 싱글톤 패턴

  • 자바로는 다음과 같이 할 수 있습니다. 
    class Singleton {
    	private static class singleInstanceHolder {
    		private static final Singleton INSTANCE = new Singleton();
    	}
    	public static synchronized Singleton getInstance() {
    		return singleInstanceHolder.INSTANCE;
    	}
    }
    
    public class HelloWorld {
    	public static void main(String[] args) {
    		Singleton a = Singleton.getInstance();
    		Singleton b = SIngleton.getInstance();
    		System.out.println(a.hashCode());
    		System.out.println(b.hashCode());
    		if (a==b) {
    			System.out.println(true);
    		}
    	}
    }
    /*
    705927765
    705927765
    true
    */

mongoose의 싱글톤 패턴

  • 실제로 싱글톤 패턴은 Node.js에서 MongoDB 데이터베이스를 연결할 때 쓰는 mongoose 모듈에서 볼 수 있습니다. 
  • mongoose의 데이터베이스를 연결할 때 쓰는 connect()라는 함수는 싱글톤 인스턴스를 반환합니다.
  • 다음은 connect() 함수를 구현할 때 쓰인 실제 코드입니다. 
    Mongoose.prototype.connect = function(uri, options, callback) {
    	const _mongoose = this instanceof Mongoose ? this : mongoose;
    	const conn = _mongoose.connection;
    	
    	return _mongoose._promiseOrCallback(callback, cb => {
    		conn.openUri(uri, options, err => {
    			if (err != null) {
    				return cb(err);
                }
    			return cb(null, _mongoose);
    		});
        });
    };

MySQL의 싱글톤 패턴

  • Node.js에서 MySQL 데이터베이스를 연결할 때도 싱글톤 패턴이 쓰입니다. 
    // 메인 모듈
    const mysql = require('mysql');
    const pool = mysql.createPool({
    	connectionLimit: 10,
        host: 'example.org',
        user: 'kundol',
        password: 'secret',
        database: 'test_database'
    });
    pool.connect();
    
    // 모듈 A
    pool.query(query, function (error, results, fields) {
    	if (error) throw error;
    	console.log('The solution is: ', results[0].solution);
    });
    
    // 모듈 B
    pool.query(query, function (error, results, fields) {
    	if (error) throw error;
    	console.log(The solution is: ', results[0].solution);
    });
  • 앞의 코드처럼 메인 모듈에서 데이터베이스 연결에 관한 인스턴스를 정의하고 다른 모듈인 A 또는 B에서 해당 인스턴스를 기반으로 쿼리를 보내는 형식으로 쓰입니다. 

싱글톤 패턴의 단점

  • 싱글톤 패턴은 TDD(Test Driven Development)를 할 때 걸림돌이 됩니다.
  • TDD를 할 때 단위 테스트를 주로 하는데, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행 할 수 있어야 합니다.
  • 하지만 싱글톤 패턴은 미리 생성된 하나의 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 '독립적인' 인스턴스를 만들기가 어렵습니다. 

 

 

 

참고자료

  •  면접을 위한 CS 전공지식 노트 - 주홍철
반응형