-
Notifications
You must be signed in to change notification settings - Fork 4
홍경표's
kyungpyoda edited this page Dec 21, 2020
·
5 revisions
홍경표(S064)가 프로젝트를 진행하며 성장한 점에 대해서 기록하였음.
Contact
홍경표
010-7676-6401
rudvy9620@gmail.com
qorghdl@naver.com
- 결론부터 말하자면
Swift
라는 언어가 이제는 내게 가장 편한 언어가 되었다고 자부할 수 있게 되었다. 교육 기간 중간중간 코딩 테스트 문제를 10개 미만을C++
로 풀어보면서 그래도 이럴 때는C++
이 더 편하구나 라고 생각했었는데, 클러스터링 알고리즘 같은 문제를 해결하다보니Swift
가 편해졌다고 확실히 느끼게 되었다. 부스트캠프 5개월의 교육 기간 내내Swift
를 쓰면서 그것의 깔끔한 스타일을 열심히 따르다보니 안좋은 코딩 습관들도 어느새 많이 사라져갔다.
상세정보
- 개요:
- K-Means는 대표적인 클러스터링 알고리즘 중 하나이다. 평균 속도가 빠른 편이면서도 구현하기에 복잡하지 않아 여러 클러스터링 알고리즘 중 선택하게 되었다. 다만 K-Means는 단점이 있는데 K를 input으로 줘야하기 때문에 적절한 K값이 아니면 좋지 않은 결과가 나온다는 것 이다. 게다가 초기 클러스터에 따라 결과가 크게 달라질 수 있다는 단점도 있었다.
- 이 구현 내용은 최종 프로젝트에서는 제외되었다.
- 문제해결:
- 최적의 K값을 결정하는 방법 중 하나인 Elbow Method를 적용했다. 간단하게 설명하자면, K가 늘어날수록 SSE(오차제곱합)는 줄어들게 되어있는데 그 SSE의 감소량이 어느 순간 급격히 작아져서 팔꿈치와 같은 모양이 만들어진다. 그에 따라 아래 예시 사진에서는 K=3 부분을 최적이라고 본다. 나는 급격히 감소한 것을 판단하기 위해서 꺾여지는 부분의 각도를 구해서 해결했다.
-
- 초기 클러스터 선정에 따라 결과가 크게 달라지는 문제를 해결하기 위해서는 초기 클러스터를 최대평균거리를 이용하여 선정했다. 어떤 논문에서 초기 클러스터를 서로의 거리 합이 가장 크도록 선정하면 결과의 안정성을 좀 더 높은 확률로 보장한다는 연구결과가 있어서 이 방법을 따랐다. 다행히 실제로 개선이 되었다.
- 연습, 테스트를 위해 만들어놨던 Repo @kyungpyoda/KMeansClusteringWithSwift
- 풀업 뷰는 이전 프로젝트에서 한 번 구현해봤었는데, 이번 프로젝트에서 한 번 더 구현하면서 비동기 Prefetching, 캐싱 기능을 추가했고 좀 더 다양한 제스처를 대응함으로써 사용자 경험 측면에서 더 개선해보았다.
상세정보
-
개요
- 하단 풀업 뷰의 상태는 3가지가 있습니다.
상태 설명 Short 화면 하단부터 1/3이 차도록 위치하는 상태. CollectionView의 데이터 수와 첫 번째 데이터 정도를 간단히 확인할 수 있습니다. Half 화면 하단부터 절반을 차지하는 상태. 적절한 Interaction을 통해 지도와 CollectionView 목록을 함께 볼 수 있습니다. Full 화면의 90%를 차지하는 상태. CollectionView를 자세히 들여다 보며 원하는 데이터를 찾을 수 있습니다. - 사용자의 Interaction에 따라 3가지 상태가 자연스럽게 전환되도록 하였습니다.
- 하단 풀업 뷰의 상태는 3가지가 있습니다.
-
잡아 끌다가 놓는 Pan Gesture
- 기본적으로 풀업 뷰는 사용자의 Pan Gesture에 따라 끌어 올려지거나 끌어 내려지도록 하였습니다.
- 그리고 놓아지는 위치에 맞는 Position으로 달라붙도록 하였습니다.
- 화면을 3등분 했을 때 하단 영역에서 놓아지면 Short
- 화면의 중간 영역에서 놓아지면 Half
- 화면의 상단 영역에서 놓아지면 Full
-
빠르고 짧게 스와이프 하듯 던져 올리는 Pan Gesture
- 임의의 Pan Gesture 속도 기준 값을 정하고 기준 값을 넘기는 Gesture가 들어올 때 빠르게 다음 상태로의 전환이 되도록 하였습니다.
- 빠른 Gesture에 적절히 대응함으로써 더 나은 UX를 이끌어냈습니다.
-
지도 뷰 위로의 Gesture를 자연스럽게 피하면서 접혀 내려지는 상태 전환
- 풀업 뷰가 Half, Full 상태에서 지도 뷰 위로의 Gesture가 생기면 풀업 뷰를 무조건 내리는 것이 아닌 풀업 뷰가 방해가 되는 경우만 피해서 내려지도록 하였습니다.
- Half 상태에서 지도 뷰를 움직이며 CollectionView를 같이 살펴볼 수 있도록 하였습니다.
-
이와 같이 사용자의 Pan Gesture에 꼼꼼히 대응하기 위해서 애플 지도의 풀업 뷰를 참고하고 네이버, 카카오 지도 앱과 비교해보며 어떻게 하면 사용자가 처음 사용해도 익숙하듯이 쉽게 사용할 수 있을지, 더 나은 UX를 위한 고민을 하며 개발하였습니다.
시연 더 나은 화질의 비디오로 보기 ⤵️
-
개요
- 풀업 뷰의 CollectionView에는 POI들이 나열되어 있습니다. Cell은 각 POI의 이름, 주소, 이미지를 포함합니다.
- 이 때, POI 데이터 모델에는 이름, 위도, 경도, 이미지 url 정보만 있기 때문에 위도와 경도는 네이버 SDK를 이용해서 도로명 주소로 변환, 이미지 url은 이미지 파일로 변환하는 작업이 필요합니다.
- 이 작업들을 비동기로 수행하고 캐싱을 통해서 사용자가 Interaction중에 불편함이 생기지 않도록 하였습니다.
-
비동기 Prefetch, 캐싱
- Cell을 DataSource로부터 생성하여 그릴 때 캐시 데이터를 가져와서 넣어줍니다.
- 캐시 데이터가 없다면 임시로 "불러오는 중"을 표시하는 데이터를 넣어둡니다. 그리고 Cell의 데이터를 로딩해서 캐시처리하는
AsyncFetch
에completionHandler
와 함께 요청을 보냅니다. - 캐시 데이터를 미리 만들어 놓기 위해서
UICollectionViewDataSourcePrefetching
프로토콜을 채택하여 구현합니다. 여기서AsyncFetch
에 미리 캐시 요청을 보내놓습니다. -
AsyncFetch
는 전달 받은 데이터 모델을 가지고 Cell이 뷰를 그리는 데에 사용할 수 있게 변환하고 캐시 데이터를 만듭니다. 이 때completionHandler
도 같이 전달 받으면 Prefetch 작업이 아닌 바로 그려야 하는 작업이기 때문에 캐시 데이터를 만들고 바로completionHandler
에 전달해줍니다. - CollectionView의 Cell이 재사용될 때마다 이미지 url을 이미지로 변환하는 것은 지극히 비효율 적이고 UX면에서도 좋지 않은데, 모든 데이터 모델을 캐싱해서 사용함으로써 Cell 재사용에 따른 이미지 반복 변환 문제를 해결하였습니다.
- 풀업 뷰를 닫으면 바로 NSCache 인스턴스 해제, 멀티 스레드에 쌓인 이미지 변환을 위한 URLSession의 비동기 Task 취소를 통해 불필요한 메모리, CPU 점유율을 바로 낮추도록 하였습니다.
시연 더 나은 화질의 비디오로 보기 ⤵️
- 클러스터링의 비동기 병렬 작업과 그것을 제어하기 위해 Operation과 GCD를 함께 사용하였다. 그 과정에서 여러 스레드에서의 공유자원 충돌 문제를 겪었고 해결하기 위해 PropertyWrapper를 이용해서 공유자원의 get set을 sync하게 동작하도록 구현했으나 get과 set 사이에서 싱크가 안맞을 수가 있어서 최종적으로 DispatchSemaphore를 이용해서 공유자원 접근을 제어하도록 하였다.
-
Week 1
-
Week 2
-
Week 3
-
Week 4
-
Week 5