💻 개발/Flutter

[Flutter / Dart] What is Singleton?

고도고도 2022. 7. 21. 00:08

블로그 내의 게시물은 PC 버전에 최적화 되어 있습니다.

 

정말 오랜만에 글 쓰는 거 같네요. 미국에서 돌아와서 일기 쓴 게 마지막인데 주기적으로 쓰려고 했었는데 1학기에 프로젝트가 너무 많아서 바빴습니다. 글 쓰고 있는 지금은 엔씨소프트에서 7주짜리 채용연계형 인턴을 하고 있습니다. 인턴을 진행하면서 플러터로 개발을 하고 있는데 개발하면서 알게된 것들, 정리하면 좋은 것들을 적어두고 싶어서 오늘부터 주기적으로 포스팅을 해보려고 합니다. (1학기 회고록을 작성하고 있는데 아직 작성이 안돼서 비공개로 해놨습니다...

 

싱글톤

싱글톤, 전공자라면 다들 많이 들어봤을 단어일 겁니다. 말 그대로 싱글, 하나의 인스턴스만 존재하도록 하는 것입니다. 인스턴스를 하나만 가지기 위해서는 어떻게 해야할까요? 머리 속에 떠오르는 개념 그대로 구현하면 됩니다. 인스턴스가 생성되어 있으면 그걸 반환하면 됩니다.

 

 우선 자바 코드로 살펴보겠습니다.

public class Singleton {
	private static Singleton _instance;
    
    // 외부에서 생성하지 못하도록
    private Singleton() {}
    
    public Singleton getInstance() {
    	if (_instance == null) {
        	_instance = new Singleton();
        }
    	return _instance;
    }
 }

private로 선언하고 인스턴스가 생성되어 있으면 이를 반환하고 그렇지 않으면 인스턴스를 생성합니다.

 

번외로 코틀린에서는 Object를 사용해서 싱글톤을 아주 쉽게 구현할 수 있습니다.

object Singleton {}

안드로이드 공부할 때 자주 사용했었고 주로 Retrofit에 사용했습니다. 네트워크 라이브러리인데 객체를 매번 생성할 필요가 없어서 이를 Object로 정의하고 사용했습니다.

 

다트에서도 Factory를 사용해서 쉽게 구현할 수 있습니다. 코틀린에서와 마찬가지로 네트워크와 관련된 클래스를 정의할 때 사용했습니다. HTTP의 Header를 설정하는 함수와 GET, POST, PUT, DELETE 함수를 정의한 HttpManager 클래스를 정의했는데 위의 예시와 마찬가지로 객체를 매번 생성할 필요가 없었기에 이를 싱글톤으로 구현했습니다.

class HttpManager {
  static final HttpManager _instance = HttpManager._internal();
  
  HttpManager._internal() {
    print("클래스가 최초에 생성될 때 한번만 실행\n");
  }
  
  factory HttpManager() {
    print("생성자 호출");
    return _instance;
  }
}

// ... 생략 ...

class APIRequest {
  final httpManager = HttpManager();
  final anotherHttpManager = HttpManager();
}

구현한 코드 중에 일부를 가져왔고 이를 실행하면 아래와 같은 결과가 출력됩니다. _internal()은 클래스가 처음에 호출될 때만 실행됩니다. 자바에서의 클래스 초기화블록처럼 활용하면 됩니다.

 

두 인스턴스가 같은 인스턴스인지에 대해 의문이 든다면 haseCode를 통해 확인해봅니다.

class HttpManager {
  static final HttpManager _instance = HttpManager._internal();

  HttpManager._internal() {
    print("클래스가 최초에 생성될 때 한번만 실행\n");
  }

  factory HttpManager() {
    print("생성자 호출");
    return _instance;
  }
}

void main() {
  final httpManager = HttpManager();
  final anotherHttpManager = HttpManager();
  
  print("");
  print(httpManager.hashCode);
  print(anotherHttpManager.hashCode);
}

같은 인스턴스임을 확인할 수 있습니다.