Pink Transparent Star

이외 개발 스터디/디자인패턴

[ 내일배움캠프 ] TIL.18 - 싱글톤 패턴(Singleton Pattern)?

채유나 2024. 5. 9. 22:39
728x90

 

디자인 패턴 중 우리가 제일 쉽게 접근하는 패턴은 바로 "싱글톤 패턴 " 이다. 오늘은 많이 사용하는 싱글톤 패턴에 자세히 알고 앞으로 제대로 사용하고 싶어서 관련 내용을 작성해 보고자 한다.

 

🔷 싱글톤 패턴이란?

추상 객체 인스턴스 생성 패턴 중 하나로 다른 패턴과 다르게 싱글톤 패턴은 정말 단순하다. 객체의 인스턴스가 오직 1개만 생성되는 패턴을 의미한다. 여러 개의 스레드가 공유해야 할 정보들을 하나의 인스턴스에 담아 놓고, 싱글턴 패턴으로 설계하면 모든 스레드에 공통적으로 적용할 수 있다.

 

싱글톤을 구현하는 방법은 여러 가지 있지만 유니티에서 주로 사용하는 코드 구조를 아래와 같이 작성할 수 있다.

public class Singleton : MonoBehaviour
{
    public static Singleton Instance;

    private void Awake()
    {
        if(Instance != null)
            Destroy(gameObject); //Instance가 이미 존재한다면 삭제
        else
        {
            Instance = this; //나 자신은 Instance에 넣어줌
            DontDestroyOnLoad(this.gameObject); //OnLoad 될때 자신을 파괴하지않고 유지
        }        
    }
}

 

 

🔷 싱글톤 장점

위의 이미지는 싱글톤 화한 클래스가 Heap 메모리에 할당이 되고 다른 클래스에서 쉽게 접근한다는 것을 표현해 보았다.

 

🔸 메모리 측면

최초 한 번의 new 연산자를 통해서 고정된 메모리 영역을 사용하여  중복생성과 해당 객체에 접근할 때 메모리 낭비는 방지한다. 또한 생성된 인스턴스를 활용하여 속도 측면에서 이점을 볼 수 있다.

 

🔸 데이터 공유가 쉬움

싱글톤 인스턴스의 경우 전역으로 사용되기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있다.

But ❗ 여러 클래스의 인스턴스에서 싱글톤 인스턴스의 데이터에 접근하게 되면 동시성 문제가 발생할 수 있다.

 

🔷 싱글톤 단점

🔸 과할 경우 성능이 낮아진다

전역(static)으로 정적 메모리에 할당된 객체이기 때문에 큰 메모리가 쌓일 경우 프로그램의 성능이 낮아진다.

정적 메모리를 사용하기 때문에 병렬처리나 동기화 같은 메모리에 접근할 때 문제가 생길 수 있습니다.

 

🔸 결합도가 높아짐

너무 많은 데이터를 공유할 경우, 싱글톤 인스턴스와 다른 클래스 간의 결합도가 높아져 개방 폐쇄 원칙에 위배될 수 있다.

 

💡 개방 폐쇄 원칙(OCP) - Open Closed Principle

▪기존의 코드를 변경하지 않으면서, 기능을 추가할 수 있도록 설계되어야한다는 원칙

▪확장에 대해서는 개방적 (Open), 수정에 대해서는 폐쇄적(Closed)으로 정의된다.

 

유니티의 사용 예시

Scene에서 Scene을 넘어갈 때 지키기고 싶은 데이터가 있을때가 있다.

하지만 아래의 이미지와 같이 Scene이 넘어가는 경우 Level의 값이 유지되는게 아닌 초기화 되는 것을 확인 할 수 있습니다.

 

 

Scene이 넘어가도 데이터를 유지하는 방법은 무엇일까?

 

 

이때 싱글톤을 이용하여 GameManager 스크립트를 제작하고 데이터를 유지할 수 있습니다.

 

GameManager의 스크립트를 아래와 같이 짜준다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    public int level = 0; //유지하고 싶은 level 데이터

    private void Awake()
    {
        if (Instance != null)
            Destroy(this.gameObject);
        else
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
    }
}

 

1. 빈 게임오브젝트(Empty Object)를 생성한 뒤 "GameManager"

 

2. 해당 오브젝트에 작성한 GameManager 를 추가

 

이러면 GameManager를 사용하기 위한 준비 끝!

 

어디에서는 아래와 같이 작성을 하면 GamaManager의 데이터에 접근 할 수 있습니다.

GameManager.Instance.(변수명 or 함수명)

 

각 Scene의 버튼에 아래의 OnClick를 연결하면 테스트를 진행을 하게된다면 아래와 같이 확인이 가능합니다.

    public void OnClickLevelUp() //레벨 업 버튼
    {
        GameManager.Instance.level++;
    }

    public void OnClickLevelDown() //레벨다운 버튼
    {
        GameManager.Instance.level--;
    }

 

 

Scene이 변하더라도 level의 값이 변경되지않는 것을 확인할 수있습니다!

 

 

이때 DontDestroyOnLoad(gameObject)을 통해 해당 오브젝트를 파괴되지않고 유지되는 것을 확인 할 수 있다.

유니티에서의 싱글톤 역할

◾  단일 시스템 자원 관리 차원

◾ 게임 시스템 상 전역 변수의 역할

◾ 씬 로드 시 데이터가 파괴가 되지 않고 유지

◾ 여러 오브젝트가 접근

◾ 단 한 개의 객체만 존재

 

❗ 상태를 가진 객체를 싱글톤을 만들면 안된다. 그 이유는 각자 다른 스레드에서 객체의 상태를 변경시킬 여지가 있기 때문 !

 

결론

오직 한 개의 인스턴스 생성을 보증하여 효율을 찾을 수 있지만 그거에 동반되는 문제점도 많아 싱글턴이 정말 필요할 때 사용해야 한다는 것을 알게 되었다. 처음에는 데이터 접근하기 쉽게 다 싱글턴화 시키는 게 편하지 않을까?라는 생각을 했었는데 오히려 접근하기 쉬워 비대칭적인 크기로 게임이 만들어질 수 있다는 것을 알게 되었다. 

정말 필요할 때만 사용하는 것이 좋을 것 같다..!

 

그럼 GameManager에는 어떤 데이터를 담고있는 것이 좋을까? 한번 공부를 하고 정리를 해봐야겠다.

 

참고 사이트

 

유니티-싱글톤패턴(Singleton) 설명 및 스크립트 예제

오랜만의 포스팅을 싱글톤으로 하게 되었네요. 일단 제 기준으로 유니티에서 사용하기 편하고 관리하기 쉬운 방법의 싱글톤 예제를 가지고 왔습니다. 싱글톤의 역할 싱글톤은 프로그래밍 디자

art-life.tistory.com

 

 

[디자인패턴] 싱글톤 패턴(Singleton Pattern)

1. 싱글톤 패턴이란? 2. 싱글톤 패턴의 장단점 3. 싱글톤 패턴 예시 코드 1. 싱글톤 패턴(Singleton Pattern)이란? : 해당 클래스의 인스턴스가 하나만 생성되게 하고, 어디서든 그 인스턴스에 접근할 수

geukggom.tistory.com

 

728x90