mobile client/iOS

[iOS] 모바일 벨로그 서비스, 이지벨(EasyVel) 회고

hongjunehuke 2023. 10. 19. 18:49
728x90

개요

이지벨은 벨로그에 올라온 아티클을 모바일로 더욱 쉽게 즐길 수 있는 서비스이다. 벨로그 웹 서비스를 애용하던 나로서 티스토리나 미디엄과 달리 앱 서비스를 지원하지 않는 벨로그가 한편으로 아쉬웠다.
내가 개발해서 내가 쓰자는 생각으로 개발하게 되었다.
이지벨 서비스를 개발하며 iOS 개발에 흥미를 느낌과 동시에 많은 성장을 할 수 있었다.

주요 기능

1. 관심 태그에 따른 아티클 추천 기능

벨로그 아티클을 그냥 보여주는 것이 아닌 앱 유저가 저장해 놓은 키워드에 관련된 아티클을 최신순으로 보여준다. 관심 태그 리스트에서 관심 태그를 관리할 수 있다.

2. 벨로그 아티클 저자 구독 기능

벨로그 아티클 저자를 검색하거나 아티클을 읽으며 저자를 구독할 수 있다. 이후 구독한 저자의 글을 챙겨볼 수 있다. 구독자 리스트에서 구독자를 관리할 수 있다.

3. 벨로그 아티클 검색 기능

벨로그 아티클을 검색하여 읽어볼 수 있다.

4. 아티클 스크랩 기능

벨로그 아티클을 스크랩할 수 있다. 스크랩된 글들은 폴더에 저장되면 유저 임의로 폴더를 생성, 삭제할 수 있다.

개발 기간

2022/08 ~ 2022/11    1차 개발
2023/03 ~ 2023/07   2차 개발 & 출시
2023/07 ~ 2023/08   1.1.0 버전 업
2023/08 ~                   추가 개발 중


시연 영상

https://tv.kakao.com/v/441403127


앱 스토어 링크

https://apps.apple.com/kr/app/%EC%9D%B4%EC%A7%80%EB%B2%A8-easyvel/id6448953485


Github 레포 링크

https://github.com/SSUDevelog/EasyVel-iOS


문제 해결 및 구현 방법

1. 서비스 규모 확장에 따른 리팩토링

[문제]
기존 기획보다 많은 기능이 추가되며 초기 MVC 패턴으로 구현된 ViewController에 많은 로직이 추가되었다. 코드 가독성이 떨어지고 유지보수가 어려운 문제가 있었다. 기존 MVC 코드의 ViewController에 UI 구현 코드까지 합쳐져 있는 문제가 있었다.
[해결]
이를 해결하기 위해 MVVM 패턴 도입을 고려했다.
UI 구현 코드는 모두 View 클래스로 분리하고 ViewModel을 도입해 View에서 표시하는 데이터들을 ViewModel이 소유하도록 구현했다.
비즈니스 로직과 네트워크 통신에 의한 데이터 변경 또한 ViewModel에서 관리되고 View는 ViewModel의 데이터를 보여주는 역할만 하도록 구현했다.
결과적으로 ViewController의 책임을 나누고 가독성과 유지보수 측면에서 개선된 코드로 발전했다.

2. 데이터 옵저빙에 대한 여러 고민

[문제]
MVC에서 MVVM 패턴으로 변경하며 ViewModel에서 발생하는 데이터 변화를 View가 옵저빙할 필요성이 생겼다.
[해결]
초기 데이터 옵저빙은 RxSwift 없이 클로저와 didSet을 활용한 Input &Output 구조로 개발했다.
괜찮은 해결책이었으나 스트림을 더 편리하게 조작하고 싶었다. RxSwift 패키지 도입을 검토하며 여러 RxSwift의 merge, flatMap, combineLatest 연산자 등을 비롯해 스트림을 조작하는 방식을 학습하고 이를 적용했다.
패키지 종속성 측면에서는 부정적일 수 있지만 RxSwift를 통해 가독성 높고 명료한 코드를 구현했다.

3. 로컬 DB(Realm)으로 아티클 스크랩 기능 구현

[문제]
이지벨 서비스의 마지막 기능으로 벨로그 아티클을 스크랩할 수 있는 기능 추가를 논의했다.
서버 개발자의 사정으로 아티클 스크랩 관련 API가 빠르게 개발되지 않게 되었다. 하지만 서비스 출시 기간에 맞추기 위해서는 API가 나올 때까지 클라이턴트애서 기다릴 수 없었다.
[해결]
스크랩한 아티클을 다른 유저와 공유하는 기능이 없었기에 로컬 데이터베이스를 활용해 개발할 수 있다고 판단했다. 로컬 데이터베이스를 앱에 추가하며 앱이 무거워지고 사용자가 앱을 삭제했을 때 로컬 데이터베이스에 저장된 데이터도 삭제됨을 인지했다.
출시에는 스크랩 데이터를 로컬 데이터베이스에 저장하고 이후 API가 나오면 그때 서버 데이터베이스를 사용하는 방식으로 변경하기로 했다.
결과적으로 출시 예정일에 맞춰 출시할 수 있었고 이후 스크랩 관련 API가 나오며 해당 기능 코드를 수정했다.

4. 클라이언트 단의 웹 스크래핑 시도

[문제]
이지벨 서비스에서 제공되는 모든 아티클은 벨로그 웹 서비스의 데이터를 스크래핑한 정보들이다.
프로젝트 초기 웹 뷰에 의존하는 서비스가 애플 심사에 통과하기 어렵다는 말에 웹 뷰 사용 없이 벨로그 아티클의 정보를 스크랩하려 했다. 서버 개발자들과 웹 스크래핑의 방식을 논의했다. 서버, 클라이언트 모두 최선의 스크래핑 방식을 찾아오고 비교한 이후 결정하기로 했다.
[해결]
iOS 클라이언트 단에서의 웹 스크래핑 방법을 찾으며 여러 방법을 시도했다. URLSession을 사용해 웹 페이지의 html 데이터를 받고, html 파서로 SwiftSoup 패키지를 사용해 데이터를 추출하려 했다. 하지만 벨로그 아티클에는 동영상이나 코드가 자주 등장하며 html만으로 데이터를 가져올 수 없었다.
초기에는 벨로그 아티클의 글에 담긴 텍스트, 사진, 동영상, 코드 등을 스크랩해서 데이터 가공 이후 사용하려 했으나 서버 팀과 논의한 결과 해당 방법이 현실적으로 어렵다고 판단했다.
결국 벨로그 아티클 URL을 통해 웹 뷰로 벨로그 아티클에 접근하기로 했다.

5. 컬렉션 뷰와 테이블 뷰에 diffable datasource 도입

[문제]
애플에서 컬렉션 뷰와 테이블 뷰에 diffable datasource를 사용하기를 권장한다는 사실을 알게 됐다.
[해결]
datasource 대신 diffable datasource를 권장하는 이유를 먼저 찾아보았다. diffable datasource는 Snapshot 개념을 통해 데이터 처리를 단순화하고 성능 측면에서도 뛰어났다. 또한 테이블에 표시될 데이터 모델과 UI 관련 코드를 분리할 수 있었다.
diffable datasource를 사용하기 위해서는 테이블의 각 데이터에 고유한 식별자를 부여해야 했다.
서버에서 Response로 들어오는 벨로그 아티클 리스트 데이터는 인덱스가 꼬일 일이 없었다. 앱 유저가 아티클 리스트 데이터를 조작할 일이 없기 때문이었다. 하지만 벨로그 아티클 스크랩과 관련된 기능은 스크랩 아티클 리스트의 고유 식별자를 리스트의 인덱스로 할 경우 리스트 사이의 아티클을 삭제하거나 추가했을 때 인덱스가 꼬이는 경우가 발생했다.
이에 벨로그 아티클 스트랩에 사용되는 diffable datasource 각 데이터 식별자는 UUID를 사용하여 고유 식별자가 중복되는 문제를 해결했다.

6. 버전 관리 코드를 빼먹었다.

[문제]
이지벨 출시 전에는 전혀 생각하지 못했던 부분이다. 출시 이후 안정화와 성능 개선으로 버전 업을 하게 되었다. 이때 나는 버전 업 이전 버전의 사용자와 새로운 버전 사용자를 분기 처리하려 했다. 하지만 버전 분기 처리 코드는 첫 출시 당시에 포함되었어야 했다.
[해결]
버전 분기 처리는 앱 스토어 자동 업데이트가 꺼져있는 앱 사용자가 버전 업 이후 앱에 들어왔을 때 버전 업 사실을 알리고 앱 스토어로 유도하는 걸 말한다.
그렇지 않으면 자동 업데이트가 꺼져있는 유저는 계속해서 1.0.0 초기 버전에 머물 것이다.
버전 분기 처리 코드를 1.0.0 첫 출시에 넣지 못했던 나는 홍보 경로였던 인스타에 버전 업 관련 공지글을 쓸 수밖에 없었다.
다시는 버전 분기 처리를 잃을 수 없을 것 같다. 당시에는 우리 프로젝트에서 매우 큰 이슈였는데 지금은 추억이 되었다.

끝내며

iOS 개발을 시작하며 이지벨 프로젝트도 시작했다.
iOS 개발을 하며 공부했던 새로운 아키텍처나 기술을 적극적으로 적용한 프로젝트이다.
지금은 앱 스토어 뉴스 카테고리 52위까지 기록하고 지속적해서 유저가 유입되는 앱이 되었다.
적어도 내가 쓰는 앱을 만들자는 생각으로 시작했던 프로젝트를 여러 사람이 쓰며 긍정적인 피드백을 주니 감사할 따름이다.

728x90