Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS][Neo & JeJe] MainUI and NetworkRequest #8

Conversation

HoonHaChoi
Copy link
Collaborator

@HoonHaChoi HoonHaChoi commented Apr 21, 2021

(온라인 반찬서비스 ) Side-dish

주요 구현 목록

  • 컬렉션뷰 활용해 메인화면 구성
  • 목업 API 네트워크 요청 구현
  • xib 커스텀 셀을 구현하여 화면 구성
  • 섹션별 반찬 목록 구현
  • 섹션별 헤더 표시

Study keywords

  • Combine
  • Diffable Data Source
  • MVVM Pattern
  • Xib

고민 및 해결

의존성을 주입하기 위해 DIContainer 객체를 만들어 주입을 시켜줬는데 좋은 방법일까 대한 의문입니다🤔

네트워크를 각각 요청하고 구분해서 응답 받는 요구사항이 있는데 순서가 상관없이 먼저 온 데이터에 대해 옵저버를 통해 도착한 데이터의 섹션을 전달하고 전달된 섹션의 아이템리스트를 가져와 화면에 표시하도록 해결했다

반찬 Title의 텍스트 양의 따라 동적으로 UI 조정되도록 했다

CollectionView ReusableView 뷰를 쓸때 높이를 정적으로 지정해서 사용하게되는데 높이를 동적으로 할 수 있을지 의문입니다!

HoonHaChoi and others added 29 commits April 19, 2021 14:14
Feat 1, 2 (feat-1-Initial_UI) and (feat-2-side-dish_model)
@HoonHaChoi HoonHaChoi added the review-iOS iOS 리뷰 label Apr 22, 2021
crongro pushed a commit that referenced this pull request Apr 22, 2021
crongro pushed a commit that referenced this pull request Apr 22, 2021
crongro pushed a commit that referenced this pull request Apr 22, 2021
#8

Feature/slide dish fetch & More button
resolve #8
Copy link

@ChocOZerO ChocOZerO left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중요한 개념에 대한 인지가 부족한것 같습니다.
클로저의 캡쳐링에 관한 공부를 해서 꼭 짚고 넘어가시기 바랍니다.
연관 키워드로는 weak, strong, unowned가 있습니다.

static func createDI() -> SideDishViewModel {
let networkManage = NetworkManager()
let useCase = SideDishUseCase(networkManager: networkManage)
let viewModel = SideDishViewModel(sideDishUseCase: useCase)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 DI라기 보다 생성자들을 모아놓은 느낌이네요.

}
}

enum Path: CaseIterable {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path라는 이름이 어색한거 같습니다.


static func execute(imageURLString: String) -> AnyPublisher<Data, Never> {
guard let safeURL = URL(string: imageURLString) else {
return Just(Data()).eraseToAnyPublisher()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL이 없을때 임의의 Data를 보내는건가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL이 없을때는 빈 데이터를 내보내도록 했습니다!

return URLSession.shared.dataTaskPublisher(for: safeURL)
.map({$0.data})
.catch({ _ in
return Just(Data()).eraseToAnyPublisher()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기도 catch에서 기본 생성자를 사용하는데 어떤 정책을 원한건지 궁금하네요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지를 불러오지 못한것에 대한 처리를 빈 데이터를 줌으로서 화면에 이미지가 보여지지 않게 하려고 이렇게 작성을 했습니다

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지가 보이지 않기위한 정책으로는 빈 데이터를 주는것보다는 nil이나 객체 내에서 hidden등을 가져갈 수 있게 하는 등의 정책이 더 나아보입니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 알겠습니다!

func execute(path: Path) -> AnyPublisher<SideDishes, NetworkError>
}

class SideDishUseCase: SideDishProtocol {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SideDish의 UseCase가 excute라는 이름의 함수로만 진행되다보니 어떤 역할을 하는앤지 잘 모르겠어요. 어떻게 관리하면 좋을까요?

Copy link
Collaborator Author

@HoonHaChoi HoonHaChoi Apr 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좀 더 명확하게 함수명을 바꾸면 좋을거 같습니다

import UIKit

enum Alert {
static func controller(title: String) -> UIAlertController {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런식의 factory를 만드는거 좋네요. Factory라는 이름을 사용했으니 팁을 드리면 보통 팩토리 함수는 make나 create로 많이 사용됩니다.

}

func setImage(itemURLString: String) {
ImageUseCase.execute(imageURLString: itemURLString)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image의 UseCase는 무엇일까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cell의 이미지 네트워크 요청을 UseCase를 만들어 처리한 것인데 처리 방법에 대해 고민이 많습니다..ㅠ

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImageLoader 같은 도우미를 만드는것도 괜찮을거 같고, excute라는 함수명 대신 download등의 이름으로 바꾸기만 해도 덜 혼동될것 같습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아아 네이밍이 좀더 명확한게 좋겠군요

private func hideView<T : UIView>(UI : T) {
UI.isHidden = true
}
private func showView<T : UIView>(UI : T) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수의 argument label은 보통 소문자로 시작합니다. 여기에선 소문자 ui 혹은 view를 사용하던가 _ 를 활용하여 parameter name을 없애는게 더 좋을 것 같네요


class SideDishViewController: UIViewController {

@IBOutlet weak var SideDishCollectionView: UICollectionView!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프로퍼티는 소문자로 시작하는게 일반적인 규칙입니다.

@ChocOZerO
Copy link

고민거리를 답변 안했었군요.
의존성 주입을 공부할땐 할 땐 의존성 주입을 위해 코드를 짠다기 보다는 OOP의 관점으로 코드를 작성하다보면 자연스럽게 의존성 주입이 필요하다고 생각이 들게 공부하는게 더 나을거 같습니다.
CollectionView나 TableView에서는 높이를 동적으로 조정하게하는 세팅이 있습니다. 이미지같은게 사이즈가 다양하게 와도 같은 cell로 처리하는걸 보면 알 수 있죠.

@HoonHaChoi
Copy link
Collaborator Author

제가 아직 동적으로 하는 것에 대해 못 찾았던 거 같습니다 좀 더 찾아보고 적용해보도록 하겠습니다!

DIContainer의 목표는 IOC Container처럼 한 곳에서 의존성을 관리하고 싶은 마음에 작성했었습니다…. ㅎㅎ
더 깊이 고민도 해보고 의존성 주입에 관해 공부해야겠네요

혹시 구조적인 부분에서 아쉽거나, 부족한 점도 피드백 해주실 수 있을까요??
아직 부족한 점이 많다고 느끼고 현업에서 일하고 계신 분들의 시각도 궁금합니다!

pay-napster-x pushed a commit that referenced this pull request Apr 26, 2021
TableView와 기본 뼈대가 되는 Cell을 Storyboard에 추가
pay-napster-x pushed a commit that referenced this pull request Apr 26, 2021
label 업데이트 함수 작성. 후에 수정 필요
pay-napster-x pushed a commit that referenced this pull request Apr 26, 2021
테이블 뷰와 DataSource 연결
pay-napster-x pushed a commit that referenced this pull request Apr 26, 2021
테이블 뷰와 delegate 연결 커스텀 헤더 지정
pay-napster-x pushed a commit that referenced this pull request Apr 26, 2021
Feature/메인 화면 UI 구성 (#8)
pay-napster-x pushed a commit that referenced this pull request Apr 26, 2021
headerView의 백그라운드색 지정, init함수 수정
crongro pushed a commit that referenced this pull request Apr 26, 2021
* [#1] init: 🎉 개발 환경 구축

* [#3] feat: ✨ Header 만들기

* [#5] feat: ✨ BestTab UI 구현

- BestTab UI
- 상수 파일
    - const.js
- 재사용 컴포넌트
    - Label.jsx
    - ItemCard.jsx

* [#7] feat: ✨ Slide UI 구현

- App.jsx
    - SlideContainer import
- BestItem.jsx
    - 삭제 (미사용)
- BestItems.jsx
    - ItemCard prop 추가
- BestTab.jsx
    - 스타일 수정
- SlideContainer.jsx
    - UI 구현
- SlideItems.jsx
    - UI 구현
- SlideArrowBtn.jsx
    - UI 구현
- ItemCard.jsx
    - 스타일 수정
    - prop 추가
- Label.jsx
    - prop 추가
    - 기본 값 추가

* [#8] feat: ✨ ShowMoreBtn UI 구현

- App.js
    - ShowMoreBtn import
- ShowMoreBtn.jsx
    - UI 구현

* [#10] feat: ✨ Header Dropdown 구현

- App.js
    - Header 경로 수정
- Header.jsx
    - 경로 변경
    - HeaderLeft & Right 분리
- HeaderLeft.jsx
    - 컴포넌트화
    - Navigations 컴포넌트화
- HeaderRight.jsx
    - 컴포넌트화
- Navigations.jsx
    - 컴포넌트화
    - Dropdown 구현

* [#13] feat: ✨ API에 fetch 요청 로직 구현

* [#13] feat: ✨ API 요청, 베스트 기능구현
- BestItems.jsx
   - API 데이터 동기화
- BestTab.jsx
   - useState, useEffect, API 요청
- BestTabContainer.jsx
   - API 데이터 동기화
- BestTabNavigator.jsx
   - API 데이터 동기화
- ItemCard.jsx
   - prop 변경
- Label.jsx
  - COLOR변수 추가

* [#15] feat: ✨ 상세 modal 페이지 UI 구현
- App.js
   - PopUpContainer import
-  PopUpContainer.jsx
   - UI 구현
- PopUpImages.jsx
   - UI 구현
- PopUpInformations.jsx
   - UI 구현

Co-authored-by: kowoohyuk <kowoohyuk91@gmail.com>
Malloc72P pushed a commit that referenced this pull request Apr 27, 2021
@ChocOZerO
Copy link

제가 아직 동적으로 하는 것에 대해 못 찾았던 거 같습니다 좀 더 찾아보고 적용해보도록 하겠습니다!

DIContainer의 목표는 IOC Container처럼 한 곳에서 의존성을 관리하고 싶은 마음에 작성했었습니다…. ㅎㅎ
더 깊이 고민도 해보고 의존성 주입에 관해 공부해야겠네요

혹시 구조적인 부분에서 아쉽거나, 부족한 점도 피드백 해주실 수 있을까요??
아직 부족한 점이 많다고 느끼고 현업에서 일하고 계신 분들의 시각도 궁금합니다!

앱 설계에 정답은 없습니다. 팀 혹은 개인의 전략이기 때문이죠.
중요한건 객체간의 겹합도를 낮추고 변화율에 따라 분리하는 것입니다. 거기에 데이터의 흐름을 입히면 우리가 흔히 접하는 설계패턴이 됩니다.
앱마다의 복잡도는 다 다르기때문에 한가지 패턴을 고수하는 것도 문제가 생길 여지가 있다고 봅니다.
객체를 만들때 그 객체의 책임과 역할이 어디까지인가를 명확히 하는 연습을 하면 좋을 것 같습니다.

ksundong pushed a commit that referenced this pull request Apr 28, 2021
- 응답을 위한 DTO 객체 간단 추가

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
- 임베디드를 사용해 item 필드를 간략화

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
- 원화 표기를 위한 포맷 추가

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
- 추가 되지 않았던 필드를 iOS와 합의하에 추가

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
- Item 객체에서 ItemDetail 객체를 얻을 수 있습니다.

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
- Item에서 ItemSummary를 가져올 수 있습니다.

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
- 모든 파일에 자동 포매팅 적용

issue: #8
ksundong pushed a commit that referenced this pull request Apr 28, 2021
[BE] DTO 설계 
closes issue #8
@HoonHaChoi HoonHaChoi merged commit 7a691ae into codesquad-members-2021:team-4 Apr 30, 2021
crongro pushed a commit that referenced this pull request May 4, 2021
* [#1] init: 🎉 개발 환경 구축

* [#3] feat: ✨ Header 만들기

* [#5] feat: ✨ BestTab UI 구현

- BestTab UI
- 상수 파일
    - const.js
- 재사용 컴포넌트
    - Label.jsx
    - ItemCard.jsx

* [#7] feat: ✨ Slide UI 구현

- App.jsx
    - SlideContainer import
- BestItem.jsx
    - 삭제 (미사용)
- BestItems.jsx
    - ItemCard prop 추가
- BestTab.jsx
    - 스타일 수정
- SlideContainer.jsx
    - UI 구현
- SlideItems.jsx
    - UI 구현
- SlideArrowBtn.jsx
    - UI 구현
- ItemCard.jsx
    - 스타일 수정
    - prop 추가
- Label.jsx
    - prop 추가
    - 기본 값 추가

* [#8] feat: ✨ ShowMoreBtn UI 구현

- App.js
    - ShowMoreBtn import
- ShowMoreBtn.jsx
    - UI 구현

* [#10] feat: ✨ Header Dropdown 구현

- App.js
    - Header 경로 수정
- Header.jsx
    - 경로 변경
    - HeaderLeft & Right 분리
- HeaderLeft.jsx
    - 컴포넌트화
    - Navigations 컴포넌트화
- HeaderRight.jsx
    - 컴포넌트화
- Navigations.jsx
    - 컴포넌트화
    - Dropdown 구현

* [#13] feat: ✨ API에 fetch 요청 로직 구현

* [#13] feat: ✨ API 요청, 베스트 기능구현
- BestItems.jsx
   - API 데이터 동기화
- BestTab.jsx
   - useState, useEffect, API 요청
- BestTabContainer.jsx
   - API 데이터 동기화
- BestTabNavigator.jsx
   - API 데이터 동기화
- ItemCard.jsx
   - prop 변경
- Label.jsx
  - COLOR변수 추가

* [#15] feat: ✨ 상세 modal 페이지 UI 구현
- App.js
   - PopUpContainer import
-  PopUpContainer.jsx
   - UI 구현
- PopUpImages.jsx
   - UI 구현
- PopUpInformations.jsx
   - UI 구현

* [#16] feat: ✨ 모달 페이지 이벤트 구현중

* [#16] feat: ✨ 수량정보 컴포넌트 분리

* [#19] refactor: 🔨 리팩토링, 부족한 부분 추가 구현
- 파일 및 폴더 구조 변경
   - common 폴더 생성
- Context.jsx
   - useContext 사용하여 prop drilling 개선
- 팝업 이벤트 구현
   - 수량 변경
   - 주문하기
   - 주문결과 안내 메시지 UI

* [#19] refactor: 🔨 리팩토링

* [#17] feat: ✨ dj-slider 폴더구조 구축

* [#17] feat: ✨ 슬라이드 1/2 구현 중

* [#23] refactor: 🔨 코드 리뷰 코멘트 반영 및 개선

* [#17] feat: ✨ 슬라이드 구현중/일부사항 수정
- util.js
   - price에 comma 붙이는 기능 구현
- PopUpItemCountContainer.jsx
   - price에 comma 붙이는 기능 import
- ItemCard.jsx
   - price에 comma 붙이는 기능 import
   - 이미지 background로 수정
- Label.jsx
   - 라벨 배경색상 적용

* [#17] feat: ✨ 슬라이드 구현중

- 모듈화
   - 시연을 위한 기능 구현을 위해 보류

* [#25] feat: ✨ 슬라이드 2/2 구현, API 데이터 동기화

- 슬라이드 명칭을 캐로셀로 변경
- API 데이터 동기화
- 캐로셀의 ItemCard를 children으로 변경
   - 모듈화를 위함!
- 아이템카드 mini, large 프로퍼티 추가
- 상세모달 캐로셀 추가
- 상세모달 스크롤 추가
- 모든 카테고리 보기 기능 구현

* [#27] feat: ✨ BestTab Skeleton UI 만들기

- Main.jsx
   - 시연을 위한 loop 설정 추가
- BestTab.jsx
   - SkeletonTab import
- BestTabNavigator.jsx
   - 주석 제거
- SkeletonTab.jsx
   - Skeleton UI 구현
- DicoJsonCarousel.jsx
   - Carousel 구현중

* [#29] feat: ✨ PopUp Skeleton UI 만들기

- Context.jsx
   - 주석 제거
- BestTab.jsx
   - 주석 제거
- PopUpContainer.jsx
   - Skeleton import
- PopUpItemsSlide.jsx
   - 주석 제거
- SkeletonPopUpContainerBody.jsx
   - Skeleton UI 구현

* feat: ✨ carousel loop 기능 구현

* [#31] feat: ✨ README.md 작성완료

Co-authored-by: kowoohyuk <kowoohyuk91@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
review-iOS iOS 리뷰
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants