학동역으로 출퇴근 하던 기억이 꽤나 벌써 흐릿하다. 성인이 되고서는 근 몇년정도는 바로 어제일 같이 느껴지곤 하는데 고작 1년 전인데도 가물가물하다니 이런 건 다소 놀랍다. 아무래도 일하던 회사 근방 환경을 갈 일이 없어지다보니 리마인드될 기회가 확 줄어든 탓이 아닐까 싶다. 내게 있어선 꿈과 같은 기회였기도 하고, 차후 스스로를, 그리고 함께 일해나갈 동료와 제품을 위해서 도미노에서의 시간을, 어떤 일을 할 수 있었고 어떤 면에서 아쉬움이 남는 지 정리해보고자 한다.

2023년초 애플 개발자 아카데미가 막 끝난 후 취업활동에 매진했다. 개발과 관련이 적은 대학으로 돌아갈 바엔 지금 취업을 해보는 것도 좋은 시도일 수 있겠다는 생각이었다. 당연히 iOS 개발자로 구직 활동을 진행했고 많은 지원 끝에 AR 관련 플랫폼 회사에 채용이 결정되었다. 내가 iOS 개발을 주로 삼았던 이유 중 하나는 언젠가 올 애플의 AR 플랫폼에 대한 기대가 있었기에 의미있는 선택이었다. 이 시점에서 도미노는 서류만 통과한 상태였는데, 사실 코딩 테스트도 스스로 만족하지 못한 성과였던 터라 기대를 하고 있지 않았다. 그런데 면접 연락이 와서 상당히 놀랐던 기억이 있다. 아무래도 뒷배가 있던터라 면접도 편안히 볼 수 있었고, 이런 부분이 오히려 좋게 비춰졌다는 생각이 든다. 도미노는 이전부터 앱 아이콘이나 디자인에서 미적인 감각이 뛰어나다는 생각이 있어서 따로 자산 관리나 주식, 코인을 하지 않음에도 앱을 사용해본 경험이 있었고, 이런 앱을 만드는데 기여할 수 있다는 생각에 설레여 아쉽게 이전 회사에 입사 이전에 죄송스럽지만 포기 연락을 드리고 도미노에 입사하게 되었다.

나에게 있어서 회사에서 일하는 경험 자체가 정말 소중했다. 나는 혼자서 대부분의 시간을 개발해왔고, 아카데미에서 수많은 팀프로젝트를 진행해왔지만 일회성인 경우가 대부분이었다. 그러나 이곳에서 유기적으로 돌아가는 제품의 업데이트, 관리를 체험하고 경험할 수 있다는 것이 값진 경험이었다. 팀에서는 모든 구성원이 출근 이후 짧은 스크럼과 각 팀 별로 모여서 각자 오늘 개발할 내용과 서로 필요한 정보를 공유하는데, 적극성이 없다면 개발자로서 성장하기 어렵다는 걸 크게 체감했다. 내 스스로가 꾸준히 학습하고 찾아보고 이걸 타인에게 공유하는 과정을 거쳐야 팀을 위해 발전할 수 있다는 걸 세삼 다시 깨닫게 되었다. 핀테크 앱이다보니 투자 관련 용어를 공부할 필요성도 있었다. 실현수익, 환차익, 섬머타임, 각 장마다 다른 휴장일이나 이름도 비슷한 ETF, ETN, ETC 등등.. 스타트업으로 팀의 초기 구성원 분들이나 나중에 팀에 들어오신 분들의 대다수가 이 투자 분야의 관심이 많거나, 이 방면에서 성과를 내신 분들이 많았다. 이런 면에서는 스스로 난처한 부분이 있었다. 나의 경우, 도미노라는 앱의 디자인적인 부분이 이 팀에 관심을 가지게 된 주된 요인이었으니까.. 그렇지만 지금와서 돌이켜보면 대표님과의 면접 때도 그렇고 내게 바란 건 내가 할 수 있는 부분을 보고, 믿고 채용한 것일텐데 다른 부분을 따라잡기에 급급해서 내게 기대한 역할을 제대로 수행하지 못하지 않았나 싶은 생각이 들기도 한다.

팀원분들도 굉장히 뛰어나신 분들이 많았다. 각 분야에서 다들 놀라운 커리어를 보유하신 분들 투성이었고 다들 굉장히 인격적으로도 나보다 훌륭하신 분들이 너무나 많았다. 특히 iOS 같은 팀원분들의 경우, 감사함이 너무 크다. 당시 아카데미 기준에서 높은 실력을 가졌다는 오만함으로 초반엔 잦은 실수도 많았다. 특히나 Git에서 메인 브랜치를 건드는 사고라던가.. 아찔한 기억들이 너무 많은데, 다른 팀원분들이 아무렇지도 않게 커버해주셔서 정말 감사함이 많이 남는다. 이 글을 보시게 될 일은 없으시겠지만 다시 한 번 죄송하고 감사드립니다..

코드면에서도 놀라움이 많았다. 적응을 위해서 초반에는 간단한 QA 티켓들을 해결하도록 역할을 맡기셨는데 각 코드를 볼 때마다 경외감이 들게 만들었다. 특히 2020년 iOS 개발에 입문하면서 SwiftUI 쪽에 정감이 더 가는 나로선 UIKit 뷰 셋업 코드를 적절한 프로퍼리 래퍼 처리와 result builder 그리고 뷰 extension을 활용해 마치 SwiftUI처럼 선언형으로 UI를 구성할 수 있다는 점이 굉장히 매력적이었다. 적절한 디자인 패턴을 위해 ReactorKit을 사용하는 코드도 처음 맛보게 되었는데 둘 다 단방향 데이터 흐름 상태 관리 패턴 라이브러리라는 공통점이 있어 이 경험이 차후 TCA를 사용하는데 있어서도 도움이 많이 되었다. 특히나 action 네이밍을 직관적으로 작성해 코드흐름을 읽고 이 함수가 어떤 유저 인터렉션에서 의도되었는 지 알기 쉬웠고 실제 repository를 건드는 주 로직 코드는 reactor 내부에서 reduce함수 하나만 보는 점이 깔끔하고 로직의 중복화를 줄일 수 있다는 게 굉장한 이점으로 다가왔다.

얼마뒤 내가 처음으로 큰 테스크를 맞게 된 건 관심 탭 개편 작업이었다. 새로 들어오신 디자이너 분께서 디자인을 담당하셨고, 그 덕에 다소 실험적인 기믹이나 인터렉션이 많았는데 이런 일을 좋아하고, 해내고 싶었던 나로선 다소 의욕에 가득차 초기 회의에서 일단 다 구현해보겠다고 말했다. 근데 이건 착오였는데 안드로이드 쪽 구현에 대해서도 생각을 해야했고 정해진 기간동안 가능한 지도 고려해야했다. 당시 회의에선 베테랑이셨던 안드로이드 개발자분께서는 걱정되는 눈빛으로 오케이를 주셨고 일단 그렇게 작업에 들어가게 되었다. 그런데 생각하지 못했던 건 도미노의 경우, CollectionView 처리를 IGListKit 프레임워크에 의존하고 있었는데 인스타그램에서 만든데다가 깃헙 스타도 10k가 넘어가는 지라 이전엔 굉장히 잘 쓰였던 iOS 라이브러리였던 것으로 보인다. (실제로 코드를 볼 때 DiffableDataSource와 많이 닮은 점이 보여서, RxSwift - Combine 관계처럼 애플이 어느정도 참조할 정도로 인기 있었던 것일까 싶었다.) 다만 현재 기준에서는 iOS 13 이후 CollectionView를 순정으로 써도 큰 문제가 없을뿐더러 나는 그런 환경이 익숙했기 때문에 조금 당황스러운 상황이었다. 게다가 셀과 리스트가 대부분의 화면에서 보여지는 도미노 앱 특성상 ReactorKit과 묶여 하나의 패턴화된 터라 이 틀을 벗어나서 내가 편한 방식으로 구현하는 게 맞을 지 고민이 많았다. 특히 IGListKit 내부 코드를 보려다 Objective-C를 보고 굉장히 당황하기도 했고.. 결국은 피처 하나를 잡고 개발하는 첫 경험이기도 했고 관습을 배워야 정확히 새로운 기술로 교체해야 할 때 이유를 명확히 제시할 수 있을 것 같아 IGListKit을 사용하기로 했다. 장기적으로 보았을 때 다른 피처를 개발할 때나 기존 코드를 유지보수 할 때 IGListKit에 익숙해져 옳은 판단이었다고 생각하지만, 당시에는 꽤나 곤란했다. 시간을 맞춰야하는 상황에서 새로운 기술을 습득해야했으니까. 특히 구현 요구사항 중에 reordering 처리가 굉장히 곤란했는데, 특히나 섹션을 넘나드는 셀의 이동이 더더욱 곤란했다. CollectionView delegate 메소드 대신 Section Controller 델리게이트로 처리했어야하는데 막상 이렇게 구현했더니 중요한 섹션간 이동은 대응이 안되서 관심그룹 간 종목 이동이 안되는 참사가 일어났다. 근 몇일간은 퇴근 이후에도 밤을 새가며 작업하느라 진을 뺐었는데 결론은 데이터 자체는 관심그룹 리스트 안에 종목 리스트라는 2차원 배열로, 실제 cellForItem 로직에선 해당 배열을 기반으로 플랫하게 펴줘서 하나의 단일 섹션 내에서 적절히 헤더 - 종목 셀들이 보여지도록 구현했다. 결국 실험적인 인터렉션 몇 개는 드랍되었고 업데이트 일이 조금 딜레이 되서 굉장히 죄송스러웠던 기억이 있다. 다만 깊게 파가며 해결하려는 마인드와 기획 의도에 맞는 인터렉션과 디자인을 구현하려는 의지가 좋은 결과를 가져다 준 점도 있다. IGListKit의 경우, 셀 이동 애니메이션을 계산할 때 셀의 데이터가 ListDiffable이라는 프로토콜을 채택하도록 해서 스냅샷 비교를 통해 자연스럽게 애니메이션이 이루어지도록 했는데 그런데 앱의 대다수 데이터는 값 타입인 구조체를 주로 사용했고, IGListKit에게 던져주기 직전에 ListDiffable을 채택한 클래스 타입으로 변환할 수 있는 Diffable 프로토콜을 채택해서 사용했다. 다만 이 과정에서 구조체의 Equatable이나 Hashable한 고유성을 일반적인 박스 클래스로 넘어가며 잃었고 자연스러운 인터렉션이 나타나지 않게 됨을 확인할 수 있었다. 이를 수정하며 앱 전반에 걸쳐 셀 애니메이션이 제대로 이루어지도록 개선하게 되는 결과를 얻을 수 있었다.

데모 모드 구현은 당시엔 꽤나 난감했지만, 도미노 앱에서 좋아하는 인터페이스 중 하나다. 앱을 로그인하지 않으면 하단의 큰 로그인 CTA 버튼이 나타나고, 앱에선 각종 샘플 데이터를 바탕으로 앱에서 어떤 기능이 가능한 지 오랜시간 앱을 쓰며 개인 데이터가 쌓이지 않았더라도 쉽게 확인할 수 있어 접근성을 높여준다. 하단 CTA버튼을 비롯한 UI 요소를 중점적으로 처리했는데, 기획에 맞게 일반화하는데 난관이 많았다. 특정 뷰는 데모모드에서 보여줘도 되고, 특정 뷰는 데모모드에서 볼 수 없다. 각 뷰마다 시트와 웹뷰 처리도 필수였고 꽤나 골치아픈 작업이었다. 도저히 답이 안나오던 찰나에 팀의 리더 개발자분께서 도움을 주셨다. 기존 statsig 이벤트 처리나 텍소노미, 팝업 처리를 위해 특정 싱글톤 클래스에서 뷰컨트롤러가 init 될 시 해당 뷰 컨트롤러의 타입값을 얻도록 하는 클래스를 확장시켜, 각 화면 이동 시마다 적절히 대응할 수 있도록 함으로서 해당 피처를 구현할 수 있었다. 보여져야 할 화면의 경우, result builder를 이용해서 특정 배열 하나만 참고하면 데모모드 UI를 적절하게 보여줄 수 있도록 구성할 수 있었다. 또한 다른 난관은 스크롤 시 하단 숨김 처리였는데 스크롤 가능한 뷰컨트롤러의 경우, Scrollable 자체 프로토콜을 채택하도록 하고, 각 화면에서 스크롤 정보 또한 적절히 앞서 언급한 싱글톤 클래스에서 구독할 수 있도록 함으로서 해결할 수 있었다.

일시적인 이벤트 페이지나 빠른 피처 테스트를 위해서 팀에선 웹뷰를 활용할 일이 많았는데 웹뷰와 네이티브 간의 연동 작업은 필수였다. 담당했던 혜택 탭의 출금 화면에서 계좌를 입력한다던가, 행운빙고와 같이 현금전환이 가능한 포인트를 얻을 수 있는 미니게임을 연동할 때, 실제 돈이 오갈 수 문제였기 때문에 더더욱 조심할 필요성이 있었다. 해당 처리를 위해 여러 개의 독립적인 미들웨어 컴포넌트를 구현하여, 웹페이지 상 게임 결과 및 진행 처리, 또는 계좌 입력 등의 API를 웹 단에서 던져주면 해당 JavaScript 이벤트와 HTTP 요청 헤더에 앱 버전 등의 중요한 메타데이터를 주입하는 작업을 분리하고, 이를 통해 각 기능별 로직을 캡슐화하여 유지보수성을 높일 수 있었고, 향후 기능 확장에도 유연하게 대응할 수 있었다.

슬슬 일에 익숙해지게 될 시기 쯤. 사내에선 불안한 이야기가 돌기 시작했던 것 같다. 구체적으로 언급하기 어렵지만, 건너 듣기로는 다음 투자와 관련된 문제로 짐작되었다. 사실 도미노의 주 목표는 마이데이터를 앱에 적용시킴으로서 더 이상 수동 자산 기입 방식에서 벗어나는 것이었지만, 여러 절차로 인해 계속해서 늦어지고 있는 상황이었고 이것이 주된 원인인 듯 했다. 그리고 얼마 안가 런웨이 기간이 생각보다 길지 않음을 공유받게 되었고 사내 방향성이 그 때부터 조금 달라지기 시작했다. 캐시나우도 그 일환인데 최대한 자금 확보에 도움이 되는 서브 프로젝트를 진행해보자는 결과물이었다. 나를 포함해 2명이서 빠르게 1달 이내 만보기 앱테크 앱인 캐시나우를 갑작스럽게 개발하기 시작하게 되었다. 빠른 MVP 출시를 위해 SwiftUI와 ReactorKit으로 비교적 익숙한 방식인 TCA를 채택해 구현했으며 미리 시장반응을 보기 위해 개발이 이미 완료된 안드로이드 앱을 금새 따라잡고 출시할 수 있었다. 그 이후부터는 내가 전담해서 개발하게 되었는데 책임의 막중함을 배울 수 있었다. 유저 피드백 하나 하나가 송곳처럼 다가왔고, 버그라도 터질 시 그건 내 책임이라는 뜻이었다. 개발하며 항상 코드의 주인의식을 떠올리고자 했던 기억이 있다. 애드 네트워크 적용이나 Firebase Distribution을 통한 스테이징 앱 관리나 fastlane을 직접 세팅하는 등 앱의 주된 책임자가 아니라면 해보지 못했을 경험들을 쌓아본 것도 지금 생각해보면 좋은 기회였던 것 같다.

얼마뒤 팀의 제일 중요한 목표였던 마이데이터 사업자로서 통과되었고, 팀은 크런치 모드로 들어갔다. 그와중에 경이로웠던 건 우리팀의 경우 리딩해주셨던 개발자분께서 속도에 잡아먹힐 듯 한데 리팩토링과 개선을 꾸준히 챙기며 가져갔다는 점이다. 앞서 시간에 쫒겨 앱을 만들던 나로선 반성이 되는 부분이었다. 마이데이터를 적용하게 되면서 코드 전반을 드러낼 필요성이 있었고, 비즈니스 로직 뿐만 아니라 대다수의 화면도 바뀌는 UI 파트도 마찬가지였다. 덕분에 대부분의 UI 구현부가 SwiftUI로, 비동기 처리를 RxSwift와 Combine이 혼재하는 구도에서 Actor와 async/await 문법을 사용하는 쪽으로 개편되었다. 나는 캐시나우와 반반 돌아가며 마이데이터 작업을 도왔는데 가장 기억의 남고 뿌듯했던 작업은 홈 초기 로딩 개편 작업이다. 이전에도 스크럼을 할 때면 지라 티켓 하단부에 홈 로딩 개선 작업 테스크가 오랜동안 묵혀있었는데, 마이데이터 개편 작업에서 오히려 더 느려지는 모습을 보여, 이 부분을 해결하는 것이 시급했다. xcode의 instruments 중 time proflier와 POI를 이용해서 리팩토링 진행부와 레거시 파트가 난립중인 코드 사이에서 중복호출을 찾아 개선할 수 있었다. 사실 깃헙 풀리를 올릴 때 다른 두 가지 정도 원인을 찾아 자세히 분석했던 기억이 있는데 하도 바쁠 시기라 제대로 정리하지 못하고 넘어가 좋은 성장과정이자 경험이었음에도 기억에 일부가 훼손되어 떠올리지 못하는 점이 정말 아쉽다.

테스크가 해결되면 다른 테스크가 몰려오는 끝도 없던 시기가 정말로 끝나고 놀랍게도 제 시기에 마이데이터가 적용된 도미노 2.0 버전을 낼 수 있었다. 실제 내 마이데이터를 연동하고 화면에 내 자산이 나타날 때의 안도감과 뿌듯함이 기억에 남는다. 다만 계속해서 여러 예외 케이스들과 QA들은 여전히 몰려왔고, 그 작업은 마이데이터 핵심 로직을 담당한 팀 리딩 개발자분의 몫이 많았다. 나는 팀의 관심에서 벗어난 캐시나우 업데이트 작업들과 도미노 QA를 보며 내가 할 수 있는 부분을 잡아 해결하는 식으로 최대한 거들어보는 중이었다. 이 시점에서 내 미래가 어느정도 짐작가는 부분이 있었고, 오히려 나쁜 무언가가 온다는 암시를 느낀 채 마음 한 켠에 대비하고 있었던 듯하다. 겨울날 밥을 먹고 조용히 회사로 올라가는 길에, 회사의 좋지못한 상황으로 각 팀의 리드 개발자를 제외한 나머지 인원들의 전원 해고 소식을 듣게 되었다.

사실. 아쉬움이 많이 남는 첫 회사생활이다. 적응의 파도에 갖혀 조금 내 팀원의 1인으로서 제 역할을 해나가고 있음을 느낄때 상황이 이렇게 된 것들이 아쉽다. 관계적인 측면에서도 아쉬움이 많이 남는다. 좋은 사람들 너무 많았고 그럼에도 그들이 내게 배려해주고 알려주고 도와주는 것만큼, 보답해주지 못했다는 마음이 크다. 개발자로서가 아닌 사람 대 사람으로서의 아쉬움이다. 성장과 경험을 거쳐 언젠가 내가 더 강한 사람이 되었을 때 현장에서든 행사에서든 웃으며 다시 마주할 수 있길 기원한다.