Skip to content

7주차 과제#6

Open
limtjdghks wants to merge 17 commits into
mainfrom
week07
Open

7주차 과제#6
limtjdghks wants to merge 17 commits into
mainfrom
week07

Conversation

@limtjdghks
Copy link
Copy Markdown
Collaborator

@limtjdghks limtjdghks commented May 29, 2026

🔗 7주차 과제

📄 작업 내용

기본과제

  • 왓챠 UI, 화면설계서를 보고 다음과 같은 기능/view를 구현해주세요.
    • 1) 탭바를 구현해주세요. ‘구독’ 탭이 아닌 다른 탭들은 내용이 비어있어도 좋습니다. 탭바 간 이동은 가능해야 합니다.
    • 2) 피그마에 있는 가로 스크롤 View들을 모두 구현해주세요.
    • 3) ‘메인으로’ 버튼을 이번 과제의 메인 뷰로 연결해주세요.

심화과제

  • 스티키 헤더를 구현해주세요.
  • 신작 업데이트 플로팅 뷰를 구현해주세요.
  • Welcome View를 구현해서, 메인 뷰로 넘어가는 네비게이션까지 함께 구현해주세요.
구현 내용 IPhone 17 pro IPhone 13 mini
GIF

💻 주요 코드 설명 및 Trouble Shooting 🚀

탭바

RootView

  • TabView를 사용하여 탭바를 구현하였습니다
  • Info.plist에서 Liquid Glass를 사용하지 않도록 설정하였습니다
            TabView(selection: $selectedTab) {
                SubscribeView().tag(0)
                    .tabItem {
                        Label("구독", image: "Watcha")
                    }
                PurchaseView().tag(1)
                    .tabItem {
                        Label("개별 구매", image: "Category")
                    }
                WebtoonView().tag(2)
                    .tabItem {
                        Label("웹툰", image: "Wallet")
                    }
                SearchView().tag(3)
                    .tabItem {
                        Label("찾기", image: "Search")
                    }
                LibraryView().tag(4)
                    .tabItem {
                        Label("보관함", image: "Folder")
                    }
            }
  • 헤더에 각 탭의 제목을 넘겨주기 위해서 selectedTab을 state로 선언하였습니다
  • 각 탭을 선택하면 selectedTab에 tag 값을 넘겨줍니다.
  • 헤더의 title을 배열로 선언하고, 저장된 state값으로 index를 선택하여 텍스트를 설정하도록 하였습니다
@State private var selectedTab = 0

    var body: some View {
        VStack(spacing: 0) {
            CommonHeader(title: ["구독", "개별 구매", "웹툰", "찾기", "보관함"][selectedTab])
            TabView(selection: $selectedTab) {
                SubscribeView().tag(0)
                    .tabItem {
                        Label("구독", image: "Watcha")
                    }

가로 스크롤 뷰 구현

  • 각 섹션에 사용 할 아이템의 카드뷰를 구현하여 스크롤뷰에서 ForEach를 통해서 데이터를 출력하도록 구현하였습니다
struct NewContentCardView: View {
    ...
}
struct WatchaPartyCardView: View {
    ...
}
struct WatchaPartyScrollView: View {
    let item: [WatchaPartyModel]
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 12) {
                ForEach(item) { item in
                    WatchaPartyCardView(item: item)
                }
            }
            .padding(.horizontal, 17)
        }
    }
}

웰컴 뷰에서 메인 뷰로 이동

  • 웰컴 뷰를 구현하고 onMainTapped를 앱 진입접에서 받도록 구현하였습니다
struct WelcomeView: View {
    var onMainTapped: () -> Void = {}

    var body: some View {
        ZStack {
            ...
                Button(action: onMainTapped) {
                    Text("메인으로")
                        .font(.medium)
                        .foregroundStyle(.white)
                        .frame(width: 331, height: 56)
                        .background(.watchaPink)
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                }
                .padding(.bottom, 13)
            }
        }
    }
}
  • showMain상태를 선언해서 루트 뷰를 보여줄지, 웰컴 뷰를 보여줄지 정하도록 하였습니다
  • 웰컴뷰 onMainTapped 함수에 showMain을 true로 바꾸도록 설정하여 버튼 클릭시 루트뷰로 이동하도록 구현하였습니다
@main
struct SwiftUI_WatchaApp: App {
    @State private var showMain = false

    var body: some Scene {
        WindowGroup {
            if showMain {
                RootView()
            } else {
                WelcomeView {
                    showMain = true
                }
            }
        }
    }
}

👀 To Reviewers

  • 저의 머리로는 루트 뷰를 변경해줄 때 상태를 이용하는 방법이 최선이었습니다 (웹 하던 습관)
  • 어떻게 하는 방법이 좋았을까요

@limtjdghks limtjdghks self-assigned this May 29, 2026
@limtjdghks limtjdghks requested review from kyooonnnggg, ser0kim and y-eonee and removed request for kyooonnnggg, ser0kim and y-eonee May 29, 2026 12:02
Copy link
Copy Markdown

@kyooonnnggg kyooonnnggg left a comment

Choose a reason for hiding this comment

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

구현해야 하는 섹션별로 스크롤, 카드, 섹션 컴포넌트를 분리해주셨더라고요.
분리를 자세히 한 만큼 파일별 코드의 역할이 명확하고 간결해서 보기에 정말 편했습니다.
저는 섹션별로 구분하고 타이틀 정도만 분리했는데 더 해보아야겠단 생각이 들었어요.

하단 탭바에 대해서 따로 파일 분리를 하고 그 파일을 루트뷰에 불러오시는 방법도 함께 제안드리고 싶습니당.

7주차 과제 고생하셨어요 !! 👍🏾

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

저같경 . . tabItem을 반복하고 싶지 않아서 tabContent라는 함수를 따로 만들어주었습니다.
기능은 동일하지만 깔끔하게 적어보고 싶어서 넣었는데용 참고해보셔도 조을 것 같습니다 ㅎㅎ

 TabView {
            tabContent(SubscriptionView(), icon: "Subscribe", title: "구독")
            tabContent(PurchaseView(), icon: "Category", title: "개별 구매")
            tabContent(WebtoonView(), icon: "Wallet", title: "웹툰")
            tabContent(SearchView(), icon: "Search", title: "찾기")
            tabContent(LibraryView(), icon: "Folder", title: "보관함")
        }

private func tabContent<Content: View>(
        _ content: Content,
        icon: String,
        title: String
    ) -> some View {
        content
            .toolbarBackground(Color("appBlack"), for: .tabBar)
            .toolbarBackground(.visible, for: .tabBar)
            .tabItem {
                Image(icon)
                    .renderingMode(.template)
                Text(title)
            }
    }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

와 저랑 생각한게 완전히 똑같아요. (신기) 컴포넌트 빼기 장인으로 인정드립니다 ^^

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Model에 대한 파일 분리를 각각 하신 이유가 있는지 궁금합니다!!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

아!!!!!!!!!!!! 패딩 여기서 넣을걸... 훨씬 깔끔하네요........
저는 각 컴포넌트에 넣어줘서 코드가 더 복잡해진 것 같아요 완전 광명 찾음

.tint(.watchaWhite)
.toolbarBackground(Color.black, for: .tabBar)
.toolbarBackground(.visible, for: .tabBar)
.toolbarColorScheme(.dark, for: .tabBar)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

.background(Color("appBlack").ignoresSafeArea())

저도 앱 진입점에서 탭바 백그라운드 색상이 떴던 문제가 있었는데 요거 넣으니까 해결 됐던 거 같아여 시도해보시길

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Watgorithm으로 네이밍 제안드립니다. . . 어때욤 . . .

Copy link
Copy Markdown

@ser0kim ser0kim left a comment

Choose a reason for hiding this comment

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

꼼꼼하게 구현해주신 거 같아서 코드리뷰하면서 많이 배웠습니다! 파일 분리를 어떻게 해야할지 감이 안와서 잘 못했는데, 참고해서 해보겠습니다~!! 졸프랑 병행하시는 와중에도 고생 많으셨어요!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

이런식으로 컴포넌트로 빼셨군요..! 참고해서 저도 빼보겠습니다 !! mainTitle, subTitle, showMoreButton 조합으로 다양한 헤더 케이스를 하나의 컴포넌트에서 처리할 수 있게 설계한 점이 인상적이었습니다. 재사용성이 높아 보여요!

import SwiftUI

struct WelcomeView: View {
var onMainTapped: () -> Void = {}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

👍 버튼 액션을 클로저로 분리해두신 구조 좋은 것 같습니다!

}

var body: some View {
HStack() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

HStack은 기본 이니셜라이저를 사용할 경우 괄호를 생략해도 동일하게 동작해서 괄호 삭제해도 괜찮을 것 같습니다 😊

Spacer()

if showMoreButton {
Button(action: {}) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

현재 버튼 액션이 비어 있는 부분이 많은데 이어지는 액션이 없어서 그런거지요??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7주차 과제

3 participants