GetX — 간편한 상태 관리와 라우팅, 의존성 주입

GetX는 상태 관리, 라우팅, 의존성 주입을 하나의 패키지로 제공하는 올인원 솔루션입니다. 보일러플레이트가 적고 배우기 쉬워서 입문자에게 인기가 많습니다.


설치

YAML
dependencies:
  get: ^4.6.0
DART
// MaterialApp 대신 GetMaterialApp 사용
void main() {
  runApp(GetMaterialApp(
    home: const HomeScreen(),
  ));
}

상태 관리

반응형 상태 관리 (Reactive)

DART
class CounterController extends GetxController {
  // .obs로 반응형 변수 선언
  final count = 0.obs;
  final name = ''.obs;
  final items = <String>[].obs;

  void increment() => count.value++;
  void decrement() => count.value--;

  void addItem(String item) => items.add(item);
}

// UI에서 사용
class CounterScreen extends StatelessWidget {
  const CounterScreen({super.key});

  @override
  Widget build(BuildContext context) {
    // 컨트롤러 등록 및 가져오기
    final controller = Get.put(CounterController());

    return Scaffold(
      body: Center(
        // Obx로 반응형 UI 구성
        child: Obx(() => Text(
          '${controller.count.value}',
          style: const TextStyle(fontSize: 48),
        )),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

단순 상태 관리 (Simple)

DART
class SimpleController extends GetxController {
  int count = 0;

  void increment() {
    count++;
    update();  // 수동으로 UI 갱신 알림
  }
}

// GetBuilder로 사용
GetBuilder<SimpleController>(
  init: SimpleController(),
  builder: (controller) {
    return Text('${controller.count}');
  },
)

Reactive vs Simple 비교

구분Reactive (.obs)Simple (update)
UI 위젯Obx()GetBuilder()
갱신 방식자동수동 (update())
메모리더 사용적게 사용
편의성높음보통

의존성 주입

DART
// 등록 방법 3가지
Get.put(CounterController());           // 즉시 생성
Get.lazyPut(() => CounterController()); // 처음 사용할 때 생성
Get.putAsync(() async {                  // 비동기 초기화
  final db = await Database.init();
  return DbController(db);
});

// 어디서든 가져오기 (BuildContext 불필요!)
final controller = Get.find<CounterController>();

// Bindings로 화면별 의존성 관리
class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => HomeController());
    Get.lazyPut(() => UserRepository());
  }
}

라우팅

DART
// 기본 이동
Get.to(() => const DetailScreen());

// Named Route로 이동
Get.toNamed('/detail');

// 이전 화면으로
Get.back();

// 화면 교체 (현재 화면 제거)
Get.off(() => const HomeScreen());

// 모든 화면 제거 후 이동
Get.offAll(() => const LoginScreen());

// 데이터 전달
Get.to(() => const DetailScreen(), arguments: {'id': 42});
// 받기
final id = Get.arguments['id'];

// 결과 받기
final result = await Get.to(() => const SelectScreen());
Get.back(result: '선택된 값');

Named Routes 설정

DART
GetMaterialApp(
  initialRoute: '/',
  getPages: [
    GetPage(
      name: '/',
      page: () => const HomeScreen(),
      binding: HomeBinding(),
    ),
    GetPage(
      name: '/detail/:id',
      page: () => const DetailScreen(),
    ),
  ],
)

// 동적 파라미터 받기
final id = Get.parameters['id'];

유틸리티 기능

스낵바, 다이얼로그, 바텀시트

DART
// 스낵바 (BuildContext 불필요!)
Get.snackbar(
  '제목',
  '메시지 내용',
  snackPosition: SnackPosition.BOTTOM,
  duration: const Duration(seconds: 3),
);

// 다이얼로그
Get.dialog(
  AlertDialog(
    title: const Text('확인'),
    content: const Text('삭제하시겠습니까?'),
    actions: [
      TextButton(onPressed: () => Get.back(), child: const Text('취소')),
      TextButton(
        onPressed: () {
          // 삭제 로직
          Get.back();
        },
        child: const Text('삭제'),
      ),
    ],
  ),
);

// 바텀시트
Get.bottomSheet(
  Container(
    padding: const EdgeInsets.all(16),
    child: const Text('바텀시트 내용'),
  ),
  backgroundColor: Colors.white,
);

GetxController 생명주기

DART
class MyController extends GetxController {
  @override
  void onInit() {
    super.onInit();
    // 초기화 (initState와 유사)
    fetchData();
  }

  @override
  void onReady() {
    super.onReady();
    // 위젯이 화면에 렌더링된 후 (1프레임 후)
  }

  @override
  void onClose() {
    super.onClose();
    // 정리 (dispose와 유사)
  }
}

GetX의 장단점

장점

  • 보일러플레이트가 매우 적음
  • BuildContext 없이 어디서든 사용 가능
  • 상태 관리, 라우팅, DI를 하나로 해결
  • 학습 곡선이 낮음

단점

  • 전역 상태에 대한 의존성이 높아져 테스트가 어려울 수 있음
  • 프로젝트 규모가 커지면 코드 추적이 어려워짐
  • Flutter 커뮤니티에서 아키텍처 관점의 비판이 있음
  • 암시적 의존성이 많아 리팩토링이 어려울 수 있음

면접 포인트: GetX를 사용하는 이유와 한계를 모두 설명할 수 있어야 합니다. "편리하지만 대규모 프로젝트에서는 Provider/Riverpod/Bloc을 선호하는 이유"를 아는 것이 중요합니다.


정리

  • GetX는 상태 관리 + 라우팅 + DI를 하나의 패키지로 제공합니다
  • .obsObx()로 반응형 상태 관리를 간편하게 할 수 있습니다
  • Get.to(), Get.back() 등 BuildContext 없이 라우팅이 가능합니다
  • 스낵바, 다이얼로그도 Context 없이 호출할 수 있습니다
  • 소규모 프로젝트에는 편리하지만, 대규모에서는 아키텍처 설계에 주의가 필요합니다
댓글 로딩 중...