약 1년 간의 잠수…

업데이트:

약 1년 간의 잠수…

약 1년 간 블로그에 글 올리는 것을 중단했다. 그간 많은 일이 있었으나 또 별 일이 없기도 한 것 같았는데 그래도 블로그에 신경쓸 겨를이 전혀 없었던 것은 사실이다.

그동안 뭐 했니?

마지막으로 글을 쓴 게 거의 작년 12월달쯤 된다. 작년 날이 지금처럼 쌀쌀해질 때쯤 밤에 잠을 자다가 문득 떠오른 생각 ‘이거 이래가지고 장사가 될까?’ 하는 마음에 영 잠을 이루지 못했다.

그 다음날 나는 긴급히 회의를 열었다. 이런 서비스와 이런 컨셉으로는 우리에게 돈을 기꺼이 지불할만한 사람들을 모으기 어렵다고 나는 말했다. 그리고 초심으로 돌아가 다시 우리 서비스에 대해서 생각해보기로 했던 것이 기억난다. 그리고 몇 시간의 회의 끝에 서비스를 거의 전면 개편하기로 했다. 사실상 프로젝트를 엎었다고 볼 수도 있을 것 같은데 그래도 IYAGI라는 앱의 이름은 건졌으니 그게 아니라고 볼 수도 있을 것 같다. 어쨌거나 저쨌거나 그러한 서비스를 구현하기 위해서는 UX디자이너나 나나 역량이 매우 후달린다는 점을 알았고 한동안 역량을 쌓는 데 집중하자고 했다.

그래서 너는 뭘 배웠니?

사람이 뭔가를 처음 배울 때 맞닥뜨리는 가장 큰 문제가 뭐냐면 뭘 모르는지조차 모른다는 것이다. 그랬기에 사실 개판으로 짠 코드가 분명 나중에 커다란 기술적 부채(Technical Debt)로 돌아올 것임을 알면서도 그걸 어떻게 해결해야 할지를 도저히 알 수가 없었다.

Clean Architecture, Test-driven Development

우여곡절 끝에 알게 된 것은 소위 말하는 Architecture에 대해서 내가 완전 무지했다는 것이다. 이 아키텍처라는 것은 어떤 단위에서 보느냐에 따라 의미가 완전히 달라지지만 일단 당시에 나는 가장 기본적인 모바일 앱 아키텍처 패턴에 대해 지식이 전혀 없었다. MVC가 뭔지, MVVM은 또 뭔지 알게 뭔가? 하하… 그래서 나는 Reso Coder의 Flutter TDD Clean Architecture Course를 완전 열심히 들으면서 Clean Architecture는 물론이고 TDD까지 프로젝트에 적용하게 되었다. 아 물론, 이 과정에서 나는 IYAGI 프로젝트의 코드를 전체 삭제!! 하고 완전히 빈 main() 함수부터 새로 작성했다. 해당 코스를 듣고 이해하는 데도 시간이 좀 걸렸지만 코드를 바닥부터 새로 짜는 작업도 시간이 꽤 걸렸던 것 같다.

Bloc Pattern

그 다음에 깨달은 것은 이 프로젝트가 작은 프로젝트가 아니라는 것이었다. 사실 그럴만도 한 것이 음성 기반의 소셜앱인데 웬만한 메이저 소셜앱의 UX와 핵심 기능을 모두 구현하려고 하니 프로젝트가 작지 않았다. 당시에는 State Management Method로 Riverpod 라이브러리를 이용한 Change Notifier 패턴을 사용했다. 나는 우리 프로젝트가 작은 프로젝트라 생각했고 또 이전에 토이 프로젝트로 만들었던 Jailhouse Workout (참고로 작동은 잘 된다.) 앱에서는 잘 써먹었기에 나름 자신도 있었던 것 같다.
그러나 코드를 작성하면서 점점 상태관리가 어려워지자 결국 중대형급 프로젝트에 알맞다고 여겨지며 구글에서도 공식적으로 추천하는 Bloc 패턴을 사용하기로 했다. Bloc 패턴 자체는 전에 Redux와 함께 공부한 적이 있어 그렇게 어렵지는 않았지만 좀 더 미세한 수준에서 다루는 법, UI단에서 상태를 표시해주는 것과 부드럽게 연동하는 것, 또 각종 예외처리에 대한 Best Practices 등을 익히고 Riverpod으로 퉁쳤던 상태 관리 코드를 모두 Bloc 패턴으로 바꿔 작성하고 그에 맞게 또 Test도 작성하느라 여기서 또 시간이 좀 걸렸다 하하하…

Service, Architecutre Again

그렇게 약 반 년 정도를 그렇게 배운 것들을 토대로, 또 모르는 게 있으면 더 배워가면서 코딩을 했다. 기본을 잘 배워두니 다른 것들을 배울 때도 훨씬 이해도가 높았다. 나름 코드 내에서 기술적으로 피해가야 하는 부분들은 꼼수를 부려서 피해가기도 했다.(사실 좀 찔렸는데 Flutter Framework 내부 코드에도 그런 부분이 있긴 있더라 ㅋㅋㅋㅋ 코드가 100% 깔끔할 수는 없는 것 같다.) 약 한 달 전, 이 꼼수에 대해서 오랜만에 블로그 포스팅을 하려고 마음을 먹고 키보드를 두드리고 있었다. 코딩할 때는 그냥 그런가보다 하고 넘겼던 것이 글을 작성하려고 생각을 정리하다 보니까 이게 이래가지고 Scalability가 괜찮나? 하는 생각이 번쩍 들었다. 사실 DB 모델링과 관련된 부분이었는데 아무래도 소셜 네트워크를 관계형 데이터베이스로 나타내려고 하니 그 관계들을 모두 불러와야 할 때 그 쿼리의 길이와 JOIN 연산의 횟수 등을 생각하면 너무나 비합리적이었던 것이다. 그 비합리성을 백엔드 단에서 처리를 했어야 했는데 앱 코드 내에서 그걸 꼼수랍시고 자랑스레 처리하고 있었으니… 후우 ㅜㅜ 그런데 사실 웬만한 메이저 플랫폼 서비스들은 소셜 네트워크를 지원하지 않는가? 페이스북도 있고, 인스타그램도 있고, Linked In, 트위터, 웬만한 곳에서는 소셜 연결을 지원한다. 그럼 이 분들은 무슨 외계 기술이 있기에 이런 복잡한 소셜 네트워크를 데이터베이스에 구겨넣어서 효율적인 쿼리를 하고 데이터 관리를 하는 것일까? 의문은 곧 구글링이다. 구글링을 해보니 각 회사의 테크 블로그에서 간단하게, 혹은 좀 더 깊게 관련 아키텍처에 관한 포스트를 볼 수 있었다. 그 뿐 아니라 각종 써드파티 블로그들에서도 아키텍처를 추정(?)하거나 분석해서 설명해주는 포스트들이 있었다.
이런 저런 아티클과 포스트들을 읽고 내린 결론은 이 문제를 예쁘고 완벽하게 해결하는 하나의 방법은 없다는 것이었다. 페이스북 같은 경우는 기본적인 데이터 저장소는 MySQL을 사용하는 관계형 데이터베이스이고 실제로 대부분의 읽기 쿼리를 처리하는 부분은 Memcached를 활용한 인메모리 데이터베이스에서 처리했다. 물론 페이스북과 같은 거대한 서비스를 떠받치기 위해 인메모리라고는 하나 그 메모리의 크기가 엄청나다. 그러다가 최근에는 아예 인메모리 데이터베이스를 그래프 데이터베이스로 바꿔서 key-value 기반의 캐시가 아니라 그래프 형태의 캐시를 사용해 훨씬 효율적인 쿼리 성능을 내준다고 한다. 인스타그램도 옛날의 페이스북처럼 MySQL 기반에 key-value 기반의 캐시 데이터베이스를 쓴다. 이게 끝이 아니라 각종 미디어 파일의 Delivery 문제도 있고 어쨌든 간단하지가 않더라!
그래서 든 생각이 나는 앱을 하나 만드는 줄 알았는데 앱은 그냥 어떤 큰 서비스의 한 부분일 뿐이고 나는 지금 하나의 서비스를 만들어야 하는구나 하는 생각이 들었다. 나는 백엔드 구현에 관한 지식도 전무할 뿐더러 직접 내가 백엔드를 모두 구현할 수는 없다는 판단 하에 클라우드 서비스를 이용하면 좋겠다 싶었다. 우리 규모에 쥐꼬리만한 서버라도 하나 들여놓으면 서버 관리자며, 서버실 비용, 전기료 등등 초기 비용이 너무 많이 든다. 애플의 iCloud도 AWS에 의존하는데 우리라고 뭐 못할 거 있겠는가? 그래서 AWS Solutions Architect Associate를 공부하기로 했고 약 3주에 걸쳐 대부분의 내용을 공부했다. 시험을 통과할 정도로 꼼꼼히 공부했냐고 묻는다면 대답은 ‘아니오’다. 그러나 대략적인 내용은 숙지하고 있으며 어차피 실전은 암기가 아니라 응용에 있다는 것을 믿기에 바로 우리 서비스의 백엔드 아키텍처 구상을 해보려 한다.

앞으로…

생각을 글로 적을 때 훨씬 생각이 정리가 잘 되는 것 같아서 앞으로 백엔드 및 프론트엔드 아키텍처에 관한 고민을 블로그에다가 적어보려 한다. 또, 새로 배우는 기술들에 대해서도 조금씩 적어보려 한다. 아마 당분간 서비스 론칭을 위해서 모든 노력과 시간을 쏟아부을 것 같기 때문에 다른 언어나 프레임워크를 배울 일은 거의 없을 것 같고 대체적으로 백엔드나 Flutter에 관한 내용, 또 코드를 작성하며 느끼는 점들에 대해 올릴 것 같다.

댓글남기기