메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

싱글턴 패턴 - 패턴으로 알아보는 객체지향의 원리(2)

한빛미디어

|

2020-10-08

|

by 한빛

905

 

싱글턴 패턴은 생성 패턴 중 가장 많이 주목받는 패턴 중 하나입니다. 싱글턴은 자원 공유를 위해 객체 생성 개수를 1개로 제한합니다.

 

 

객체 생성

클래스는 선언 후 객체를 생성해야 사용할 수 있습니다. 객체 생성은 내부 new 키워드를 사용합니다. new 키워드의 또 다른 중복 객체 생성 특징에 대해 알아봅시다.

 

new 키워드

선언된 클래스를 객체로 생성하는 과정을 인스턴스화라고 합니다. 인스턴스화는 선언된 클래스를 기반으로 객체를 생성해 메모리에 할당하는 작업을 수행합니다. 그리고 이 모든 일을 수행하게 만드는 명령어가 new 키워드입니다. [예제 - 아래]는 간단한 인사말을 출력하는 클래스입니다.

 

<예제>

<?php

class Hello

{

    public function greeting()

    {

        return "안녕하세요.";

    }

}

Hello 클래스의 객체를 생성해 변수 $obj에 저장합니다. 이 코드를 그림으로 설명하면 다음과 같습니다.

 

3.jpg

객체 생성

 

클래스를 이용해서 객체를 생성하는 방법은 new 키워드가 유일하며, new 키워드를 사용하지않고 객체를 생성할 수는 없습니다. 많은 언어에서 선언된 클래스를 이용해 객체를 생성할 때 new 키워드로 설계하는 경우가 많습니다.

 

객체의 중복

객체의 인스턴스화 과정을 좀 더 살펴봅시다. 객체 생성이란 선언된 클래스에 따른 객체를 메모리에 할당하는 동작입니다. 이러한 객체 생성 과정은 new 키워드를 통해 반복 생성할 수 있는데, 다음과 같이 new 키워드를 이용해 클래스의 동일한 객체를 여러 개 생성할 수 있습니다.

 

<예제>

$obj1 = new Hello;

$obj2 = new Hello;

$obj3 = new Hello;

$obj4 = new Hello;

$obj5 = new Hello;

 

이 코드의 의미는 한 번 선언된 클래스를 이용해 동일한 객체를 제한 없이 무제한으로 생성할수 있다는 것입니다. 즉 시스템 자원이 허락하는 한 무제한으로 객체를 생성할 수 있습니다.

 

4.jpg

객체 중복 생성

 

선언된 클래스는 객체를 생성하기 위한 모형 틀과 같고, 이 모형 틀을 이용해 동일한 객체를 수없이 생성할 수 있습니다. 이런 이유로 객체를 붕어빵과 붕어빵 틀에 비유하여 설명하는 경우도 많습니다. 이는 객체지향의 원리이며 특징입니다.

 

 

유일한 객체

앞에서 알아본 것과 같이 객체지향에서는 하나의 클래스를 이용하여 객체를 무제한 생성할 수있습니다. 이러한 객체지향의 특징은 장점이면서 때로 단점이 되기도 합니다. 그 이유를 살펴봅시다.

 

자원 공유

객체지향에서 new 키워드로 생성한 객체는 각각 독립된 자원입니다. 독립된 자원이란 서로 다른 메모리 영역을 차지하고 있다는 것을 의미합니다. 만일 생성된 하나의 객체를 공유할 경우 복수 객체를 생성하는 new 키워드의 특징이 문제가 됩니다.

 

5.jpg

객체 공유 문제

 

선언된 클래스는 하나지만 new 키워드로 생성된 객체는 2개입니다. 별도의 C 객체가 동일한 클래스로 생성된 객체라고 착각하여 정보에 접근할 때 문제가 발생합니다. A, B 객체는 단지 생성을 위한 클래스 선언만 같을 뿐, 서로 다른 메모리에 생성된 전혀 다른 객체입니다. 따라서 객체가 동일하지 않으므로 객체의 상탯값을 공유할 수 없습니다.

 

스코프

프로그램에서는 변수를 크게 전역 변수와 로컬 변수로 구분합니다. 변수가 접근할 수 있는 영역을 구분하는 것입니다. 이러한 변수의 접근 영역 구분을 다른 용어로 스코프scope라고 합니다. 전역 변수는 프로그램 전반에서 접근 가능한 공용 변수로 데이터를 쉽게 공유할 수 있다는 장점이 있습니다. 함수는 대표적으로 변수의 접근 영역을 구분하는 프로그래밍 방식입니다. 하지만 함수들은 변수 영역이 서로 나뉘어 있기 때문에 함수 간 데이터를 공유하기 힘듭니다. 이러한 이유로 이전에는 전역 변수를 활용해 함수 간 값을 공유 처리했습니다.

 

예를 들어 PHP에서는 전역 변수 접근을 위한 global 키워드를 제공합니다. 함수 안에 있는 변수명 앞에서 global 키워드를 이용하면 함수 밖의 변수에 접근할 수 있습니다. 또는 $GLOBALS 슈퍼 변수를 이용할 수도 있습니다. 다음은 $GLOBALS 슈퍼 변수를 이용해 전역 변수에 접근하는 예제입니다.

 

<예제>

<?php

$conf = [

    ‘name’= >"jiny",

    ‘version’= >"1.0"

];

 

class foo

{

    public function conf()

    {

        return $GLOBALS[‘conf’]; // 전역 변수 접근

    }

}

 

$obj = new foo;

print_r($obj->conf());

 

foo 클래스의 conf ( ) 메서드는 클래스 밖에 있는 $conf 변수에 접근하여 값을 읽은 후 반환합니다.

 

$ php index.php

Array

(

    [name] => jiny

    [version] => 1.0

)

global 키워드나 $GLOBALS 슈퍼 변수로 외부의 전역 변수값을 참조하는 방식은 오래 전부터 사용해온 방법입니다.

 

하지만 전역 변수로 외부의 값을 공유하면 다양한 문제가 발생할 수 있기 때문에 전역 변수로 값을 공유할 때는 스코프의 변수 범위를 보다 면밀하게 관리해야 합니다. 잘못하면 사이드 이펙터(부작용)side effect으로 오동작이 발생할 수 있어 디버깅에 많은 어려움이 있습니다.

 

 

싱글턴

전역 변수처럼 생성한 객체를 공유하려면 하나의 객체만 존재해야 합니다. 객체가 중복 생성되면 공유할 수 없습니다. 싱글턴은 다른 생성 패턴과 달리 하나의 객체만 생성을 제한하는 패턴입니다. 그리고 생성된 객체는 공유되어 어디서든 접근할 수 있습니다.

 

유일한 객체

싱글턴이라는 이름만으로도 동작을 유추할 수 있습니다. 옛말에 ‘사공이 많으면 배가 산으로 간다’는 말이 있습니다. 싱글턴이라는 단어는 ‘하나’, ‘단독’과 같은 의미입니다.

 

응용 프로그램에서 전역 변수, 공용 장치 등은 하나의 객체만 필요한 경우가 많습니다. 예를 들면 컴퓨터에서 키보드 입력 장치는 하나입니다. 여러 대의 프린터가 연결되어 있어도 프린터로 전송하는 데이터 스풀spool은 하나입니다. 또한 프로그램의 환경 설정 파일도 하나만 있습니다.

 

이런 것이 여러 개 존재한다면 시스템과 프로그램은 자주 충돌할 것입니다. 충돌을 방지하려면 단일 객체를 사용해야 하며, 싱글턴은 하나의 객체만 유지하게 하는 생성 패턴입니다. 싱글턴 패턴은 다음과 같은 상황에서 매우 유용합니다.

  • 공유 자원 접근
  • 복수의 시스템이 하나의 자원에 접근할 때
  • 유일한 객체가 필요할 때
  • 값의 캐시가 필요할 때

 

전역 객체

일반적인 절차지향적 프로그래밍 방법에서 전역 변수는 global 키워드를 사용해 쉽게 접근합니다. 전역으로 선언된 변수는 하나만 존재하므로 값을 공유하기가 편합니다. 하지만 객체를 생성해 공유하려면 어떻게 해야 할까요? 객체는 중복 생성이 가능하기 때문에 생성된 객체를 공유하려면 약간의 속임수가 필요합니다.

 

객체를 공유하려면 객체를 복수로 생성하는 문제가 해결되어야 합니다. 그리고 생성되는 객체를 1개의 단일 객체로 유지해야 합니다. 단일 객체는 여러 곳에서 접근을 시도해도 결국은 동일한 객체를 사용하게 됩니다.

 

[그림(아래)를 보면서 예를 들어봅시다. 하나의 클래스로 생성된 객체의 상탯값을 공유하려면 객체 생성을 제한해야 합니다. 여기서 ‘제한한다’는 의미는 new 키워드를 사용할 때 서로 다른 A, B 객체가 생성되는 것이 아니라 동일한 객체 1개만 유지한다는 것입니다. 그리고 이러한 기능을 처리하는 패턴을 싱글턴이라고 합니다.

 

6.jpg

객체에 접근하는 방법만 다를 뿐 같은 객체를 사용한다

 

싱글턴 패턴을 적용하면 몇 번의 new 명령을 수행해도 동일한 객체를 반환하며, 1개의 객체만 존재하므로 객체를 공유해도 문제 발생 소지가 적습니다. 싱글턴은 전역 변수를 객체 형태로 변형해놓은 전역 객체입니다.

 

객체지향 프로그램에서 객체 1개만으로 프로그램을 작성하는 경우는 없습니다. 프로그램 설계시 수많은 클래스 선언과 객체가 생성되고 각각의 객체는 고유한 책임을 집니다.

 

이러한 객체들은 서로 관계를 맺으며 복잡한 동작을 수행합니다. 모든 객체는 상호 관계 속에서 작용하며 동작하고, 객체의 상호 관계 속에는 공유 객체도 존재합니다. 서로 다른 객체가 값을 공유할 때나 중복되는 자원을 줄일 때 싱글턴 패턴을 적용합니다.

 

보증

싱글턴에서 중요한 핵심은 ‘어떻게 하나의 객체만 생성할 수 있는가’입니다. 싱글턴은 객체의 관계 속에서 상호 작용하기 위한 값을 저장하고 전달하는데, 값을 전달하기 위해서는 공용 객체가 필요합니다. 싱글턴 패턴은 new 키워드 이용해 객체를 생성하는 방법을 원천적으로 금지합니다. 클래스의 생성자 접근 제한으로 인해 new 키워드의 객체 생성 동작을 방해합니다. 객체 생성이 제한된 싱글턴은 대신 객체를 생성할 수 있는 메서드를 추가하며, new 키워드 대신 객체 생성 메서드 호출만으로 객체를 생성할 수 있습니다.

 

또한 싱글턴은 내부 참조체가 있어 자신의 객체를 보관합니다. 즉 내부적으로 중복 생성을 방지하는 로직(플라이웨이트 패턴)이 있습니다. 싱글턴은 참조체를 통해 하나의 객체만 갖도록 보증하지만, 싱글턴 패턴을 적용하면 클래스 상속과 복수 객체를 생성할 수 있는 객체지향의 장점은 포기해야 합니다.

 

 

 

 

24가지 패턴으로 알아보는 객체지향의 원리

쉽게 배워 바로 써먹는 디자인 패턴

 

B9696096335_l.jpg

 

 

 

댓글 입력
자료실