# 만국박람회 ## 📖 목차 1. [소개](#🌱-소개) 2. [타임라인](#📆-타임라인) 3. [시각화된 프로젝트 구조](#👀-시각화된-프로젝트-구조) 4. [실행 화면](#💻-실행-화면) 5. [트러블 슈팅](#❓-트러블-슈팅) 6. [참고 링크](#🔗-참고-링크) ## 🌱 소개 |Gundy|Dragon| |:-:|:-:| ||| `Gundy`와 `Dragon`의 iOS 만국박람회 프로젝트입니다. 테마는 1900년도에 실제로 프랑스에서 진행된 Exposition universelle de 1900의 한국 전시입니다. 아래 나열된 기술들을 적용하여 프로젝트를 진행하였습니다. - **핵심적으로 다뤄본 기술** - 테이블뷰 - JSONDecoder - 화면간 데이터 전달(Segue) - AttributedString - 화면 Orientation 설정 - AutoLayout - Dynamic Type - Navigation Bar - NameSpace ## 📆 타임라인 <details> <summary>STEP 1</summary> 221018 - Exposition - exposition_universelle_1900.json 파일과 매칭할 구조체 Exposition 구현 - Exhibition - items.json 파일과 매칭할 구조체 Exhibition 구현 - 폴더 정리 - MVC 패턴의 시각에서 폴더 분류 </details> <details> <summary>STEP 1 Feedback 반영</summary> 221020 - 네이밍 - 직관적이지 못한 네이밍 수정 - 접근제어자 - 아직 사용하지 않는 프로퍼티들 모두 private 적용 </details> <details> <summary>STEP 2</summary> 221020 - InformationViewController - 스토리보드 상에서 기본 레이아웃 설정 및 IBOutlet 연결 - JSONDecoder를 통해 Expoosition 타입의 인스턴스 생성 - Exposition 인스턴스의 프로퍼티를 통해 레이블의 텍스트를 할당 - NavigationController 임베드 - NavigationBar hidden 처리 및 화면 전환시 hidden 해제 - Segue를 통해 화면전환 구현 - ExhibitionListViewController - 스토리보드 상에서 테이블뷰와 프로토타입셀 추가하고 tableView 프로퍼티와 연결 - JSONDecoder를 통해 [Exbibition] 타입의 인스턴스 생성 - extension을 통해 UITabelViewDataSource 및 UITableViewDelegate 프로토콜 채택 - 각 셀별로 기본설정을 해 주는 confogureCells 메서드 구현 - Segue를 통해 화면전환 구현 - 다음 화면에 넘겨줄 데이터를 위한 prepare 메서드 내부 코드 작성 - ExhibitionViewController - 스토리보드 상에서 기본 레이아웃 설정 및 IBOutlet 연결 - 이전 화면에서 받아온 데이터를 통해 레이블과 이미지 및 네비게이션 타이틀 설정 221021 - refactoring - 컨벤션 통일 - 기능이 많은 메서드 분리 및 연산 프로퍼티 작성 - 네이밍 수정 - 은닉화 </details> <details> <summary>STEP 2 Feedback 반영</summary> 221025 - InformationViewController - JSONDecoder 관련 코드 간략화 - ExhibitionListViewController - 테이블뷰 관련 메서드 분리 - 메서드 네이밍 복수형 수정 - cellIdentifier 프로퍼티 삭제 - prepare 메서드 구현부 수정 - JSONDecoder 관련 코드 간략화 - 메서드 선언부 위치 수정 - ExhibitionListTableViewCell - cellIdentifier 프로퍼티 추가 - initializer를 통해 cellIdentifier 할당 - nameLabel의 text를 반환하는 연산 프로퍼티 text 추가 - ExhibitionViewController - 메서드 분리 - JSONDecoder + Extension - 데이터에셋의 name과 변환할 타입을 받아 디코딩을 수행하는 타입 메서드 decodeAsset 구현 - 기타 - 각 타입별 프로퍼티 및 메서드 은닉화 - 컨벤션 정리 - namespace 역할을 하는 Constant 타입 생성 </details> <details> <summary>STEP 3</summary> 221026 - StoryBoard - 첫 번째 화면(InformationViewController) 요구사항 구현 - 두 번째 화면(ExhibitionListViewController) 요구사항 구현 - 세 번째 화면(ExhibitionViewController) 요구사항 구현 - 요구사항에 맞게 화면이 보이는 위치를 디바이스 맨 아래부분까지로 제약 수정 - 각종 레이블 및 버튼에 DynamicType 적용 - 기타 - 최종 구현이 완료된 클래스에 final 키워드 적용 </details> <details> <summary>STEP 3 Feedback 반영</summary> 221028 - 은닉화 - `@IBOutlet private weak var`로 컨벤션 수정 - 프로퍼티 은닉화할 수 있도록 메서드 캡슐화 - identifier - 보다 구체적인 identifier를 사용하기 위해 cell의 타입 이름 "ExhibitionListTableViewCell" 사용 </details> ## 👀 시각화된 프로젝트 구조 ``` [Expo1900] ├── Info.plist ├── Source │ ├── App │ │ ├── AppDelegate.swift │ │ └── SceneDelegate.swift │ ├── Model │ │ ├── Exhibition.swift │ │ ├── Exposition.swift │ │ ├── JSONDecodeExtension.swift │ │ └── Constant.swift │ ├── View │ │ └── Base.lproj │ │ │ └── Main.storyboard │ │ └── ExhibitionListTableViewCell.swift │ └── Controller │ ├── InformationViewController.swift │ ├── ExhibitionListViewController.swift │ ├── ExhibitionViewController.swift │ └── OrientationMaskController.swift └── Resource ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── expo_assets │ │ └── Contents.json │ └── Contents.json └── Base.lproj └── LaunchScreen.storyboard ``` ## 💻 실행 화면 |![](https://i.imgur.com/LfoAnJ8.gif)|2번화면| |:-:|:-:| |1번설명|2번설명| |3번화면|4번화면| |3번설명|4번설명| |5번화면|6번화면| |5번설명|6번설명| |7번화면|8번화면| |7번설명|8번설명| ## ❓ 트러블 슈팅 - #### 테이블뷰 셀 두 번째 화면(출품작 리스트 테이블뷰)에서 사용할 프로토타입 셀에서 필요한 것은 좌측의 이미지, 타이틀, 간단한 설명의 두 레이블이라고 생각했습니다. 이는 subtitle 스타일의 셀과 유사하다고 생각해 처음에는 기본 셀의 subtitle을 사용하였습니다. 그런데 액세서리뷰를 설정하는 순간부터 스크롤이 튀는 버그가 있고, 일정한 이미지 사이즈를 맞추는 것이 적절한 것 같아 커스텀 셀을 사용하는 것으로 변경하였습니다. - #### 매직리터럴 vs 네임스페이스 `InformationViewController`파일에 작성된 코드 중 `"exposition_universelle_1900"`,`"메인"`와 같이 매직리터럴 사용하는 방식에서 휴먼에러 방지를 위해 enum을 사용하여 namespace 설정을 해야하나 고민해봤으나, 재사용되는 것이 아니기에 STEP2는 매직리터럴을 사용하였습니다. - #### 크기가 다른 문자열 첫 화면의 방문객 수, 개최지, 개최기간 등은 콜론(:)을 기준으로 왼쪽과 오른쪽의 폰트 사이즈가 다릅니다. 해당 사항을 가장 쉽게 구현하는 것은 StackView에 Label을 두 개 넣는 것이라고 생각했는데, attributedLabel을 사용하면 단일 레이블로도 같은 결과를 낼 수 있었습니다. 더 직관적이고 간단한 방법으로 작업하기 위해 attributedLabel을 사용하기로 결정하였습니다. - #### View vs StackView 오토레이아웃을 적용하면서 stackView가 제약 잡는 데에 더 까다로운 부분들이 있어서 view가 더 편한 것은 아닌가? 하는 생각이 들었습니다. 이 부분은 경험이 더 축적되야 판단이 설 수 있는 문제로 인지하였습니다. 추후에 View와 StackView를 어떤 경우에 사용해줘야 하는지에 대한 판단의 기준을 알게되면 추가로 내용 첨부하겠습니다. > 피드백 받은 의견 : StackView가 아무래도 꽤 편하게 레이아웃을 잡게 해주는 친구라고 저는 생각하는데🤔 뭐 이것도 개인마다 다르지않을까 싶네요ㅎㅎ > 저는 그래서 StackView를 사용할 수 있는 레이아웃이면 그렇게 하고, StackView로는 안되는 뷰들은 오토레이아웃을 딱딱 잡는것 같아요!! > 이건 정말 정답이 없고 스타일 차이라고 생각합니다:) > 둘다 가능한 상황이면 더 선호하는 방법을 택하거나! 성능 같은것들도 한번 고려해볼 수 있겠죠~? 근데 지금 같은 뷰에서는 성능 같은건 딱히 고민해볼 필요가 없을것 같아요! (시간되실때 StackView 성능 한번 검색 해보세용) - #### AutoLayout 원하는대로 배치가 이루어지지 않아 많이 고생한 부분입니다. 이번에 오토레이아웃을 경험해보면서 느낀점은 개발자 성향에 따라 오토레이아웃 방법이 다양하게 나올 수 있다는 것이였습니다. 그러하여, 뷰를 구성할때 기본적으로 오토레이아웃을 잡아주는 부분들은 통일된 방법이 있는지 궁금해져서 추후에 추가 학습을 통해 알게된 정보가 있다면 내용 첨부하겠습니다. > 피드백 받은 의견 : 기본적인 개념들만 충실히 알고 있는 상태로 연습을 하다보면 패턴?들이 보이게 될겁니다! 너무 규칙화된 방법을 외우려고하면 나중에 복잡한 오토레이아웃을 다뤄야될때 오히려 발목을 잡힐 수도 있을것 같아요! ## 🔗 참고 링크 - Apple Developer Documentation - [UITableView](https://developer.apple.com/documentation/uikit/uitableview) - [TableViews](https://developer.apple.com/documentation/uikit/views_and_controls/table_views) - [Filling a table with data](https://developer.apple.com/documentation/uikit/views_and_controls/table_views/filling_a_table_with_data) - [Configuring the cells for your table](https://developer.apple.com/documentation/uikit/views_and_controls/table_views/configuring_the_cells_for_your_table) - [JSONDecoder](https://developer.apple.com/documentation/foundation/jsondecoder) - [Using JSON with Custom Types](https://developer.apple.com/documentation/foundation/archives_and_serialization/using_json_with_custom_types) - [Encoding and Decoding Custom Types](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) - WWDC - [Accessibility Inspector (WWDC 2019)](https://developer.apple.com/videos/play/wwdc2019/257/) - [Writing Great Accessibility Labels (WWDC 2019)](https://developer.apple.com/videos/play/wwdc2019/254/) - 위키백과 - [JSON](https://ko.wikipedia.org/wiki/JSON) - 야곰닷넷 - [LLDB 정복하기](https://yagom.net/courses/start-lldb/) --- [🔝 맨 위로 이동하기](#만국박람회)