[Project] 키오스크 KPT 회고록

2024.04.02 - [◽️ Programming/T I L] - [ProJect 일지] 키오스크 (1)

2024.04.03 - [◽️ Programming/T I L] - [ProJect 일지] 키오스크 (2)

2024.04.04 - [◽️ Programming/T I L] - [ProJect 일지] 키오스크 (3) (Compositional Layout)

2024.04.05 - [◽️ Programming/T I L] - [ProJect 일지] 키오스크 (4)

 

내가 구현한 기능

  • 홈탭 페이지
  • 상품 탭 페이지 (CollectionView , SegmentController)
  • 고객센터 탭 페이지 (TableView)
  • 디자인 디테일

 

4월 1일 ~ 7일 까지 만든 첫 팀프로젝트가 마무리 되었다. 발표를 맡아 오늘 발표를 하고 첫 팀프로젝트가 마무리 되었다.

프로젝트를 진행하면서 팀원분들을 아주 잘 만나 배울점도 많았고 문제가 있어도 착착 해결해 가면서 마무리 할 수 있었다.

진행하면서 느낀 점과 구현 해봤던 내용, 튜터님의 피드백을 정리해서 한번 돌아보자!


먼저 내가 맡았던 내용은 키오스크의 상품을 보여주는 CollectionView와 SegmentedControl 를 사용해 카테고리 별로 상품 컬렉션 뷰를 나누는 역할과 가로로 CollectionView 를 사용해 홍보 이미지를 나열한 홈 탭 페이지, 테이블 뷰를 사용한 고객센터 페이지 그리고 전반적인 앱 디자인 디테일을 손보는 역할을 맡았다.

 

CollectionView 는 처음 다뤄보는 거라 내가 한번 구현해 보고싶다고 팀원분들에게 호기롭게 얘기했지만 안해봤는데 혹시 피해를 끼치지 않을까 싶어서 속으로 걱정이 앞서긴 했다.

 

그렇지만 이런 마음을 영양분으로 사용하면 해낼 수 있을거라 생각했고 생각보다 빠른 시간에 필수 구현 요소 인 CollectionView와 SegmentedControl를 구현할 수 있었다.

 

CollectionView

CollectionView는 TableView 와 유사하지만 다른 점이 하나 있다면 flowLayout 을 통해 레이아웃을 잡아줘야 한다는 것이었다.

func createFlowLayout() -> UICollectionViewFlowLayout {
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical
    layout.itemSize = CGSize(width: 170, height: 100)
    layout.estimatedItemSize = CGSize(width: 170, height: 200)
    layout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
    return layout
}

flowLayout 을 통해 컬렉션 뷰의 셀 크기를 조절하는 방법이 테이블 뷰와 가장 다른 부분이었다.

컬렉션 뷰는 앞으로도 사용할 일이 많을 것 같으니 잊지말고 숙지하도록 하자 🙂

SegmentedControl

세그먼트 컨트롤도 컬렉션뷰와 마찬가지로 처음 써본 개념이었던 것 같다. 각각의 카테고리 마다 sender 는 배열과 비슷하게 인덱스를 가진다. 예를 들어 첫번째는 0, 4번째는 3 이런식으로..

 

이걸 활용해서 특정한 인덱스가 sender 값으로 들어갈때 즉 , 세그먼트컨트롤러 내 원하는 탭을 선택했을 경우 그 안에 상품 컬렉션 뷰의 카테고리를 나눠 맞는 카테고리 상품만 들어가도록 설정하면 연결은 생각보다 수월하게 가능했다.

@IBAction func segmentValueChanged(_ sender: UISegmentedControl) {
    switch sender.selectedSegmentIndex {
    case 0:
        searchBar.text = ""
        filteredProducts = dataManager.products.filter { $0.category == "맥북" }
    case 1:
        searchBar.text = ""
        filteredProducts = dataManager.products.filter { $0.category == "아이폰" }
    case 2:
        searchBar.text = ""
        filteredProducts = dataManager.products.filter { $0.category == "패드" }
    case 3:
        searchBar.text = ""
        filteredProducts = dataManager.products.filter { $0.category == "워치" }
    case 4:
        searchBar.text = ""
        filteredProducts = dataManager.products.filter { $0.category == "악세사리" }
    default:
        break
    }
    mainCollectionView.reloadData()
}

그 이후 마지막에 새로운 값이 들어왔으니 그 값을 우리가 볼 수 있도록 새로 고치는 메서드를 넣어주면 구현이 완료된다 🙂

NavigationBar

처음에 코드로 네비게이션바를 구현했으나, SceneDelegate 안에 구성하다보니 다른 내용이 보이지 않고 고객센터 탭만 보이는 생각치도 못한 오류가 발생했다..

 

그래서 어쩔 수 없이 코드로 구현한 내용은 삭제하고 스토리 보드를 통해 네비게이션바를 넣게 되었다.

그 이후 네비게이션바의 옵션을 코드로 설정했다.

func setupNaviBar() {
    title = "고객센터"
    
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    appearance.backgroundColor = .white
    navigationController?.navigationBar.tintColor = .black
    navigationController?.navigationBar.standardAppearance = appearance
    navigationController?.navigationBar.compactAppearance = appearance
    navigationController?.navigationBar.scrollEdgeAppearance = appearance
    navigationController?.navigationBar.prefersLargeTitles = true
}

SceneDelegate 안에 코드를 구성해 어떤 화면을 띄우게 되면 일반적으로 구성한 ViewController 보다 먼저 시스템이 인식하여 ViewController에서 구현한 내용은 볼 수 없게 되는 점을 잊지말고 꼭 체크하자 🙂

 

CompositionalLayout

홈 탭 페이지 내 가로로 구성된 컬렉션뷰 위에 헤더를 넣어주기 위해 아무리 노력을 해봐도 헤더 부분이 위로 가는게 아니라 왼쪽에 위치하는 것이었다..

 

이걸 해결하기 위해선 CompositionalLayout 을 사용해 보기로 했다.

그렇지만 CompositionalLayout의 개념은 아직 내가 다 이해하기는 어려운 개념이었다.. 이렇게 짧은 프로젝트 기간엔 더더욱 ㅠㅠ 그렇지만 일단 어떻게든 구현할 수 있도록 만들었고 추후에 CompositionalLayout 에 관해 더욱 공부해봐야 겠다고 생각했다.

let layout = UICollectionViewCompositionalLayout { (sectionIndex, _) -> NSCollectionLayoutSection? in
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    item.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8)
    
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.9), heightDimension: .absolute(500))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    
    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .groupPaging
    section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
    
    let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(50))
    let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
    header.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 24, bottom: 0, trailing: 0)
    section.boundarySupplementaryItems = [header]
    
    return section
}

프로젝트 피드백

아쉬운 반복적인 Autolayout 코드
튜터님께서는 많은 부분의 UI 를 코드로 잡다보니 각각 다른 컨트롤러 마다 많은 Autolayout 설정으로 인해 다소 반복적인 코딩을 한 부분이 확인되었고, 추후에는 상속이나 프로토콜 방식으로 해당 내용을 구현하면 더욱 깔끔하고 효율적인 코드를 작성할 수 있을거라 조언해 주셨습니다.

긍적적인 부분은 많은 탭 부분에 많은 기술 구현을 넣은 부분

다양한 탭을 활용해서 다양한 기능을 구현해 본 완성도가 아주 칭찬할 부분이라고 해주셨다. 지금은 확실한 결과물이 중요한 과정이기 보다 중요한 기능을 다양하게 많이 시도해보고 그걸 결과물로 까지 이어지는게 더욱 중요한 과정이기 때문이다. 라고 해주셨고

Compositional Layout

컴포지셔널 레이아웃은 아직 어려운 개념일 것이다. 하지만 앞으로 사용하게 될거고 유용한 기능이기에 한번 경험해본 것으로 만족하고 추후에 다시 활용해 보도록 하자 라고 마무리 코멘트를 남겨주셨습니다.


KPT 회고

Keep

  • 팀프로젝트에 Github를 처음 사용하면서 앞으로 git, github 모두 공부가 필요하다고 생각했다.
  • 원활한 역할 분담으로 프로젝트 마감 기간을 잘 맞출 수 있었고 오류 없이 진행할 수 있었다.

Problem

  • Github 머지 시 충돌로 많은 시간 소요 추후 머지 시 오류가 나지 않는 방법 생각하며 프로젝트 진행해야 함
  • 중복 코드가 많아 효율성이 떨어지는 코딩 과정

Try

  • 중복 코드를 줄이고 효율적인 코드 구성에 대한 고민
  • Compositional Layout 에 대한 추가적인 공부



사실 아직 많은 과정이 남아있지만 처음하는 팀프로젝트 발표까지 다 끝나니 마음이 좀 허하기도 했다. 그렇지만 앞으로 가야할 과정이 훨씬 더 많이 남아있으니 다시 마음을 다잡고 앞으로 가자