RIBs - 개념편

김재형_LittleTale·2025년 9월 10일

RIBs

목록 보기
1/4
post-thumbnail

들어가기에 앞서

이번편을 작성하는데 있어서
좀 시간이 필요했습니다....
Pin + Flex Layout 편을 작성하고 있었는데
Ribs 라는 친구가 생각보다 재밌어 보이드라구용
그래서 중간에 갈아타는 바람에 걸린 것두 있고
사용법 보다는 개념을 좀더 집중해서
이해도를 높히고 들어가고 싶은 마음도 컷기에
좀더 확실하게
알아보고 시도해보고 적용해보면서 시간이 걸렸던 것 같습니다...
자 시작해보죠.

RIBs가 왜 나온 것인가

MVC 를 유지보수 할때에 새로운 기능이 늘어날때마다 복잡성이 증가

  • 모듈 증가할 수록 테스트 복잡
  • ViewController 평균 코드 줄이 3000줄

VIPER 아키텍처란 무엇인가

  • View : UI
  • Interactor : 비즈니스 로직 + Network + Data Layer 수행
  • Presenter : UI의 상호작용 -> Interactor의 Data를 요청후 View 반영 담당
  • Entity : UI에 사용할 모델
  • Router : 화면 전환 로직

Viper 장점

  • MVC 대비 추상적
  • 각각의 책임 분담으로 인한 유지보수 도움
  • 테스트 용이 단 Presenter, Interactor 한

Ribs는 왜?

  • View, Business 트리와 밀접 -> 한쌍을 이루어야 함이 거슬림 -> 단독 노드 구성 가능하게
  • View 트리가 중심인점

VIPER 아키텍처

View <-> Presenter <-> Interactor -> Entity
            |-> Router

RIBs

Builder <-> Component
   ↓
┌──────────────────────────────────────────────┐
│ Router <- Interactor <-> Presenter <-> View  │
└──────────────────────────────────────────────┘

RIBs 의 정의

UI가 중심이 아닌 Business Logic 중심으로 하겠다!
State 변화 감지는 Business 단에서 관리 하겠다!
L "" 는 Scope ( 격리된거죠 ) 를 통해 관리 하겠다!
하나의 화면엔 여러 VC 가 이루어질 수 있다!

RIBs 필수적 요소

  • Router: Attach (뷰 추가) Detach (뷰 제거)
  • Interactor: 비즈니스 로직 -> Rib 들을 Attach, Detach할지 명령
  • Builder: Rib 생성

옵션 적인 요소

  • UI: Layout, Animation
  • Presenter: Translation Logic - Interactor <-> View

Scope

상속처럼 자식에서 부모의 내용을 받아서 사용 가능
AuthToken 같은거 생각
State관리는 이친구가 관리

  • Child Rib에서는 Parent Rib의 내용을 이미 가지고 있다고 가정

RIBs Life cycle

Attach, Detach 상태가 존재하는데
Router에서 애니메이션 설정이 필요함
Router에 Will, did 라이프 사이클을 추가하여 사용하면 편리

RIBs 단점

하나의 기능에 많은 클래수 수와 하나의 파일에 여러가지 클래스가 존재
Ribs를 하나의 프로젝트에 전체를 종속 시켜야 하는 문제
Ribs 내부에 RxSwift가 내장되어 있는데 이것 또한 문제

Parent 와 자식 간의 데이터 교환시

Interface Listener 사용하여 소통함

RIBs 생성 방법

  • Rib 생성

  • 부모의 Router에 프로퍼티 적용: 생성된 Child Builder 프로퍼티 추가

  • Dependency적용: Builder를 만들떄에 Componenet 주입
    컴포넌트는 부모의 컴포넌트 속성을 따름

  • Builder 에 변경된 Router 내용 적용

    RIBs 구성 상세

    Interactor

    비즈니스 로직을 포함
    해당 클래스에서 Rx 구독을 수행해야함
    상태를 변경하는 결정을 수행
    그외에 다른 Rib을 자식으로 연결할지 결정함

    Router

    Interactor의 요청을 수신 받음
    자식 Rib의 연결 혹은 분리

    1. 라우터는 자식 Interactor를 모의하거나 그 존재에 신경 쓸 필요 없이
      복잡한 Interactor 논리를 쉽게 테스트할 수 있게 해주는
      Humble Objects 역할을 합니다.
    2. 라우터는 부모 인터랙터와 자식 인터랙터 사이에 추가적인 추상화 계층을 생성합니다.
      이로 인해 인터랙터 간의 동기식 통신이 다소 어려워지고,
      RIB 간의 직접 결합 대신 반응형 통신을 채택하는 것이 용이해집니다.
    3. 라우터는 인터랙터에서 구현해야 하는 간단하고 반복적인 라우팅 로직을 포함합니다.
      이러한 보일러플레이트 코드를 제거하면 인터랙터의 크기를 줄이고
      RIB에서 제공하는 핵심 비즈니스 로직에 더 집중할 수 있습니다.

Router 종류

  • Router

    기본 라우터
    뷰가 존재 하지 않는 경우에 사용

     ViewableRouter<Interactable, ViewControllable>

    뷰가 존재할 경우에 사용해야하는 라우터
    즉 이 RIB이 ViewController를 가지고 있어야 함
    자식의 화면을 Present/ Dismiss 하거나 교체 하여야 함

      LaunchRouter<Interactable, ViewControllable>

    앱 시작 지점 전용
    AppDelegate 에서 Launch 로 앱을 띄울때 쓰이는 루트 라우터

Builder

RIB의 모든 구성 클래스, 각 자식에 대한 빌더를 인스턴스화

Presenter

비즈니스 모델을 뷰 모델로 변환 혹은
반대로 변환하는 상태를 저장하지 않는 클래스
해당 클래스는 생략이 가능하며 뷰모델 변환은 뷰컨트롤러 혹은 인터랙터 책임

View(Controller)

UI 업데이트 혹은 빌드

Component

Rib 종속성 관리
Rib을 구성하는 다른 유닛들을 인스턴스화 할 수 있도록 지원
외부 종속성에 대한 접근을 제공
부모 Rib의 컴포넌트는 일반적으로 자식 RIB의 빌더에 주입되어 자식 RIB이
부모 Rib의 종속성에 접근하도록 함

마무리 하면서

개념을 다루면서 제가 궁금했던 점을 정리한 내용입니다.
TCA 편을 보셨다면 꽤 비슷한 흐름이 보이실 겁니다.
어느 부분이냐 바로 트리 구조라는 흐름이 포인트일 것 같습니다.

TCA도 상위 Reducer 가 하위 리듀서를 감지할 수 있듯이
RIBs 도 그런 형태를 취합니다.

다만 RIBs는 제가 개인적으로 느끼기에는
많이 복잡한 구조를 가지고 있습니다.
다음편인 프로젝트 작성하기 편에서 느끼실 수 있을 것 같아요
모두 고생하셨구 다음편에서 뵙겠습니다....
감사합니다.

바로 프로젝트 코드를 보고싶다면
https://github.com/Little-tale/HowRIbs
를 참고해주세용 스타도 주시면 감사합니당

profile
IOS 개발자 새싹이, 작은 이야기로부터

0개의 댓글