[GetX] Service vs. Controller 차이를 GetX 패턴에 적용하기

Broccolism·2022년 8월 21일
6
post-thumbnail

참고 영상: YouTube 개발하는 남자 - [ Flutter / 플러터 ] GetxService 는 GetxController 와 뭐가 다를까? #7

문득 궁금해졌다. 공식 문서에 보면 서비스와 컨트롤러의 차이점에 대해 크게 눈에 띄게 설명해놓은 부분이 없다. 위 유투브 영상을 보면 실험을 통해 간단하게 차이점을 설명하고 있다.

  • GetxController: 화면이랑 같이 죽는다.
  • GetxService: 영원히 살아있다.

그래서 GetxService로 등록한건 아래 코드처럼 일부러 데이터를 날리지 않는 이상 앱 실행하는동안 계속 유지된다.

Get.reset();

GetX 패턴에 적용하기

GetX 패턴은 저번에도 다룬 적이 있다. GetX는 플러터 상태 관리 라이브러리 중 하나인데, 사용 방법이 간편해서 많은 사람들이 쓰고 있다. (어느날 구글링을 하면서 GetX 사용이 독이 될 수 있다는 글을 시작으로 달린 긴 논쟁을 본 적이 있지만, 간편하다는 사실에는 논란이 없었다.) GetX를 사용하면서 누군가 개인적으로 프로젝트 구조를 정리한게 있는데, 이게 널리 널리 퍼져서 GetX Pattern 으로 자리잡았다.

Repository는 GetxService, Controller는 GetxController

GetX 패턴에서 데이터의 흐름은 이렇게 흐른다: (백엔드 서버) -> Api -> Repository -> Controller -> View. 사용자가 화면에서 볼 데이터를 컨트롤러가 관리하는데, 이 컨트롤러에게 데이터를 wrapping해서 넘겨주는 역할을 repository가 한다. 모바일 환경에서 화면 하나는 여러번 생겼다가 사라질 수 있다. 하지만 데이터를 warpping해서 넘겨주는 기능은 앱이 실행되는 내내 살아있어야 한다.
앞서 말했듯이 GetxService는 일부러 지우지 않는 이상 앱 종료 전까지 쭉 남아있고, GetxController는 화면이 죽으면 같이 죽는다. (그렇게 안 할 수도 있지만 별도 옵션을 줘야 한다.)

  • 결론: Repository는 GetxService, Controller는 GetxController를 사용하면 좋다.

아래는 예시 코드다.

// sample_repository.dart

abstract class AbstractSampleRepository {
  Future<SampleUserModel> getSampleUserProfile();
}

class SampleReopsitory extends GetxService implements AbstractSampleRepository {
  final SampleApi sampleApi;

  SampleReopsitory({required this.sampleApi});
  
  Future<SampleUserModel> getSampleUserProfile() async {
    try {
      Response res = await sampleApi.getSampleUserProfile();
      debugPrint(res.body.toString());
      return SampleUserModel.fromJson(res.body);
    } catch (e) {
      debugPrint("ERROR: $e");
      rethrow;
    }
  }
}
// sample_controller.dart
class SampleController extends GetxController {
  final SampleReopsitory sampleReopsitory;

  SampleController({required this.sampleReopsitory});

  final Rx<SampleUserModel?> _user = Rx<SampleUserModel?>(null);
  SampleUserModel? get user => _user.value;

  Future<void> getProfileAndIncreaseCount() async {
    await _getSampleUserProfile();
    _increaseCount();
  }

  Future<void> _getSampleUserProfile() async {
    _user.value = await sampleReopsitory.getSampleUserProfile();
  }
}

번외) Api는 GetConnect

GetX가 편리하다고 하는 여러가지 이유 중 하나로, http 통신에 대한 wrapper 클래스가 있다. GetConnect 클래스다. http 메소드를 다음과 같이 사용할 수 있다.

const sampleUrl = "http://ko.gravatar.com/beaua06344c126b.json";

class SampleApi extends GetConnect {
  Future<Response> getSampleUserProfile() async {
    return await get(sampleUrl);
  }
}
profile
설계를 좋아합니다. 코드도 적고 그림도 그리고 글도 씁니다. 넓고 얕은 경험을 쌓고 있습니다.

4개의 댓글

comment-user-thumbnail
2022년 12월 5일

저도 GetX를 써봤지만 확실히 개발 편의성 만큼은 여타 상태관리 패키지들에 비해서 최고! 다만 나중에 프로젝트 커지면 편의성이 오히려 독이 되기도하더라구요 ㅠ 저는 이제 Bloc을 선호하게 되었답니다...

1개의 답글
comment-user-thumbnail
2023년 3월 3일

GetX로 상태관리를 할 때, 추후 프로젝트 규모가 커지면 한 Controller안에 코드 수가 너무 많다고 느껴질 때가 있는데, 같은 맥락 안에 있더라도 Controller를 나눠주는게 좋을까요?

1개의 답글