11월 9일 (화) 멘토링 - boostcampwm-2021/iOS04-OwnMyWay GitHub Wiki

근황

저번주 이후로 바뀐 부분 설명드림

  • backlog가 너무 사용자 중심으로 되어있어서 개발할때 혼란이 생겨서 개발자 입장도 고려해서 보완했습니다.
  • 이슈를 작성하고 asignee를 나다싶으면 가져가는 방식으로 고쳤습니다.

컨테이너 관련 이슈

멘토링 초반의 기록이 누락되었음

카트 뷰컨에서 눌렸을때 액션도 담당 -> 그것도 addLandMark가 delegate로 받을까?

  • 내부적으로 처리해도됨
  • addChild를 하는 순간 연결이 됨
  • 잘 안된다면 didLoad를 안해서 그런것일듯
    • 내부 처리가 잘못되었을수도
  • Combine으로 해도됨

코디네이터

요약: delegate 이름 변경하기, 의존성 주입 개선하기, addChild 문제 해결하기??

채점받는 느낌인데 코디네이터를 잘 짰을지 모르겠음, 뷰컨이 아니라 뷰모델단에서 했는데 메모리 문제? addChild는 있는데 removeChild는 없음. remove는 pop할때 해야할 수도 있을텐데..

  • remove는 따로 할 필요가 없음
  • pop 시키면 알아서 remove됨
    • 별도로 해야하는 경우는 뗐다 붙였다 할 경우에
    • addChild하면 부모 라이프 사이클을 따라가므로 넘어가도 됨
  • delegate란 표현은 안씀
    • 위임처리를 하는게 아니라 로직이 담겨있음
    • 뭔가를 받을때 사용한다?
    • 라이프 사이클을 받기 위한 행동들임
    • 코디네이터 내부에서 뭔가를 할때 적합함
    • 추상화된 개념 자체를 들고 있는걸로 작성하는게 맞음
    • 딜리게이트는 코오디네이터 안에 딜리게이트 변수라고 생각할 수 있음!
  • 개선할 점은 의존성 주입이 안되어있는 상황임
    • 코오디네이터에서 뷰타입을? 받고 하는 예제가 있음
    • 뷰모델 생성하고 넣는데 의존성 관리가 불가능함
    • 맨 위에서 아래까지 내려올 수 있게 의존성을 관리하는걸 고민해보자 더 찾아보면서 익혀보겠습니다.
  • 쉽지 않음
    • 지금은 이정도로 만족하고 프로젝트 완성될때 개선해보자
    • 테크닉 관련이라 제품 완성도랑 무관함
    • 기술적으로 엄청 중요한건 아님
    • 일단 동작하게 만들고 나중에 개선하자
  • addChild 이런 부분은 동작이 안되는 부분이니까 바로 개선해보자

킹피셔 의존성 관련 이슈

요약: extension으로 빼서 킹피셔 의존성 줄이기

  • 지금 코드가 Kingfisher를 사용하는데
  • imageView.kf.setImage()
  • 이 부분이 킹피셔 관리 정책에 강하게 결합됨
  • imageView.setImage() 함수를 만들고
    • 내부에서
    • kingfisher는 정답이 아님
      • 문제생겨서 갈아 엎은적도 있음
      • 한번 래핑을 하고 사용하면 킹피셔에서 어디로 갈아타야 하는 경우 저 함수 안의 코드만 갈아끼우면 됨
      • 결론: 의존성을 줄여보자!
      • imageView의 extension으로 분리해보자!

Extension 파일 분리 문제

요약: 지금 수준에선 MARK만 달아서 구분해주면 충분해보임, 더 길이진다면 파일이 아니라 모듈 자체를 분리하기

익스텐션을 많이 쓰는데 파일별로 분리하는게 좋을까, 같은 파일 내부에 두는게 좋을까

  • 선택적인데 코드량에 따라 다름, 짧으면 MARK: - 처리정도만 하는 편
  • 더 길어지면 파일이 아니라 모듈 자체를 분리해야 함
  • 객체 자체를 분리해야 하는 경우라서 파일을 분리하지는 않음
    • 길면 보기 힘드니까
  • 200~300줄이라 상관없어보임

네비게이션 관련 이슈

요약: 두 가지 방법이 있는데 Travel을 관리하는 객체를 만들어주는걸 추천함

기술적인 질문, 타이틀과 날짜를 입력받는 부분이 있고 다음으로 넘어갔을때 관광명소를 추가할 수 있음 뒤로 가기 버튼을 눌렀을때 현재 Travel이라는 객체로 관리를 하는 중임. 제목, 날짜, 관광명소를 배열로 가짐 전달을 해줘야 다시 관광명소 화면으로 갔을때 이전에 선택한걸 유지할 수 있었음 전달하는 방법을 찾기 어려워서 네비게이션 아이템에 액션을 걸어서 navigationPop 동작과 전달하는 동작을 엮엏서 타겟을 해놨음 그러니까 슬라이드 액션이 안먹혔는데 방법을 계속 찾았는데 pop을 할때 정보 전달을 하려고 하면 괜찮은 방법이 있을지

  • 최근에 저런 화면을 만들었는데 저런 상황에서 선택지는
  • 데이터를 관리하는 객체를 따로 만들기
    • pop하든 말든 다른 관리 객체에서 관리하니까 문제가 없음
  • 뷰컨트롤러 하나를 두고 뷰만 갈아끼우는 방법도 가능함
    • 사용자가 느끼기엔 A->B이지만 뷰컨트롤러는 하나고 뷰만 이동함 (데이터는 submit할때 씀)
  • 변수 몇개 건드리면 할 수 있었던걸로 기억함
    • 아쉽게도 기억이 안나심 travel이 구조체여서 발생한 문제로 보입니다. 클래스면 괜찮았을텐데. Combine할때 구조체를 걸어놔서 travel이 바뀌면 감지하는 방식임. 이쪽에서 좀 더 알아보겠습니다.
  • 객체 자체는 애초에 value object라서 구조체가 맞아보임
  • travel 관리를 각각 하는데 그걸 관리하는 별도의 객체가 생긴다는 의미
  • 구현을 좀 더 더럽게하면 A 뷰컨에서 이벤트 스트림 받아서 업데이트하기
  • 근데 작성자말고는 보기 힘들어짐
    • 데이터 관리하는 객체 두거나 이벤트 delegate로 업데이트 치는 방식...
    • 백버튼 누를때 저장하는데 그냥 이벤트 받아서 갱신하는 경우도 있음
  • 추천은 관리 객체를 만들기
    • 관리 비용, 가독성 측면에서 감사합니다.

모든 화면에서 대응하기

요약: UI 설계 자체가 잘못되었을 수 있음

모든 기기 크기에 대응해야하는데 맵뷰와 콜렉션뷰를 하나의 뷰로 만들었음 작은 화면에서 스크롤해야하는데 first responder가 맵뷰로 잡혀서 스크롤이 너무 힘들어지는 문제가 발생했음. 어떻게 해결해야 좋을까요

  • 저건 해결할 방법이 없음
  • 제스처 방향 자체가 저게 맞음
  • 지도 크기를 줄이거나 위치를 조정한다거나... 모든 화면에 대응하려고 스크롤이 안되는 화면으로 하고 맵뷰같은걸 비율로 하려고 했음. 근데 가로세로 비율도 다 다르니까 width, height 정하는데 어려움이 있었음. 맵뷰를 정사각형으로 무조건 보여주고 싶은데 다른 부분의 비율이 깨지는데 어떻게 접근해야 좋을까요.
  • 만약 저 화면을 만든다고 하면, 저 화면의 문제가 이 화면에서 두 가지 동작으로 하려고 해서 생기는 문제임.
  • 정사각으로 보이는 화면은 그 화면말고 안보임
  • 지도가 보이는 화면에서 추가동작은 설계가 잘못됨
  • 동작을 바꿀 수 있다면 지도에 있는걸 핀꽂고 다른 뷰로 전환을 시킨다거나 모달을 띄운다거나 등등
  • 지도 크기 자체를 늘릴 수 있다거나 하는 방식을 제공해야함
  • 이 상태에선 원하는 레이아웃 구조가 안나올듯 홈버튼 없는 아이폰 기준으로 생각하보니, 고려를 못했음
  • 기기별로 비율을 다르게 가져갈 수도 있음
  • 아이폰8이나 하위버전, 노치폰이 아닌 비율은 몇대몇이고 노치폰에선 몇대몇 이런식으로 잡을 수도 있음
  • 추가하는 것에 대한 UI를 바꿔도 되고

다음 버튼이 너무나도 큼

요약: safe area inset을 더해주는 방식으로 구현하기

safe area 꽉 채우려고 일부러 크게했습니다.

  • safe area inset을 받아서 더해주는 방식으로 구현했어야함

굉장히 부끄럽다

개발 진도 문제

요약: UI/UX에 영향을 주거나 치명적인 오류가 아니라면 일단 기능 구현부터 빠르게 하고 나중에 리팩토링하자

일을 하다보니 추가적인 일이 생겨서 진행이 잘 안된다. 누구는 쓰레기버리고 뒤에서 치우는 느낌임. 오늘은 2명이 리팩토링하고 2명이 기능구현했음...

  • 일단 4명이 전부 기능 구현을 해야함
  • 리팩토링은 나중에 앱스토어에 올라갈 수준이 되고나서
  • 카톡도 코드가 개판이었지만 동작은 잘 되니까 나중에 리팩토링함
  • 코드가 깔끔해도 사용성이 안좋으면 안씀
  • 앱이 커질때 추가적인 기능을 붙이고 그러기 위해 리팩토링하는거
  • 속도가 안나면 다 포기하고 기능구현 문제 하는게 맞음
  • UI/UX 개선은 즉각적으로 하는게 좋은데 코드 관련 개선사항 (동작은 하는데 코드가 더럽거나하는거, final 붙이거나 하는거)은 나중에 처리하기
    • 지금 코드 컨벤션이 정해졌으니 이전 파일은 일단 냅두고 다음 파일부터 적용해보자
    • 나중에 하자
  • 코드 리뷰에서 걸러지는 정도면 충분함
  • 주니어들이 코드는 잘쓰는데 기본적인 iOS SDK 쓰는법을 모르는 경우가 있었음
    • 일단 구현부터 하고 그다음에 코드 수준을 높이자!
  • 너무 심하게 가독성이 떨어지거나 크래시를 유발할 수 있다면 바로 고쳐야겠지만 아키텍처는 나중에 처리하기
  • 이 이상으로 공을 들이기보단 어느 선만 지키면 나중에 리팩토링하기
  • 신규 앱 만들때는 엔지니어링 레벨을 높게 잡을수록 개발 속도가 늦어짐
    • MVC는 훨씬 빠를텐데...
    • 보일러 플레이트 코드도 생기고...
    • 테스트 코드없이 플레이만 잘 되는게 좋을수도 있음

테스트

요약: 일단 유즈케이스나 Extension 코드, Util 코드를 먼저 테스트하자. Presentation 레이어는 나중에!

MVVM에서 강점이 ViewModel이 UIKit에 의존적이지 않아서 테스트가 가능하다는건데 테스트는 신경쓰지 못해서 테스트가 없음. 좀 막막함...

  • 테스트 코드는 접근 방식이 조금 다름
  • 최근 작성된 코드에 대한 테스트를 추가하는 것도 방법임
  • extension 코드나 유틸 코드는 라인이 엄청 많음
  • core logic 먼저 테스트를 작성하고 클린 아키텍처 기준으로 usecase 먼저...
  • 프레젠테이션 레이어는 나중에. 우선순위가 낮음
  • 도메인 단의 비즈니스 로직들에 좀 더 신경써주면 좋아보임
  • 유즈케이스에서 레포지토리를 조합한다던지 직렬 요청을 통해 뭔가를 반환하는데 우리 작업 방식으로는 구현을 다 하고 실행해서 데이터가 다 오는지 확인할텐데 테스트만 돌려봐도 동작하는지 다 알 수 있음
  • 뷰랑 뷰모델에 대해 추가하는건 당장 무리로 보임
    • 100% 추가해야 한다고 보시진 않음
  • 많이 쓰는 extension 코드나 utils 코드를 테스트하자
  • 그리고 비즈니스 로직에 대한... 잘 안바뀌는 로직들 위주로 해보자 중요한 비즈니스 로직이랑 슈가 코드가 잘 동작하는지, 뷰모델도 사실 보여주는거니까 테스트 우선순위를 낮게 가져간다는 말씀이신가요?
  • 맞습니다
  • 멘토님은 프레젠테이션도 작성하시는데 상황마다 다름
  • 유즈케이스와 레포지토리정도.
    • 레포지토리도 상황마다 다름
  • 아무튼 유즈케이스의 비즈니스 로직과 유틸들 정도는 해보자
  • 뷰 관련된 건 숙련되고 나서 하자
  • 일단 비즈니스 로직이 없다보니...

실패 처리

요약: ViewController까지 내려오게 하는게 맞음

실패 처리를 유즈케이스에서 할지 레포지토리에서 할지 궁금함

  • 실제로는 에러를 전달해줘야함 최종적으로는 뷰컨까지 전달될까요?
  • 다이얼로그든 스낵바든 보여줘야함
  • OMWError Error
  • enum FooError: Error {}
  • case database~~~
  • 로컬 디스크립션을 보여줘도 되고...
  • 얘도 엔티티다 보니 도메인 레이어임
  • 어떤 에러메시지를 보여줄지는 프레젠테이션 레이어에서 보여주면 됨
  • 광범위하게 쓰는건 네트워크 에러 DB 에러
  • Rx는 RxError도 있음
  • 못적었다; 맨처음에는 레포지토리가 result 타입으로 반환하고 그걸 usecase가 다시 넘겨준다고 하면 유즈케이스가 왜있지하는 생각이 들었음 똑같은걸 한번 더한다는 느낌을 강하게 받음
  • 상황에 따라 그럴 수 있음
  • 여러 정보들이 필요한 상황이 생길 수 있음
  • 그런 정보를 섞어서 보여줘야 할 수도 있음
  • 그럼 스펙들이 생기는데 유즈케이스는 정말 동작에 관한 것임
  • 검색이라는 유저가 느끼는 동작 안에 해야할 일이 있을 수 있음
    • 유즈케이스 안에 동작이 생길 수 있는데 지금은 비즈니스 로직이 너무 단순해서 bypassing하는 정도라서...
    • 회원가입하는 경우 유저 검증하고 요청을 보내야 한다거나
    • 그럼 네트워크 요청을 3번해야함
    • 이런 케이스가 생각보다 많음
    • 당장은 하는일이 없어보여도 실제 앱에선 하는 일이 많다
    • usecase에서 DTO? 받으면 안됨
    • 앱이 엄청 복잡하지 않아서 서버가 있으면 저런 작업이 생기는데...
    • 지금은 그냥 로컬 DB에서 꺼내는 정도라 아마 지금 상황에선 그렇게 느낄 수 있음

위치 데이터

요약: 기능 구현 자체는 될 가능성이 높으나 좋은 기획인지 의문

이번주 내용중에 맵에 유저가 이동한 경로를 받아서 그려주는 기능을 할건데 위치 데이터를 다 저장하다가 또 켰을때 그동안 이동한것도 다 보여줘야 함 1분, 5분에 한번씩 위치정보를 받아도 여행이 길어지면 데이터가 너무 길어질 수 있겠다는 생각이 들었음. 반경 몇m 안떨어지면 위치 정보를 업데이트하지 않는다던지 해서 조금이라도 줄여보려고 하는데 이렇게 하는게 앱에 무리가 갈까요

  • 기록 자체는 무리가 아님.
  • 백그라운드에서 기록을 하려면 권한이 따로 필요함
  • 실제로 이렇게 하는 앱이 있음
  • 친구들이 뭐하는지 다 뜨는 앱임
    • 백그라운드에서 기록하는데 백그라운드에서 받는 권한이 있음
    • 그것만 하면 됨
    • 엄청 복잡하거나 무거운 로직은 아님
    • 실제로 앱이 있으니까
    • 구현하기가 쉽지는 않을 수 있음 중간에 백그라운드에서 킬이 될 수도 있고... 킬이 되지 않나요? 우선순위는 다르지만 킬 될걸요?
  • 테스크 자체가 달라요
  • 애플 공식 제공하는 job이 있는데 백그라운드에서 킬이 안되는 게 있음
  • xcode 보면 앱에서
  • Capabilities에서
    • sign with apple 이런거 추가하는 공간임
    • 백그라운드 job이 따로 있음 백그라운드 모드가 있음
  • 더블클릭하면 추가가 됨
  • 로케이션 업데이트가 있음
  • 백그라운드에서 위치정보를 계속 업데이트함
    • 앱이 꺼져도 파란색으로 점이 켜지고 계속 트래킹함
  • 아니면 앱이 꺼지면 계속 꺼짐
  • 백그라운드 모드의 location updates 검색해보자
  • 돌아가는 길은 사진 위치정보 위치로
    • 최근 사진을 불러와서 사진을 지도에 보여주는 것도 방법이겠음
  • 일단 저걸 사용할 수 있을지를 먼저 찾아보는게 좋겠음 염려되는게 저걸 백그라운드에서 계속 돌아가게 하면... 네비게이션같은거처럼 배터리 소모가 클까봐 걱정됩니다. 여행중 쓰는 앱이라 전원 관련 이슈가 민감할텐데 궁금하네요
  • 그래서 배터리 소모가 큰 앱이라 여행이랑 안맞아보이고
  • 그냥 추억을 만든다는 점에서 사진을 중심으로 하는 것도 좋아보입니다.
  • 구현 자체는 가능하다는걸 말하고 싶으셨음
  • 저 기능 자체가 옳은 기능일까?
    • 기획 자체가 잘못되었을수도 저런게 reject 사유가 될 수 있을까요?
  • 배터리 안내만 잘 하면 됩니다
  • 공식적으로 지원하는 기능이니까요