10년 된 인디 모바일 앱
안녕하세요, 저는 테일러 휴즈 입니다. 저는 소프트웨어 엔지니어입니다. 저는 Facebook, Google, Clubhouse 및 여러 스타트업에서 앱을 출시하고 팀을 구성했습니다.
우리 는 2013년에 Cluster 라는 사진 공유 앱을 만들었습니다 . 10년 전 앱스토어에 다음 달 출시됐다. 그 당시에 는 경쟁자가 많았고 매일 더 많은 제품이 출시되었습니다.
2015년까지 우리는 Cluster가 10억 사용자 제품으로 성장하지 않을 것임을 알아냈습니다. 우리는 백만 가지의 다른 전략을 시도해 보았지만 VC 규모의 수익에 필요한 수준까지 성장할 수 없었습니다. 하지만 앱은 서서히 새로운 사용자를 찾았고, 우리 가족 을 포함하여 앱 내에서 사랑하는 사람과 연결된 많은 사람들을 찾았 습니다. 그래서 우리는 그것을 계속 유지하기 위해 열심히 노력했습니다.
클러스터는 오늘날에도 여전히 살아 있으며 원래 경쟁업체의 대부분은 더 이상 존재하지 않습니다( Facebook Moments 및 Dropbox Carousel 과 같은 헤비 히터 포함 ). 400만 명이 넘는 사람들이 지난 10년 동안 플랫폼에서 거의 1억 5천만 개의 사진과 비디오를 공유했습니다. 장기 가족 및 친구 그룹이 10년 동안 앱에 머무르는 것을 보았고 수천 명의 장기 사용자가 여전히 거의 매일 앱을 사용합니다.
수년에 걸쳐 우리는 Cluster의 원래 소프트웨어를 유지하면서 앱의 핵심 부분을 천천히 업그레이드 및 변경하여 버그를 수정하고 비용을 절감하며 비즈니스를 유지하기에 충분한 돈을 벌기 위해 노력해야 했습니다. 사진첩 인쇄 방법 (2016년)과 앱스토어 구독 모델 (2022년)을 추가했습니다. AWS 계정 간에 마이그레이션하고 일부 서비스를 GCP로 옮겼습니다. 새로운 타사 SDK의 버그를 수정하고 6개 언어 모두에서 주요 플랫폼 업그레이드를 수행했습니다. (Python, Go, JavaScript, Swift, Objective-C 및 Java.)
그리고 많은 원본 코드가 남아 있습니다! 그러나 우리는 장기적으로 소프트웨어를 구축하는 데 있어 귀중한 교훈을 많이 배웠습니다.
우리가 있었던 곳, 그리고 지금 우리가 있는 곳
2013년의 원래 백엔드는 Postgres 데이터베이스와 함께 Django 1.4 를 실행하는 Python 2.7 모놀리식이었습니다. 당시 EC2의 사용자 지정 AMI에 패브릭 을 사용하여 git과 함께 배포했습니다. 지난 여름 저는 Python 3으로 업그레이드했으며 새로운 EC2 Graviton 인스턴스의 Elastic Beanstalk에서 실행하고 있습니다. 이제 CodePipeline으로 배포합니다.
모바일 앱의 경우 원래 iOS 앱은 iOS 6.0 SDK에 대해 빌드되었습니다. Android는 3.x, Honeycomb을 대상으로 한 것 같습니다. 나는 iOS 7 릴리스를 다루어야 했던 것을 분명히 기억합니다. 모든 것이 갑자기 평평해진 것을 기억하십니까? (그렇지 않을 수도 있습니다.) 현재 최소 SDK 대상은 iOS 14이며, Swift(원래 릴리스 날짜: 2014년 6월)와 Objective-C를 맞춤형으로 혼합하여 사용하고 있습니다. Android 앱은 뒤쳐져 있지만 가능한 한 빨리 스프루스로 돌아가겠습니다.
그래서 시간의 시험을 견뎌낸 것은 무엇입니까?
최적화는 유지 관리할 가치가 없는 경우가 많습니다.
가장 큰 교훈 중 하나는 지난 10년 동안 엔지니어로서 제 자신의 성장에 대해 말해줍니다. 참신함과 최적화는 내구성 있고 장기적인 코드의 적입니다.
2013년에 저는 인스타그램이 어떻게 여러분의 사진을 초고속으로 공유할 수 있었는지에 대해 들었습니다. 사진을 선택하고 필터를 사용하기 시작하면 이미 백그라운드에서 사진을 업로드하고 있습니다. 마지막으로 "포스트"를 누르면 쾅! 사진이 즉시 게시되는 것 같습니다. 얼마나 멋진 지.
그래서 물론 이것도 만들었습니다. 포스트를 누르기 전에 사진을 선택 후 업로드하는 시스템을 구축했고, 초기 포스트 를 더 빠르게 하기 위해 축소 된 이미지를 먼저 업로드하는 방식으로 레이어링하여 복잡하게 만들었습니다 . "Taylor가 새 사진을 업로드했습니다"보다 훨씬 나은 완벽한 통합 알림을 생성하기 위해 알림 시스템을 매우 복잡하게 만들었습니다. 모바일 연결에서 비디오 업로드가 더 빨리 완료되기 때문에 비디오 업로드를 즉석에서 인코딩 했습니다 . (영원히 지원하는 완전히 새로운 언어의 비용으로.)
이 모든 것들은 특히 내가 앱을 유지하는 사람이 아닐 때 유지하는 것이 정말 부담스러워졌습니다. 수년 동안 저는 고용주와의 이해 상충으로 인해 관여할 수 없었고 Cluster는 저처럼 그것을 좋아하는 놀라운 엔지니어들에 의해 유지되었습니다.
이 코드의 복잡성은 사용자에게 클러스터의 가치를 의미 있게 증가시키지 않았 으므로 결국 오류가 발생하거나 혼란스러워지면 고칠 가치가 없었습니다.
지나치게 복잡한 것, 가지고 있으면 좋은 것, 약간 화려하거나 맞춤형인 것 — 모두 찢어졌습니다.
업로더는 이제 기본입니다. "포스트"를 누르면 사진 업로드가 시작되고 원래 있어야 했던 것처럼 진행률 표시줄이 표시됩니다. 비디오는 전체 파일을 받은 후에 인코딩됩니다. 알림이 더 간단하고 경합 상태가 덜 발생합니다.
모든 주요 종속성은 코드의 종말을 재촉합니다.
개발의 세계에서 2013년 이후 어떤 변화가 있었나요? 별거 아니죠?!
Python과 모바일 플랫폼 자체가 아마도 가장 명백한 대규모 변화일 것입니다. 우리는 Python 2의 일몰을 보기 위해 살았고 8개 이상의 주요 iOS 릴리스를 거쳤습니다. 하지만 그 외에도 Go에 일부 코드가 있고 Node.js에 일부 코드가 있습니다. 두 코드 모두 2014/2015 이후 많은 중요한 변화가 있었습니다. (클러스터의 웹 앱 중 일부는 사용자 지정 Node.js 프런트엔드에서 실행됩니다. 다시 말하지만, 제가 무슨 생각을 했을까요?)
수년에 걸쳐 Python(Django 및 Celery 앱), Golang 및 Node.js와 같은 각 주요 언어에 대한 런타임 및 배포 프로세스를 다시 빌드해야 했으며 이러한 각 언어는 지속적인 유지 관리의 시간과 복잡성에 또 다른 차원을 추가합니다.
그러나 타사 종속성은 핵심 언어 및 프레임워크보다 훨씬 나쁩니다.
특히 인증 을 위한 타사 SDK 는 아마도 최악의 이동 대상이었을 것입니다. Google SDK는 Google+ SDK가 되었으며 현재는 Google 로그인 SDK입니다. Facebook SDK가 완전히 제거되었습니다. ( Facebook 세션 재팽창 ? 제가 제거했습니다.) Crashlytics는 Twitter Fabric이 되었고 이제 Google Firebase의 일부가 되었습니다. Apple은 끔찍한 바이너리 푸시 알림 서비스를 종료하고 현재의 이상한 HTTP/2 솔루션으로 대체했습니다. 우리는 Apple Sign-In을 구현해야 했는데 설명서가 놀라울 정도로 부족했습니다.
타사 통합은 최악입니다. 세심하게 제3자 파트너를 선택하십시오.
가장 적게 변경된 사항은 무엇입니까? " 지루한 " 기술. Postgres와 Redis는 계속 실행하기 위해 하이징크가 전혀 필요하지 않았습니다. Django 자체도 2022년 6월에 Django 1.5에서 Django 4.0으로 업그레이드했을 때 문제가 거의 발생하지 않았습니다. Django 뷰를 거의 건드릴 필요가 없었습니다! 대부분의 Django 변경 사항은 구성 및 라우팅에 있었으며 가장 어려운 한 가지는 고대 Django 1.5 세션 데이터를 최신 Django 4.0 형식으로 마이그레이션하여 마이그레이션 중에 사용자가 로그아웃되지 않도록 하는 것이었습니다.
클라이언트에서 핵심 ViewController 논리는 기본적으로 변경되지 않았지만 모든 새로운 타사 SDK로 인해 전체 로그인 흐름을 다시 작성해야 했습니다.
통합 테스트는 생명의 은인입니다.
클러스터에는 Google App Engine(!)의 로컬 인스턴스에 대한 호출을 포함하여 전체 스택 실행을 시도하는 매우 비싼 통합 테스트 세트가 있습니다. 테스트 도구는 말 그대로 로컬 Google App Engine을 실행하고 URL을 테스트 도구 모음과 공유하여 이에 대한 호출을 발행합니다. 바나나입니다.
이러한 테스트는 최신 표준으로 볼 때 느리고 끔찍합니다. 전체 제품군을 실행하는 데 몇 분이 걸립니다. 하지만 앱을 작동시키는 대부분의 핵심 코드 를 실행 하기 때문에 이 코드베이스를 계속 유지 관리하는 동안 그들은 절대적인 신의 선물 이었습니다.
Python 3 마이그레이션, 특히 str에서 바이트로의 전환은 큰 향상이었습니다. 그러나 그것은 또한 매우 간단했습니다. 2to3 를 실행하고, 이 거대한 테스트 모음을 실행하고, 오류를 수정합니다.
사실 마이그레이션 후 가장 많이 망가진 곳 은 테스트를 하지 않은 곳 이었습니다 . 물론! 테스트가 없었다면 완전히 망했을 것입니다.
여담: 장기적으로 구축 vs. MVP 출시
어떤 의미에서 장기적으로 구축하는 것은 가능한 한 빨리 MVP를 시작하고 반복하는 "린 스타트업" 유형의 목표에 반하는 것처럼 보일 수 있습니다. MVP는 해키하고 단순한 것을 시작하는 것을 의미하지만 장기적으로 빌드하는 것은 해키한 것을 시작하는 것과 반대인 것 같습니다.
하지만 두 가지 목표는 실제로 매우 잘 일치한다고 생각합니다.
- 실제적이고 긴급한 사용자 문제를 익숙한 방식으로 해결하는 간단한 솔루션을 구축하는 데 집중하십시오.
- 안정적이고 시간이 지나도 많이 변하지 않는 실전 테스트를 거친 소프트웨어와 플랫폼을 사용하세요.
- 실제적이고 긴급한 문제를 해결하는 데 절대적으로 필요한 경우에만 타사와 통합하십시오.
(확실히 다른 한 가지는 런타임 성능과 비용을 최적화하는 것입니다. 기본 엔드포인트에서 합리적으로 잘 실행되도록 앱을 조정하고, 자동 크기 조정을 구성하고, Glacier 파일 스토리지를 설정하는 등은 개념을 검증할 때 시간을 낭비할 일이 아닙니다.)
마무리
클러스터를 구축했을 때 2023년에도 여전히 실행될 것이라고는 상상하지 못했습니다. 또는 여전히 실행 중이라면 상당한 성공을 거두고 C++ 등으로 전체를 다시 작성했을 것이라고 생각했습니다.
하지만 앱은 살아남았고, 부분적으로는 앱을 계속 실행하는 간단한 코드의 견고한 핵심이 있기 때문이라고 생각합니다. 이제 원래 구현의 복잡성을 일부 제거했으므로 2033년에는 좋은 상태가 될 것이라고 확신합니다!
게시물이 좋아요? Twitter, @taylorhughes 에서 저를 찾으세요 !

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































