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

멘토링

  • ViewModel Input/Output

  • ViewModel을 추상화할지 말지

  • 레포지토리에서 에셋에 있는 로컬 제이슨 데이터에 접근하기 위해 NSDataAsset을 썼는데, 그게 Ukit에 의존적이라 레포지토리가 UIKIt에 의존하게 되어벌임 -> 우짠데

    • 그냥 스토리지에 넣고 번들에서 로딩하면 됨 (파일을 로드해도 되고)
    • JSON 시리얼라이저나 인코더/디코더 써서 원하는 형태로 바꾸면 됨
    • 에셋 말고 파일로 가져오면 UIKit 의존성이 없어질 것이야
      • 사실 크게 중요한 부분은 아니긴 함
    • 리소스라서 되어있는거
    • 정리: 프로젝트 파일 안에 json 파일이 존재하고 경로를 따서 불러오기
  • self를 명시적으로 붙이는게 좋은가?

    • 객체의 프로퍼티나 함수를 사용할때 self를 사용하는 컨벤션의 기준을 어떻게 잡으면 좋을까
      • 한 사람이 짠 것처럼 보일 수 있게 맞추는게 좋을텐데 말이야
    • self는 장단이 없어보임 -> 다 붙이시는 편임 -> 안붙이는 팀도 많아서 다수결로 정하는 수준;
    • 그 다음은 보통 파라미터가 3개 이상일때 개행을 어떻게 할까? -> 이것도 취향이라 가위바위보를 해서 지키면 될듯
    • 집중해야하는 컨벤션은 스위프트 스타일 가이드 -> 함수 이름 잘 짓기
      • 위에서 하든 말든 통일만 되면 ㄱㅊ다면 함수명을 짓는 방법과 파라미터 이름에 조금 더 집중하는게 좋을 것임
      • 기준은 스위프트 스타일 가이드
      • 스타일 시트나 레이 벤더리치가 뭐지? 아무튼 여기서 만들어놓은거 따라도 좋음
  • 린트 라인 100자로 정해놨는데 너무 빡빡함

    • xcode 설정을 애초에 100자로 정해놓으심
    • 개행을 잘 활용하면 좋은데 한줄에 있어야 더 편한게 있을순 있음
      • 이때는 별로 안중요한듯
      • 린트를 무시하는 코드를 넣어서 의도적으로 무시하는 경우도 잇나봄
    • 결론: 우리의 문제다
    • 못들었음;;
      • 무슨 옵션을 true로 한다고 하신거같음
      • 읽기 편하게 이렇게 하시는 편임
      • 파라미터도 옵션마다 개행하고 스타일 차이임
    • extension을 활용해서 코드를 줄일수도 있음
      • 반복적인걸 한명이 총대매고 익스텐션으로 정리해도 좋음
    • 유틸성 코드를 테스트를 하는 것도 좋음
      • 테스트는 어떻게하면 좋을지 다음주쯤에 보여주심
    • convinience init을 만들어서 편의성 메소드를 만들어도 좋아
      • UIEdgeInsets(all: 12.0)
      • 가독성이 좋아지니까 해보자
  • 에펠탑을 검색할때 엪을 잡지 못함

    • 검색 로직이 들어갈것 -> 가져온 데이터들중에서
    • 한글자를 입력할때마다 검색을 함 -> 영어는 문제가 없는데 한글은 에펠을 치는 중에 엪이 될수도 있고...
    • inputChanged에서 스트림을 흘려보내면 중간중간 결과값이 없어 깜빡거릴수도 있지 않을까? 걱정
    • 검색은 요청량을 줄이기 위해 debounce를 사용함
      • 쓰로틀과 디바운스라는 2가지 개념
      • 쓰로틀은 요청을 몇초마다 짤라서 보내주는 형태임
      • 디바운스는 검색이나 입력에 많이 사용
        • 가나다를 치면 실제로 500ms로 디바운스를 걸면 500ms동안 발생한 이벤트중에서 가장 마지막것만 적용함
        • 실제는 더 짧지만 (200ms)
        • abc를 빠르게 치면 abc라는 마지막 요청만 감
      • 쓰로틀이나 디바운스를 안걸면 가나다라만 쳐도 8번정도 요청이 간다
      • 둘 중 하나를 걸면 되는데 콤바인에 이미 있음
        • 액션을 넣을때 걸던지 디바운스 처리를 뷰모델에서 해도 됨
        • 뷰컨에서 디바운스 처리를 해줘도 됨
      • 쓰로틀은 버튼에서 많이함
        • 버튼을 광클하면 푸시 2번되는 현상을 막을 수 있다
        • 디바운스랑 다르게 한 번 누르면 몇초동안 이벤트를 무시함
      • 마지막 이벤트가 상대적으로 더 중요하다 -> 디바운스
      • 각 이벤트가 중요도가 동일하다 -> 쓰로틀
      • 디바운스는 정해진 시간동안 같은 이벤트가 또 발생하면 이전의 이벤트를 취소시킴
      • switchToLatest를 사용하면 이벤트를 중간에 취소시킬 수 있음
        • 쓰로틀을 걸었다 -> ABCD를 입력했는데 AB와 ABCD로 두번 끊어서 들어갈 수도 있음 -> 저걸 쓰면 AB를 취소시킴
      • 검색은 응답도 빠르고 자동완성을 보여줘야하다보니 이런걸 잘 쓰진 않는데 좋아요 요청 같은걸 하는 경우엔 쓰로틀을 걸고 저걸 또 추가함
  • 코디네이터 차일드가 외잇을까

    • 코디네이터가 가장 쉬운 구현이 이런거임
      • 전체 코디네이터가 있고 거기에 모든 인터페이스 다 붙이기
    • 조금 복잡한거 -> 앱 코디네이터 + 각 피쳐들에 대한 코디네이터가 차일드로 붙음
    • 코디네이터라는 인터페이스 정의할때 트리구조로 차일드가 찢어짐
      • 자식의 자식에도 코디네이터를 계속 붙이는 방식
    • 모델이나 피쳐 단위로 쪼개질수도 있어서 이렇게 함
    • ribs 개념 보면 트리구조로 붙여감
      • 예시가 조금은 다른데 코디네이터도 비슷하게 구현됨
      • 빡세게 구현하면 특정 화면에서 특정 도메인으로 이동할땐 step? 도 있대
      • 앱 코디네이터에서 작업해보자 -> 화면이 별로 없음
        • 인터페이스 여러개 붙이고 마지막에 다 모여서 어떻게 분리할지 고민해보기
        • 딜리게이트 처리가 필요할 수도 있음
        • A ->B 화면 이정도하는데 딜리게이트로 정보를 넘겨주면 편한데 코디네이터로 하면 이벤트를 코디네이터가 처리해줘야함
          • 이런거 고민
        • 나누는건 나중에 하자
    • 트리구조로 관리가 된다
      • 예시는 다른 화면 이동할때 탭이 다르다보니 코디네이터를 매번 선언해서 사용함
    • 메모리 해제가 안되게 이렇게 작업하는거
    • 차일드가 배열로 들고 있는 레퍼런스도 몇개 보고 트리로 구성하는 것도 어떤 화면이 갈 수 있는 경로를 담는건가?
      • 안넣어주면 메모리에서 사라짐
      • 우리가 만드는 앱 코디네이터는 씬딜리가 들고있으니 안사라지는데 이걸 쪼개서 차일드로 만들다보면 자식 코디네이트가 사라져버릴 수도 있음
        • 코디네이터를 생성하고 start를 호출한 다음에 코디네이터가 사라져버리면 안되잖아
          • 의존성을 받아서 아래로 그려주는거니까 사라지면 안된단말이야
          • 차일드 구조가 명확해야하니까 다 지정하는거
          • 무슨 뜻인지 이해가 안됨
    • 결론: 일단 앱코디네이터가 몰아놓고 나중에 정리

엔티티는 속성만 딱 있음 -> Codable같은거 없음 -> DTO를 한번더 가공해서 넘기기?

  • MovieResponseDTO를 MovieDTO로 바꾸고 그걸 다시 MoviePage로 바꾸고 Movie로 바꾸기도 함
    • 비즈니스 로직상 리모트와 로컬에서 가져온걸 동시에 보여주게 될수도
    • 데이터 격리를 위해 계속 이렇게 변환해주는 것
  • 네트워킹으로 받은것도 보여주고 캐싱해놓은것도 보여줌
    • 전역적으로 쓰게되면 섞어서 보여주는게 힘들어짐
    • 도메인의 영역으로 분리해줘야 종속되지 않고 작업이 가능할 것임
    • Movie는 모두가 공유하는 진짜 딱 데이터만 있는 엔티티임
      • 앱 전역적으로 사용되는 모델은 엔티티

네트워크/코어데이터에서 받아오는 타입 DTO는 코더블이 필요하니까 격리시켜놓고 도메인 레이어단으로 넘어올때 변환을 해서 사용한다!

  • DTO 이름 자체가 네트워크나 코어데이터에서 받아올때 쓰는 데이터 전달용 객체임
  • 이걸로 어떤 문제를 해결할 수 있는지를 알면 good

변경되면 좋을 부분

  • 레포지토리 인터페이스랑 구현체가 같은 파일 안에 있음
  • 실제 클린 아키텍처에선 두개의 위치가 다르다!
    • 위치가 다르다는건: 레포리토리는 도메인 레이어 / 구현체는 데이터 레이어
    • 모듈로 쪼개면 두개의 위치가 다름 -> 현재는 같은 앱 타겟이라 문제가 없음
    • 프로토콜과 구현 객체는 원칙적으로 다른 위치 (파일이든 타겟이든) 에 있는게 더 좋은 구조임
    • 클린 아키텍처대로 도메인 레이어, 데이터 레이어, 프레젠트 레이어를 아예 폴더 구조로 쪼개고 작업하는 것도 좋은 생각
    • 엔티티와 DTO가 섞여서 사용되는듯
    • 네트워킹하거나 로컬에서 데이터 가져오는 레포지토리 구현체 (클래스/구조체)는 데이터 레이어
    • 유즈케이스는 ? 레이어
    • 공부하는 중이니까 원리대로 해보는게 좋지 않겟나 질문: 뷰모델이랑 유즈케이스도 프로토콜로 추상화를 시켜놓음 -> 이때도 구현체와 인터페이스를 분리해야 하는가?
  • 뷰와 뷰모델은 같은 프레젠테이션 레이어라 파일을 구분할 필요가 없음
  • 레포지토리는 종속적인 인터페이스가 있고 구현체는 자유롭게 바뀔 수 있으니까
  • 프레젠테이션과 데이터는 서로 모름
  • 뷰모델은 유즈케이스를 통해 정보를 받아오고, 유즈케이스는 레포지토리를 통해 가져와야함
    • 유즈케이스는 레포지토리의 인터페이스를 알아야 가져올 수 있겠지
    • 근데 레포지토리가 실제 어떤 방식으로 가져올지는 유즈케이스가 몰라도 됨
  • 구조를 잘 나누면 코드를 이해하기 쉬울것임 폴더 구조부터 그렇게 해보고 나중에 프레임워크로 분리해보는 것도 좋은 경험일 것임

final을 왜 붙이는지를 알아야함

  • 다이나믹 디스패치 개념이 나옴

좋은건 코드컨벤션을 정리할때 이유가 납득이 안되면 거부하는 것도 좋음

  • 왜 좋지? 회사에선 안좋을수도 ㅋㅋ

다음 버튼 구현을 누가 봤을때 이해가 잘 안될수도 -> 자세히 적기 화면 전환, 바인딩, 코어데이터 상관없어보이는 세 가지가 섞여있음

  • 그룹핑이 잘 되어있으면 좋음
  • 화면 전환 이슈라면 코디네이터를 이용해서 빈 화면을 볼 수 있다 이런것까지 하면 좋음
  • 팀원들이 바빠지면 옆사람들이 뭐하는지 모를 수 있는데 이슈가 상세하면 그런걸 파악하기 좋음

코디네이터같은 초기세팅이 오래걸리는 것들이 끝나면 뒤쪽은 할만 할 것임

너무 설탕을 치는건 안좋지만 초반에 편의성 관련 작업을 해주면 좋음

회고 할때 피드백을 많이 해주면 좋음 -> 긍정적, 개선점 피드백

  • 이걸 이렇게 해보면 더 좋지 않을까
  • 이런 피드백을 안해보면 회사에서 솔직하지 않다는 인상을 줄 수도 있음
  • 아쉬웠던 부분을 말해주는건 좋은데 너무 blame하면 안됨

캘린더에서 날짜 범위가 좀 늦게뜨는것 같다

  • 222222