THE STEADY COMPANY
TCA와 RIBs 사이, ComposableRIBs를 만든 이유 cover image

TCA와 RIBs 사이, ComposableRIBs를 만든 이유

View는 TCA로, 구성과 생명주기는 RIBs로 가져가려는 시도

2026-02-14 21:00

·
  • iOS
  • Swift
  • TCA
  • RIBs
  • AI
  • TDD

TCA와 RIBs 사이, ComposableRIBs를 만든 이유

TCA를 쓰면서 가장 자주 막혔던 지점은 내장된 Navigation 로직이었다.
특정 화면으로 이동하려면 결국 그 화면을 알고 있어야 하고, 그러려면 해당 화면의 Reducer까지 알아야 했다.
작은 앱에서는 큰 문제가 아니지만, 모듈이 늘어날수록 "누가 누구를 알아야 하는가"가 빠르게 복잡해졌다.

그리고 어느 순간 enum이 너무 커졌다.
Delegate, Child, Destination 같은 case가 계속 늘어나는데, 이걸 경계 단위로 깔끔하게 쪼개기 어렵다고 느꼈다.
특히 "이 case는 외부에 공개하고 싶지 않다" 같은 의도를 타입 레벨로 표현하기 어려운 점이 계속 아쉬웠다.


TCA가 불편해서가 아니라, 경계가 더 필요했다

TCA 자체는 정말 강력하다.
상태 변화는 명확하고, Effect도 예측 가능하며, 테스트 작성 경험도 좋다.
문제는 "기능 구현"이 아니라 "기능 간 결합"에서 더 자주 터졌다.

화면 전환이 깊어질수록 상위가 하위를 더 많이 알아야 했고,
모듈 경계를 지키려 해도 결국 구체 타입을 알아야 하는 순간들이 생겼다.
그 순간부터는 독립적인 모듈이라기보다, 서로를 많이 아는 모듈 집합처럼 느껴졌다.
결국 TCA만으로 모듈을 세우면 계약보다 구현이 먼저 드러나는 경우가 많았고,
그 지점에서 모듈 간 강결합이 자연스럽게 생겼다.


RIBs에서 배운 건 추상화의 힘이었다

이런 답답함을 느끼던 시점에, 다시 RIBs를 떠올렸다.
RIBs의 가장 큰 장점은 각 레이어가 추상화에 의존한다는 점이다.
Builder, Router, Interactor, Dependency 경계가 명확하고, 의존성 역전이 구조적으로 강제된다.

결과적으로 테스트 가능한 지점이 많아진다.
특정 모듈을 검증할 때 외부 모듈의 구체 구현을 몰라도 되고, 계약(Protocol)만 만족하면 된다.
이게 단순히 "예쁜 아키텍처"의 문제가 아니라, 실제 개발 속도와 안정성으로 연결된다는 걸 여러 번 체감했다.

다만 RIBs도 단점이 뚜렷하다.
프로토콜이 과도해지면 코드 점핑이 많아지고, 맥락 전환 비용이 커진다.
파일을 넘나드는 피로감은 분명히 존재하고, 러닝 커브도 낮지 않다.


그렇다면 둘 중 하나만 선택해야 할까

SwiftUI + MVI(또는 단방향 데이터 흐름)에서 오는 생산성은 무시하기 어렵다.
View를 그리는 속도, 상태 바인딩의 명확함, 프리뷰와 반복 개발 경험은 확실히 강력하다.
그래서 지금 시점에 UIKit + Rx/Combine 중심으로 완전히 되돌아가기는 쉽지 않다.

그래서 생각을 바꿨다.
"둘 중 무엇이 정답인가"가 아니라, "어디에서 어떤 장점을 가져올 것인가"로.

  • View, ViewModel(또는 Feature) 계층은 TCA의 장점을 적극 활용한다.
  • 모듈 구성, 생명주기, 의존성 경계는 RIBs의 장점을 가져온다.

이 아이디어를 실제 코드로 확인해보고 싶어서 시작한 것이 바로
ComposableRIBs다.


ComposableRIBs를 만들면서 가장 놀랐던 지점

원래는 가벼운 POC였다.
아이디어 검증만 하고 끝낼 생각이었는데, 생각보다 진행이 너무 잘됐다.

회사 서비스 개발에서는 "적당히 내가 직접 코드를 많이 쳐야 한다"는 압박이 늘 있었다.
AI를 활용하더라도 결국 손으로 세세하게 만지면서 안전장치를 거는 방식이었다.

그런데 ComposableRIBs는 접근이 완전히 달랐다.
정말로 내가 코드를 거의 작성하지 않았다.

내가 한 일은 크게 세 가지였다.

  1. TDD 기준을 먼저 제시한다.
  2. 내가 원하는 동작과 설계 의도를 명확하게 설명한다.
  3. 생성된 코드의 동작을 예측하고 방향을 계속 조정한다.

필요할 때는 Example 앱 생성도 요청했고,
내가 한 검증은 "코드를 다시 치는 것"이 아니라 "시뮬레이터에서 동작 확인"이었다.
몇 시간 안에 꽤 완성도 있는 형태로 프레임워크가 올라오는 경험은 솔직히 인상적이었다.


TDD + AI는 만능이 아니라 증폭기였다

확실히 TDD로 개발하니 일의 질이 올라간다는 느낌이 있었다.
적어도 "무엇을 보장해야 하는지"가 테스트 케이스로 남기 때문이다.

하지만 동시에 한계도 분명했다.
AI는 자신이 상정한 케이스를 중심으로 테스트를 만들기 때문에,
겉보기에는 정상처럼 보이지만 실제 운영 맥락에서는 빈틈이 생길 수 있다.

결국 중요한 건 도구의 성능 자체보다, 그 도구를 어떻게 지휘하느냐다.
어떤 실패 시나리오를 추가할지, 어떤 경계를 분리할지, 어떤 트레이드오프를 감수할지 판단하는 사람이 필요하다.


앞으로 더 중요해질 역량

나는 앞으로 개발자의 핵심 역량이 "구현 속도" 하나로 수렴하지는 않을 거라고 본다.
오히려 더 중요해지는 건 다음에 가깝다.

  • 문제를 구조화하는 능력
  • 검증 가능한 요구사항으로 바꾸는 능력
  • 테스트 케이스의 빈틈을 찾아내는 능력
  • AI에게 명확한 오더를 내리고 결과를 판별하는 능력

결국 미래에도 살아남는 개발자는
"코드를 많이 치는 사람"보다는
"정확한 판단과 오더로 시스템을 원하는 방향으로 끌고 가는 사람"일 가능성이 높다.

ComposableRIBs는 그 가능성을 확인해본 첫 번째 실험이다.
그리고 개인적으로는, 이 실험을 계속 이어갈 생각이다.