트래블튠 트러블슈팅

hyeseong
7 min readOct 23, 2023

--

Sesac iOS 개발자 교육과정을 2023.07.17 부터 시작해서 하루하루 수업 진도를 놓치지 않기 위해 발버둥 치다 보니 어느새 개인 프로젝트 개발 기간이 되었다.

개발 기간은 약 한달.

어떤 앱을 만들지 정한 후 관련 앱과 디자인 그리고 필요한 기능을 정리했다.

개발 목표는 MVVM 아키텍처를 적용시켜서 최대한 가벼운 ViewController 를 만들자! 라는 목표로 시작했다.

메인 기능으로는 크게 오디오 재생, 나만의 이야기 (좋아요 기능), 검색, 지도에 관광지 정보 보여주기이다.

기능별 개발 일지

1) 오디오 재생

단순 재생을 구현하는데는 관련 블로그와 애플개발자 페이지를 보고 금방 기능을 만들 수 있었다. 하지만 목표는 앱이 백그라운드에 있을 때 재생이 되어야 하고 이때도 유저가 재생/일시정지를 제어할 수 있어야 하는 것이 목표 기능이었다.

a) 백그라운드 재생 = Xcode -> Target -> Background Mode 에서 Audio 를 사용설정

b) 무음모드 = 테스트 하던 도중 갑자기 소리가 안나서 확인해보니 현재 기기가 무음 모드였다. 무음모드일 때도 동작하도록 AVAudioSession playback 카테고리를 설정해주었다.

c) 잠금화면에서 제어 = MPRemoteCommandCenter 를 이용해서 잠금화면에서도 재생/일시정지가 잘동작되는 것을 확인했다.

트러블슈팅

1. 포그라운드 상태에서 화면의 재생을 눌러 재생상태로 변경

2. 백그라운드 상태에서 잠금화면의 일시정지를 눌러 일시정지상태로 변경

3. 다시 포그라운드로 돌아왔을 때 재생버튼의 이미지는 일시 정지 상태로 변하지 않고있음.

- LifeCycle 을 이용하면 되지 않을까 싶어서 viewWillAppear 에 print 를 작성해서 포그라운드에서 백그라운드로 돌아올 때 콘솔로 확인했지만 print 문은 보이지 않았다.

- SceneDelegate 에서 앱의 백그라운드와 포그라운드를 확인할 수 있는 메서드가 있는 것이 생각나서 sceneWillEnterForeground 메서드에서 NotificationCenter 를 이용해 현재 AVPlayer의 상태를 전달해주도록 수정 후 해결했다.

앱 출시 후 추가적으로 알아보니 SceneDelegate 가 아닌 ViewController 내에서 Notification.Name.UIApplication.willEnterForegroundNotification를 이용해 Foreground 상태로 오는 것을 체크 후 재생 이미지를 업데이트 시켜 주면 될 것 같다.

2) 오디오 데이터 Realm 저장

메인화면에 테마별로 오디오 파일을 API 통신 후 보여주는 ViewController 가 있는데 사용 중인 API 가 하루에 1000회만 사용할 수 있었다. 테스트하다보면저녁부터 데이터가 안나왔는데 확인해보면 1000회를 다 사용했다는 오류메시지를 확인할 수 있었다.

개선을 위해 처음 해당 ViewController 를 실행시 저장한 Realm 데이터가 없다면 API 요청을 한 후 Realm 에 저장시키고 다음부터는 Realm 의 데이터를 사용하도록 수정하였다.

이때 서버에서 주는 Response 구조체와 Realm 에 저장할 데이터가 거의 같다고 판단해서 같은 구조체를 사용하기로 했다. Realm 은구조체를 저장할 수 없기 때문에 하나의 클래스로 Response 데이터, Realm 데이터를 사용하기로 했다.

개발하면서 계속 불편하다고 느낀점이 있다. 하나로 Response 와 Realm 을 관리하니 만들어진 파일은 하나 줄겠지만 화면이 많아 질수록 이게 Realm 에서 가져온 데이터인지 서버통신하고나서 받은 Response 인지 헷갈리기 시작했다. 차라리 각각 Response 용 구조체, Realm 용 클래스를 만들어서 형 변환을 해서 관리하는게 좀 더 좋지않았을까? 하는 생각이 들었다.

앱 출시 후 관련 블로그를 찾아보았는데 추후 업데이트 때 참고하면 좋은 글이다.

3) 검색

a) 검색 기능은 API 호출 후 리스트로 보여주는 부분이라 오래 걸리지 않겠지? 하고 이터레이션을 작성할 때 완료시간도 얼마걸리지 않는다고 해두었는데 UI 를 만들고 데이터를 다루는데 시간이 너무너무 지연되었다.

DiffableDataSource 와 CompositionalLayout 를 이용해 UI 를 잡으려고 했다.왜냐하면 첫번째 섹션은 태그셀 디자인, 두번째 섹션은 일반 Vertical 스타일의 셀인데 섹션별로 디자인이 다를 때 이것들을 사용하면 좀 더 쉽게 개발할 수 있다고 기억하고 있어 선택했다.

데이터를 업데이트 시키기 위한 구조체의 구조를 잡는데 시간이 오래 걸렸다. 고려해야 될 사항은 사용 되는 데이터는 Hashable 해야되고 , 섹션별로 UI 가 다르고, 첫번째 섹션은 고정적인 데이터, 두번째 섹션은 Realm 데이터와 연동된 가변적인 데이터로 구성해야 한다. 이때 어떤 블로그 글보다 도움이 되었던 코드는 Apple 에서 제공해주는 예제코드이다. 구현은 되었지만 아직까지 제대로 정리가 되지 않아서 추후 학습을 이어나갈 계획이다.

b) 검색 결과페이지에서는 Parchment 라이브러리를 활용해 탭UI 를 구성했다. 라이브러리는 설명이 잘되어있어 금방 커스텀 해서 적용을 할 수 있었다. 기존에 구조와는 달라서 데이터를 어떻게 전달할지 고민했다. 부모 ViewController 안에 2개의 자식 ViewController 로 있는 구조로 부모, 자식 ViewController 간의 데이터 전달 할 때 Down Casting 을 통해 부모 -> 자식으로 데이터를 직접 전달 하고 있는데 데이터를 다루는 부분은 웬만하면 ViewModel 로 이관해서 ViewController 의 역할을 줄여야되는데 구현하기에 급급해서 하나씩 ViewController 에서 데이터를 다루고 있기 시작했다. 일단 완성이 목표였기에…

4) 지도 기능

API 통신 이후 Mapkit 을 활용해서 지도에 Annotation 과 Clustering 으로 유저에게 보여주는 기능이다. 기본 기능을 구현 후에 오류를 잡는데 오래 걸렸던 기능이다. API 통신이후 이미지를 보여주는 CustomAnnotaionView 를 만들었는데 처음에는 이미지가 잘나오다가 지도를 줌인하며 Clustering 이 동작되고 나서는 기본 이미지로 변경되는 오류가 있었다. CustomAnnotaionView 에서 prepareForDisplay() 를 이용했다. 이 메서드는 View 에 들어가는 값을 미리 설정하는 메서드인데 여기서 image 를 가져오는 작업을 추가로 해주었다. 기존에는 처음 AnnotationView 를 추가해줄 때만 이미지를 추가해서 현재 데이터와 맞지 않는 데이터가 뜰 때도 있고 줌인제스처 이후 이미지가 없어지는 오류가 있었는데 이후 해결되었다.

마치며..

넣고 싶은 기능을 전부 넣지는 못했지만 한번 사용해보고 싶은 기능은 넣을 수 있어서 1.0 버전에서는 만족을 하려고 한다. 추후 2.0, 3.0 버전에서는 기능도 기능이지만 좀 더 코드 구조를 개선시켜보려고 한다.

기획에 대한 피드백 그리고 이게 맞을까 하는 의구심이 생길 때면 멘토님들에게 질문 후 금방 다시 개발을 할 수 있었는데 멘토님들에게 너무 감사하다는 말을 전하고 싶다.

--

--