접은 글은 스스로에 대한 개인적인 피드백을 담고 있습니다. (TMI)
해설 영상을 보며 과제를 진행할 때 해설 영상의 코드를 이해해보려고 시간을 많이 허비하였습니다. 잘못된 방향으로 쓰여진 코드를 해설 영상의 코드이므로 일방적으로 맞다고 생각하며 너무 맹목적으로 정보를 받아들인 것을 반성하여봅니다.. ( 다른 사람의 코드에서 리팩토링을 하는 방향성만 알려주셨기에 해당 코드의 세부적인 내용에 대해선 튜터님께서도 모르셨다)
이번 개인과제 제출이 얼마안남은 상황이고 중간에 잘못된 방향으로 시간을 많이 잡아먹어 오늘 배운 내용으로만 생각을 간략하게 정리해야할 것 같습니다.
이제라도 과제를 전부 끝마치진 못하더라도 제 방식으로 다시 생각해보며 배운 내용을 활용해 경험을 쌓는 형식으로 과제를 수행해봐야할 것 같습니다.
오늘은 어제의 TIL에서 정리해봤던 제네릭을 활용한 제약 조건을 이해해보고 제네릭 싱글톤을 만들어보는 형태로 학습하였습니다.
왜 제네릭 싱글톤을 사용하였나..
과제의 해설영상에서는 Manager에 정보를 몰아넣고 있습니다. 따라서 좀 더 효율적으로 싱글톤을 세분화할 수 있으면 편하지 않을까 라는 생각에서 만들어보고 싶었습니다.
목표를 설정하였으니 학습
where T : 의 기능에 대해 생각을 많이 해보았고 또 추론하여 찾아본 결과 <T>에 들어가는 자료형을 제한하는 제약 조건이라는 결론을 내었었습니다.
일단 제네릭 싱글톤을 사용할 때는 상속을 알아야합니다. 상속을 하는 쪽의 정보를 받는 쪽에서 공유가 가능한 것을 이용하여 싱글톤의 기능을 나누어주는 것이 제네릭 싱글톤의 원리입니다.
public class Manager<T> : MonoBehaviour where T : MonoBehaviour //다른 자료형이 들어갈수도 있기에 MonoBehaviour로 제한을 걸어둠
{
private static T instance;
public static T Instance
{
get
{
if(instance == null) //상속받은 클래스의 인스턴스가 null이라면
{
instance = FindObjectOfType<T>(); //어딘가에 해당 인스턴스가 존재할 수 있으니 해당 클래스의 타입을 찾는다.
//instance = (T)FindAnyObjectByType<T>();
if (instance == null) //그럼에도 찾을 수 없다면
{
GameObject singletonObj = new GameObject(typeof(T).Name); //해당클래스의 이름으로 새로운 객체를 만들고
instance = singletonObj.AddComponent<T>(); //해당 타입으로 초기화 시켜준다.
DontDestroyOnLoad(singletonObj);
}
}
return instance;
}
}
}
제네릭 클래스임을 알려주기 위해 클래스명 옆에 <T> 를 써주고 where T : MonoBeheviour로 MonoBeheviour를 사용하는 클래스만이 상속을 받을 수 있도록 설정하여줍니다.
상속을 하였을 때 MonoBehaviour도 같이 상속받긴 하지만 where T : MonoBehaviour를 써주는 이유는 <T>에 다른 자료형이 들어가는 경우와 MonoBehaviour가 없으면 유니티 기능을 사용할 수 없기 때문에 이런 기능을 보장해주는 역할입니다.
public class Manager<T> : MonoBehaviour where T : MonoBehaviour
부모 클래스는 사실상 자식 클래스의 설계도와 비슷한 부분입니다. 실 기능보단 여러 클래스와 공유하고 싶은 기능을 작성하는 것이 일반적입니다. 그래서 일단 일반 싱글톤 처럼 static으로 전역 변수임을 선언하여 줍니다.
private static T instance; <=T는 상속받는 클래스의 자료형이 들어가게 된다. EX) AudioManager instance
public static T Instance
프로퍼티 부분에서 일반 싱글톤 패턴처럼 인스턴스를 초기화 시켜주어 instance가 비어있을 때 생성하는 로직을 작성합니다. <T>는 상속받았을 때 상속받는 클래스의 자료형이 들어가는 것을 계속 인지해주셔야 합니다.
public static T Instance
{
get
{
if(instance == null) //instance가 null일 때
{
instance = FindObjectOfType<T>(); //어딘가에 해당 인스턴스가 존재할 수 있으니 해당 클래스의 타입을 찾는다.
if (instance == null) //그럼에도 null이라면
{
GameObject singletonObj = new GameObject(typeof(T).Name); //해당클래스의 이름으로 새로운 객체를 만들고
instance = singletonObj.AddComponent<T>(); //해당 타입으로 초기화 시켜준다.
}
}
return instance;
}
Find 관련 함수의 경우 오브젝트를 모두 뒤져 찾는 것이기에 성능저하가 일어날 수 있다고 알고있는데 싱글톤을 선언하는 시점에서는 오브젝트가 그렇게 많지 않기에 허용되는 범위입니다.
public class AudioManager : Manager<AudioManager> <= Manager<T> 부분을 생각하여 자기 자신의 타입을 넣어준다.
{
}
//AudioManager.Instance. 처럼 이제 싱글톤으로 접근이 가능하다.
상속받는 클래스에선 제네릭에서 호출하는 쪽에서 자료형을 정해주는 것을 생각하여 꺽쇠부분에 자기 자신의 클래스 타입을 적어주시면 싱글톤을 상속받을 수 있습니다.
제네릭 싱글톤은 앞으로의 프로젝트에서도 사용할 여지가 많을 것 같고 또 활용도가 높아보였기에 한번 알아보고 싶은 개념이었습니다. 관련 예시부분을 좀 더 찾아봐서 정보를 얻어보고 개선하여보는 방향으로 개념을 더 정리해보고 싶은 마음입니다.
'TIL' 카테고리의 다른 글
2024 11 14 TIL (0) | 2024.11.14 |
---|---|
2024 11 13 TIL (0) | 2024.11.13 |
2024 11 11 TIL (2) | 2024.11.11 |
2024 11 08 TIL (0) | 2024.11.08 |
2024 11 07 TIL (0) | 2024.11.07 |