brunch

You can make anything
by writing

C.S.Lewis

by 최우람 Jun 10. 2022

트로스트 앱 아키텍처 이야기 -1-

트로스트는 빠르게 성장하고 있는 멘탈케어 서비스입니다.

그렇기에 고객들의 니즈를 빠르게 찾고 개발하고 테스트하기 위해 2~3주 단위로 릴리즈 되고 있습니다.

서비스가 성장하는 과정에서 고객들의 니즈는 정말 다양합니다.

그것을 위한 많은 피처들을 우선순위에 맞춰 선정하고 개발하고 테스트해야 합니다.

고객은 결코 기다려주지 않기 때문에 릴리즈 주기는 짧아야 합니다.

물론 이렇게 빠르게 개발하는 와중에도 버그도 끊임없이 수정해야 하죠.


우리는 고객의 니즈를 찾아 빠르게 개발하고 테스트해보고 결과에 따라 움직여야 합니다.

만일 추가한 기능이 고객의 니즈가 아니라면 빠르게 걷어내기도 해야 하죠.

걷어내진 기능은 다음에 또 언제든지 재사용될 수 있고 좀 더 고객의 니즈에 맞게 고도화될 수도 있습니다.


즉, 트로스트 서비스에는 개발해야 할 것들이 산더미이고 또한 짧은 릴리즈 주기에 맞춰 빠르게 개발되어야 하며 기능의 추가 제거가 빈번히 일어날 수 있고 고도화는 항상 준비되어있어야 하는 데다가 안정적이어야 한다는 말이죠.

결국 프로덕트 전체가 엄청 바쁘단 이야기입니다.




그럼 앱 개발자가 많이 있겠네요?


아니요, 의외로 그렇지 않습니다.

물론 개발자가 많이 필요합니다. 하지만 대부분의 스타트업은 개발자 채용이 쉽지 않습니다.

이 글을 쓰는 시점 기준 트로스트 앱 개발자는 총 3명이 있습니다.

주니어 안드로이드, iOS 개발자 각 1명과 (지금은)안드로이드, iOS 모두 개발하고 있는 저.


사실상 앱 개발자는 안드로이드, iOS 플랫폼 별로 각 1.5명씩 있다는 이야기입니다.

위에서 언급한 해야 할 일에 비해서 턱없이 부족한 인원입니다.

그런데 어떻게 큰 문제없이 릴리즈 되고 있을까요?

Hoxy...?




물론 믹서기는 더 이상 가동하지 않습니다!!


흔히 믹서기라고 부르는 개발자를 갈아 넣는 시스템은 훌륭한(?) 아웃풋의 수단이죠.

물론 개발자가 행복해질 수 없는 최악의 수단입니다. 개발자의 피와 살로 만들어진 프로덕트...


사실 지금의 시스템을 정착시키는 과정에서의 시행착오로 몇 번의 믹서기 모드가 가동된 적은 있습니다.

개발자가 해야 할 일을 정해서 탑다운 방식으로 전달받아 정해진 기간 안에 개발해야 하는 기존 방식에서

일정 릴리즈 주기에 맞춰 개발자가 직접 일정 산출하고 아이템을 픽하여 주도적으로 개발하는 스프린트 방식으로 바꿨을 때, 그리고 아키텍처가 아직 확립이 되어있지 않고 스프린트 시스템도 서툴렀을 때.

어쩔 수 없이 믹서기 모드가 가동되기도 했었습니다.


하지만 우리는 일하는 구성원들이 행복하게 일할 수 있게 계속 고민했고 한 가지 방식만 고집하지 않고 우리에게 맞도록 계속 고치고 개선하면서 어느 정도 정착이 돼서 개발자가 믹서기를 가동할 일이 없을 것이라 생각이 듭니다.

물론 앞으로도 가동할 생각은 없고요!




전 좀 더 개발자스럽게 이 문제를 풀고자 했습니다.


예전 안드로이드와 iOS가 각각 Java와 Objective-C로 개발되던 시기에 두 플랫폼은 너무나도 달랐습니다.

그나마 대중적이던 Java에 비해 Objective-C의 독특한 문법은 기상천외하게 느껴지기까지 했을 겁니다.


하지만 Kotlin과 Swift로 상당 부분 넘어간 지금 많은 앱 개발자가 느꼈을 겁니다.

언어적으로는 둘이 이제 꽤 비슷해졌다. 라는 걸요.


게다가 이미 안드로이드와 iOS 아키텍처는 정말 많이 닮아가고 있습니다.

우버의 RIBs 같은 대중화된 아키텍처는 이미 두 플랫폼 모두 지원합니다.

MVP MVVM 같은 아키텍처는 이미 안드로이드도, iOS도 보편화되어있습니다.

이제 안드로이드에서 설계한 아키텍처를 iOS로 구현하는 것은 별로 어려운 일이 아닙니다.

물론 반대도 마찬가지입니다.


단순히 언어만 닮아진 것이 아닌 언어 레벨에서 지원하는 기능들도 닮아가고 있습니다.

Kotlin(Java)의 Lambda와 Swift의 Closure는 물론 표준 라이브러리에서 제공하는 고차함수(Higher-Order Function) 역시 교차하여 읽는데 문제가 없습니다.

태생은 많이 달랐던 Kotlin의 Coroutine, Swift의 Combine조차 Flow가 나오면서 많이 닮아가고 있습니다. 물론 그 둘을 비교하기 이전에 리액티브 프로그래밍에 있어서는 Rx가 이미 예전부터 두 언어 모두 완벽히, 강력하게 지원하고 있죠.


아마 이쯤 되면 당연히 떠오르는 생각이 있을 겁니다.





두 플랫폼의 아키텍처를 완전히 통일시킬 수 있겠는데?

이 생각을 시작으로 트로스트는 자체 아키텍처를 만들어서 적용하였습니다. 이 아키텍처는

MVVM 형식으로 뷰와 뷰모델은 바인딩으로 동작합니다.

View, ViewModel, Interactor, Repository 레이어로 분리됩니다.

각 레이어는 인터페이스를 통해 의존성이 역전되어있고 주입으로만 구성될 수 있습니다.

각 레이어는 Rx를 이용하여 데이터를 전달합니다.

플랫폼 의존성은 철저하게 View레이어에서만 처리되고 로직 레이어는 플랫폼 의존성이 존재하지 않습니다.

로직 레이어에서 플랫폼에 의존된 기능을 사용할 경우 인터페이스를 통해서만 접근할 수 있고 실제 객체는 View 레이어에서부터 주입받습니다.

각 레이어는 Mock으로 구성된 하위 레이어를 이용하여 독립적으로 유닛 테스트가 가능합니다.



그리고 안드로이드, iOS 개발자는 서로 코드를 보고 베낄 수 있습니다.

(View 레이어 제외)

물론 단순히 베끼는 것이 아닌 함께 최적의 로직을 구상하고 한 명이 그것을 코드로 작성하고 공유한다는 것입니다.


프로세스를 간단히 설명해보겠습니다.

만약 한 스프린트에서 2개의 메인 피쳐를 개발해야 한다면 개발에 앞서 서로 2개의 피쳐 구현 방향에 대해 충분히 이야기합니다.

충분한 토의를 통해 큰 그림이 정해졌다면 안드로이드, iOS 개발자는 각각 하나씩 맡아 개발합니다.

본인의 개발이 끝나면 상대방이 작성한 코드에서 로직부(뷰모델, 인터렉터)를 그대로 베낍니다.

그리고 View를 본인의 플랫폼에 맞게 구현하여 로직부와 연결하고 테스트 코드도 작성합니다.


이런 방식으로 서로 다른 플랫폼임에도 병렬로 개발이 가능해지고 마치 각 플랫폼별로 두 명 이상 있는 효과를 낼 수 있게 됩니다.

이게 말도 안 되는 이야기라고 하실 수 있습니다. 그래서 로직부 코드 몇 개를 비교해서 보여드리겠습니다.


실제 트로스트 안드로이드(좌)와 iOS(우)에서 쓰이고 있는 뷰모델 클래스 코드입니다.
실제 트로스트 안드로이드(좌)와 iOS(우) 뷰모델의 코드 중 바인딩 코드 일부입니다.

위 코드를 보시면 실제로 매우 닮아있고 거의 옮겨놓은 수준이라고 느낄 수 있을 것입니다.

이렇게 앱 통합 아키텍처를 통해 부족한 인력을 최고의 효율로 끌어올릴 수 있었습니다.





하지만 처음부터 쉬웠던 것은 아닙니다.

제약사항이 굉장히 많았습니다.

우선 가장 중요한 것은 주니어 개발자들이 쉽게 따라올 수 있을 정도의 난이도여야 했습니다.

주니어 개발자는 아키텍처의 본질과 목적을 명확히 이해해야 합니다. 그저 돌아가기만 하는 코드를 작성하는 것이 아닌 개발에 앞서 설계부터 항상 생각하고 고민할 수 있는 기반 지식을 가진 개발자로 성장시키고자 했기 때문입니다.

그리고 고객들의 니즈를 위해 개발해야 할 것들은 끊임없이 나왔기에 아키텍처로 인해 개발 속도가 늦어지면 안 됐습니다.

물론 저는 개발도 하면서 아키텍처를 가르치고 가이드하는 시간도 내야 했습니다.

새 아키텍처로 처음부터 만들 수 있는 시간은 없기에 기존 코드에 새 아키텍처를 올릴 수 있어야 했고 기존 코드와 호환되어 제품의 동작에 문제가 없어야 했습니다.

이게 모두 충족되면서 두 플랫폼 간에 로직 코드가 보고 베낄 수 있을 정도로 비슷한 구조여야 했죠.


과정은 결코 쉽지 않았으나 주니어 개발자분들이 굉장히 적극적으로 잘 따라와 주고 빠르게 성장하면서 무사히 안착시킬 수 있었습니다.



다음 글에서 이 아키텍처에 대해 자세히 이야기해 보겠습니다.

[다음 글 보기]




브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari