Skip to content

[FEAT] 로그인·회원가입 플로우 디자인 명세 반영 및 디자인 컴포넌트 구현#39

Merged
khyeji98 merged 65 commits into
developfrom
feature/#35
May 21, 2026
Merged

[FEAT] 로그인·회원가입 플로우 디자인 명세 반영 및 디자인 컴포넌트 구현#39
khyeji98 merged 65 commits into
developfrom
feature/#35

Conversation

@khyeji98
Copy link
Copy Markdown
Collaborator

@khyeji98 khyeji98 commented May 19, 2026

Summary

  • 로그인·회원가입 플로우 화면에 디자인 명세 반영 (바텀시트 제외)
  • DesignSystem 컴포넌트 구현 (TextInput, Avatar, NavigationMain, NavigationPage, BangawoText, Menu, ActionButton, Toast 등)
  • 이미지 에셋 추가 (ic_arrow_big_right_24, ic_album_24, ic_circle_exclamation 외 다수)

Changes

회원가입·로그인 플로우 UI

  • LoginView에 로그인 3D 이미지 적용
  • TermsAgreementView에 DesignSystem 컴포넌트 적용 및 네비게이션 액션 추가
  • ProfileInputFeature 이름 입력 및 프로필 이미지 선택 UI 개편
  • Terms/Profile 화면 뒤로가기 delegate 처리 추가
  • StationSearchSheet DesignSystem 기반 UI 개편
  • 메뉴 오버레이 부모 뷰 이동 및 네비게이션 바 숨김 통합

미반영: 바텀시트 화면은 아직 디자인 명세를 반영하지 않았습니다.

DesignSystem 컴포넌트

  • TextInput 컴포넌트 추가
  • Avatar 컴포넌트 구현 (localImage 타입, edit 버튼 액션 포함)
  • NavigationMain, NavigationPage 컴포넌트 구현
  • NavigationIconButtonNavigationIcon enum 타입화
  • BangawoText 컴포넌트 구현
  • Menu 컴포넌트 구현 (선택 상태, 아이콘 색상 커스터마이징 지원)
  • ActionButton 컴포넌트 구현
  • Toast 컴포넌트 구현
  • Asset 컴포넌트 구현
  • CheckboxRow API modifier → init 파라미터 방식으로 변경
  • TopHero description optional 변경 및 이미지 표시 수정
  • TextButton 불필요한 padding 제거

에셋

  • ic_arrow_big_right_24, ic_arrow_big_left_24, ic_album_24, ic_circle_exclamation, ic_star_24 등 이미지 에셋 추가

Demo

데모 영상을 여기에 첨부해 주세요.

Test plan

  • 로그인 화면 UI 정상 표시
  • 약관 동의 화면 DesignSystem 컴포넌트 적용 및 뒤로가기 동작
  • 프로필 입력 화면 이름 입력 및 이미지 선택 UI
  • 역 검색 시트 UI 정상 동작
  • 추가된 DesignSystem 컴포넌트 DesignSystemDemo에서 확인

To Reviewer

바텀시트 화면은 디자인 명세가 아직 확정되지 않아 이번 PR에는 포함하지 않았습니다.
컴포넌트 API 설계에 대한 의견이 있으시면 자유롭게 코멘트 부탁드립니다.

Closes #35
Closes #27
Closes #30
Closes #31
Closes #34
Closes #26
Closes #28
Closes #29

khyeji98 added 30 commits May 19, 2026 13:41
타이포·색상 명세 반영, Button+ButtonStyle → View+DragGesture 전환
@khyeji98 khyeji98 self-assigned this May 19, 2026
@khyeji98 khyeji98 requested a review from duthd3 May 19, 2026 20:58
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Design System 컴포넌트 도입으로 인증 플로우 UI가 개편되었으며, 키보드 dismiss, 뒤로가기 액션 등 사용자 경험 개선을 위한 기능들이 추가되었습니다. 전반적으로 새로운 Design System 컴포넌트들의 API 설계 및 구현이 잘 되어 있으며, Preview를 통한 다양한 상태 확인도 충실하게 이루어졌습니다. 한 가지, Feature 간 데이터 전달 시 파라미터 이름의 일관성 유지가 필요합니다.

case let .path(.element(id: _, action: .profile(.delegate(.proceedToDepartureSearch(nickname))))):
state.path.append(.departure(DepartureSearchFeature.State(nickname: nickname)))
case let .path(.element(id: _, action: .profile(.delegate(.proceedToDepartureSearch(name))))):
state.path.append(.departure(DepartureSearchFeature.State(nickname: name)))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 [P3] Minor

ProfileInputFeature.State에서 nicknamename으로 변경되었으므로, DepartureSearchFeature.State의 이니셜라이저 파라미터도 nickname 대신 name으로 일관되게 사용하는 것이 좋습니다. 현재 코드에서는 새로운 name 값을 nickname이라는 파라미터에 할당하고 있어 혼동을 줄 수 있습니다.

Suggested change
state.path.append(.departure(DepartureSearchFeature.State(nickname: name)))
state.path.append(.departure(DepartureSearchFeature.State(name: name)))

@khyeji98 khyeji98 added feature New feature or request refactor add labels May 19, 2026
@github-actions
Copy link
Copy Markdown

{
"summary": "전반적으로 디자인 명세가 잘 반영되었으며, DesignSystem 컴포넌트들이 Clean Architecture 및 SwiftUI/TCA 컨벤션에 맞게 잘 구현되었습니다. 특히 BangawoPreview와 새로운 CustomSizeFont 타입 정의, 그리고 관련 .pretendardCustomFont View Extension이 도입되어 일관된 타이포그래피 적용에 큰 도움이 될 것으로 보입니다. 다만, 일부 뷰에서 텍스트 스타일 적용 시 BangawoText 또는 업데이트된 pretendardCustomFont 대신 기존 방식인 pretendardFont와 수동 lineSpacing을 직접 사용하는 부분이 발견되었습니다. 이는 DesignSystem의 타이포그래피 일관성을 저해할 수 있으므로, 가능한 경우 새로운 컴포넌트 또는 익스텐션을 사용하는 것을 권장합니다.",
"comments": [
{
"path": "Projects/Presentation/AuthFlowFeature/Sources/Login/LoginView.swift",
"line": 61,
"code_snippet": " .pretendardFont(family: .SemiBold, size: 16)",
"body": "🟡 [P3] Minor\n\n새롭게 정의된 BangawoText 컴포넌트 또는 업데이트된 pretendardCustomFont View Extension을 사용하여 DesignSystem의 타이포그래피 규칙을 일관되게 적용하는 것이 좋습니다. 현재 pretendardFont와 수동 lineSpacing을 직접 사용하는 방식은 DesignSystem에서 의도하는 CustomSizeFont의 라인 높이와 자간 값을 적용하지 않을 수 있습니다.\n\n```suggestion\n BangawoText("카카오로 3초 만에 로그인", textStyle: .labelLarge)\n```"
},
{
"path": "Projects/Presentation/AuthFlowFeature/Sources/Login/LoginView.swift",
"line": 83,
"code_snippet": " Text("네이버 로그인")",
"body": "🟡 [P3] Minor\n\n새롭게 정의된 BangawoText 컴포넌트 또는 업데이트된 pretendardCustomFont View Extension을 사용하여 DesignSystem의 타이포그래피 규칙을 일관되게 적용하는 것이 좋습니다. 현재 pretendardFont와 수동 lineSpacing을 직접 사용하는 방식은 DesignSystem에서 의도하는 CustomSizeFont의 라인 높이와 자간 값을 적용하지 않을 수 있습니다.\n\n```suggestion\n BangawoText("네이버 로그인", textStyle: .labelLarge)\n```"
},
{
"path": "Projects/Presentation/AuthFlowFeature/Sources/Login/LoginView.swift",
"line": 104,
"code_snippet": " Text("Apple로 로그인")",
"body": "🟡 [P3] Minor\n\n새롭게 정의된 BangawoText 컴포넌트 또는 업데이트된 pretendardCustomFont View Extension을 사용하여 DesignSystem의 타이포그래피 규칙을 일관되게 적용하는 것이 좋습니다. 현재 pretendardFont와 수동 lineSpacing을 직접 사용하는 방식은 DesignSystem에서 의도하는 CustomSizeFont의 라인 높이와 자간 값을 적용하지 않을 수 있습니다.\n\n```suggestion\n BangawoText("Apple로 로그인", textStyle: .labelLarge)\n```"
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Navigation/NavigationMain.swift",
"line": 32,
"code_snippet": " .pretendardFont(family: .Medium, size: Typography.typographySize500)",
"body": "🟡 [P3] Minor\n\n새롭게 정의된 BangawoText 컴포넌트를 사용하여 DesignSystem의 타이포그래피 규칙을 일관되게 적용하는 것이 좋습니다. NavigationMain의 타이틀은 CustomSizeFont.headingSmall에 해당하므로, 해당 스타일을 사용하도록 변경을 고려해 주세요.\n\n```suggestion\n BangawoText(title, textStyle: .headingSmall)\n```"
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Navigation/NavigationPage.swift",
"line": 49,
"code_snippet": " .pretendardFont(family: .Medium, size: Typography.typographySize400)",
"body": "🟡 [P3] Minor\n\n새롭게 정의된 BangawoText 컴포넌트를 사용하여 DesignSystem의 타이포그래피 규칙을 일관되게 적용하는 것이 좋습니다. NavigationPage의 타이틀은 CustomSizeFont.titleLarge에 해당하므로, 해당 스타일을 사용하도록 변경을 고려해 주세요.\n\n```suggestion\n BangawoText(title, textStyle: .titleLarge)\n```"
}
]
}

Copy link
Copy Markdown
Collaborator

@duthd3 duthd3 left a comment

Choose a reason for hiding this comment

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

제미나이 리뷰만 수정할 거 있으면 수정해주세용

@github-actions
Copy link
Copy Markdown

{
"summary": "새로운 DesignSystem 컴포넌트들이 프로젝트 전반에 걸쳐 성공적으로 통합되었으며, TCA, SwiftUI, Swift 코드 품질 가이드라인을 잘 준수하고 있습니다. 특히, 컴포넌트 분리, 상태 관리, 커스텀 폰트 처리, 그리고 데모 뷰 구현 방식이 매우 인상적입니다. 전반적으로 코드 품질이 높습니다.",
"comments": [
{
"path": "Projects/Presentation/AuthFlowFeature/Sources/DepartureSearch/DepartureSearchView.swift",
"line": 105,
"code_snippet": " text: .constant(store.selectedStation?.name ?? "")",
"body": "🔵 [P4] Readability\n\ntext 파라미터에 긴 조건부 nil 병합 연산자 ?? "" 대신 store.selectedStation?.name 만을 전달하고, SearchField 내부에서 플레이스홀더를 처리하는 방식이 더 명확할 수 있습니다. 현재 방식도 동작하지만, SearchField의 책임이 증가하는 것을 피하기 위한 제안입니다.\n\nsuggestion\n text: .constant(store.selectedStation?.name)\n"
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/ActionButton/ActionButton.swift",
"line": 101,
"code_snippet": " withAnimation(.spring(duration: 0.4, bounce: 0.1)) {",
"body": "⚪ [P5] Nitpick\n\n애니메이션 지속 시간 및 바운스 값은 DesignSystem의 Animation 또는 Timing 토큰으로 정의하여 사용하는 것이 좋습니다. 이는 일관된 사용자 경험을 제공하고 향후 디자인 변경 시 유지보수성을 높이는 데 도움이 됩니다. 현재는 하드코딩되어 있습니다."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/ActionButton/ActionButton.swift",
"line": 105,
"code_snippet": " do { try await Task.sleep(for: .seconds(3)) } catch { return }",
"body": "⚪ [P5] Nitpick\n\n매직 넘버인 3초는 DesignSystem의 Duration 또는 Timing 토큰으로 정의하여 사용하는 것이 좋습니다. 이는 애니메이션 및 타이밍과 관련된 값을 일관되게 관리하고 유지보수성을 향상시키는 데 도움이 됩니다."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Button/BangawoButton.swift",
"line": 127,
"code_snippet": " if isKeyboardAttached { return UIScreen.screenWidth }",
"body": "🔵 [P4] Readability\n\nUIScreen.screenWidth는 전역적으로 화면 너비를 가져오므로, GeometryReaderLayout 프로토콜을 사용하여 뷰의 부모 컨테이너가 제공하는 너비를 사용하는 것이 SwiftUI의 레이아웃 시스템에 더 잘 부합합니다. 이는 특정 디바이스 크기에 묶이지 않는 유연한 레이아웃을 제공하는 데 도움이 됩니다. 현재는 키보드 부착 시에만 사용되므로 큰 문제는 없지만, 일반적인 컴포넌트에서는 고려할 필요가 있습니다."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Checkbox/Checkbox.swift",
"line": 40,
"code_snippet": " switch (variant, state, size) {",
"body": "⚪ [P5] Nitpick\n\nImage.Asset은 이미 DesignSystem 모듈에 정의되어 있으므로, Image 접두사는 불필요합니다. .Asset으로 직접 접근하는 것이 더 간결합니다.\n\nsuggestion\n switch (variant, state, size) {\n case (.circle, .enabled, .small): Asset.icCheckboxCircleEnabledSm\n case (.circle, .disabled, .small): Asset.icCheckboxCircleDisabledSm\n case (.circle, .enabled, .medium): Asset.icCheckboxCircleEnabledMd\n case (.circle, .disabled, .medium): Asset.icCheckboxCircleDisabledMd\n case (.ghost, .enabled, .small): Asset.icCheckboxGhostEnabledSm\n case (.ghost, .disabled, .small): Asset.icCheckboxGhostDisabledSm\n case (.ghost, .enabled, .medium): Asset.icCheckboxGhostEnabledMd\n case (.ghost, .disabled, .medium): Asset.icCheckboxGhostDisabledMd\n }\n"
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Menu/Menu.swift",
"line": 24,
"code_snippet": " self.items = Array(items.prefix(5))",
"body": "🔵 [P4] Readability\n\n메뉴 아이템 개수를 5개로 제한하는 것은 DesignSystem의 제약사항으로 보입니다. 이 제한이 명확한 디자인/기능적 이유가 있다면 해당 제약에 대한 설명이나 토큰화된 상수를 사용하는 것이 좋습니다. 또한, 이 제한을 컴포넌트 init에서 직접 강제하는 것보다, 상위 뷰에서 items 배열을 Menu에 전달하기 전에 처리하도록 유도하는 것이 Menu 컴포넌트의 유연성을 높일 수 있습니다."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Navigation/NavigationIconItem.swift",
"line": 17,
"code_snippet": " switch self {",
"body": "⚪ [P5] Nitpick\n\nImage.Asset은 이미 DesignSystem 모듈에 정의되어 있으므로, Image 접두사는 불필요합니다. .Asset으로 직접 접근하는 것이 더 간결합니다.\n\nsuggestion\n switch self {\n case .userPlus24: return Asset.icUserPlus24\n case .user24: return Asset.icUser24\n case .bell24: return Asset.icBell24\n case .verticalMenu24: return Asset.icVerticalMenu24\n case .arrowBigRight24: return Asset.icArrowBigRight24\n case .close24: return Asset.icClose24\n }\n"
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Navigation/NavigationMain.swift",
"line": 25,
"code_snippet": " self.trailingIcons = Array(trailingIcons.prefix(3))",
"body": "🔵 [P4] Readability\n\n트레일링 아이콘 개수를 3개로 제한하는 것은 DesignSystem의 제약사항으로 보입니다. 이 제한이 명확한 디자인/기능적 이유가 있다면 해당 제약에 대한 설명이나 토큰화된 상수를 사용하는 것이 좋습니다. 또한, 이 제한을 컴포넌트 init에서 직접 강제하는 것보다, 상위 뷰에서 trailingIcons 배열을 NavigationMain에 전달하기 전에 처리하도록 유도하는 것이 컴포넌트의 유연성을 높일 수 있습니다."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/Navigation/NavigationPage.swift",
"line": 28,
"code_snippet": " self.trailingIcons = Array(trailingIcons.prefix(2))",
"body": "🔵 [P4] Readability\n\n트레일링 아이콘 개수를 2개로 제한하는 것은 DesignSystem의 제약사항으로 보입니다. 이 제한이 명확한 디자인/기능적 이유가 있다면 해당 제약에 대한 설명이나 토큰화된 상수를 사용하는 것이 좋습니다. 또한, 이 제한을 컴포넌트 init에서 직접 강제하는 것보다, 상위 뷰에서 trailingIcons 배열을 NavigationPage에 전달하기 전에 처리하도록 유도하는 것이 컴포넌트의 유연성을 높일 수 있습니다."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/TextInput/TextInput.swift",
"line": 76,
"code_snippet": " // TODO: datefield 구현 예정",
"body": "⚪ [P5] Nitpick\n\nTODO 주석이 명확하게 남아 있어 좋습니다. 추후 datefieldtimefield 구현 시 해당 주석을 제거해주세요."
},
{
"path": "Projects/Shared/DesignSystem/Sources/Components/TextInput/TextInput.swift",
"line": 79,
"code_snippet": " // TODO: timefield 구현 예정",
"body": "⚪ [P5] Nitpick\n\nTODO 주석이 명확하게 남아 있어 좋습니다. 추후 datefieldtimefield 구현 시 해당 주석을 제거해주세요."
},
{
"path": "Projects/Shared/DesignSystem/Sources/CustomFont/CustomSize.swift",
"line": 6,
"code_snippet": "import CoreGraphics",
"body": "⚪ [P5] Nitpick\n\n이 파일에 CoreGraphics를 명시적으로 임포트할 필요는 없어 보입니다. CGFloatSwiftUI 또는 Foundation을 통해 이미 사용 가능합니다. 불필요한 임포트를 제거하여 모듈 종속성을 최소화하는 것이 좋습니다.\n\nsuggestion\n"
},
{
"path": "Projects/Shared/Shared/Project.swift",
"line": 10,
"code_snippet": " product: .staticFramework,",
"body": "🔵 [P4] Readability\n\nShared 모듈의 제품 타입을 .framework에서 .staticFramework로 변경했습니다. 이는 빌드 및 링킹 성능 개선에 도움이 될 수 있는 좋은 변경입니다. 이 결정에 대한 명확한 아키텍처적 근거가 있다면 문서화에 추가하는 것을 고려해볼 수 있습니다."
}
]
}

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

새로운 DesignSystem 컴포넌트들이 잘 구현되었고, 기존 인증 플로우 화면에 성공적으로 적용되었습니다. 새로운 타이포그래피 시스템, 내비게이션, 버튼, 입력 필드 등 핵심 컴포넌트들이 디자인 명세와 SwiftUI 컨벤션에 따라 체계적으로 구축되었고, 각 컴포넌트의 프리뷰도 충실하게 작성되어 재사용성 및 유지보수성이 높을 것으로 예상됩니다. TCA 액션 및 상태 관리도 변경된 UI 플로우에 맞춰 일관성 있게 업데이트되었습니다. 전반적으로 코드 품질이 우수하며, 주어진 가이드라인을 잘 준수하고 있습니다.

await MainActor.run {
store.send(.galleryImagePicked(data))
photoItem = nil
photoItem = nil // 동일한 사진을 다시 선택할 수 있도록 리셋 (nil이 되지 않으면 onChange 재발화 안 됨)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[P5] Nitpick

줄 끝 주석은 일반적으로 120자 라인 제한을 초과하기 쉽습니다. 가독성을 위해 별도의 줄로 빼는 것이 좋습니다.

Suggested change
photoItem = nil // 동일한 사진을 다시 선택할 수 있도록 리셋 (nil이 되지 않으면 onChange 재발화 안 됨)
photoItem = nil
// 동일한 사진을 다시 선택할 수 있도록 리셋 (nil이 되지 않으면 onChange 재발화 안 됨)

@@ -20,7 +20,10 @@ public extension View {
}

func pretendardCustomFont(textStyle: CustomSizeFont) -> some View {
return self.modifier(PretendardFont(family: textStyle.fontFamily, size: textStyle.size))
self
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 [P4] Readability

.pretendardCustomFont 뷰 모디파이어 내부에서 self 키워드 사용은 불필요합니다. Swift 컨벤션에 따라 제거하는 것이 좋습니다.

Suggested change
self
modifier(PretendardFont(family: textStyle.fontFamily, size: textStyle.size))
.kerning(textStyle.letterSpacing * textStyle.size)
.lineSpacing(textStyle.lineHeight - textStyle.size)

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

DesignSystem 컴포넌트 전반에 걸쳐 디자인 명세가 잘 반영되었고, 컴포넌트 API 설계가 체계적입니다. NavigationBar 숨김 처리와 새로운 Typography 시스템 적용, Preview 환경에서의 폰트 등록 방식 개선 등 전반적인 코드 품질 향상이 돋보입니다. 다만, TCA Navigation Path 처리 로직에서 반복되는 부분이 있어 개선의 여지가 있습니다.

return .send(.delegate(.authDidComplete))

case .path(.element(id: _, action: .departure(.delegate(.dismiss)))):
state.path.removeLast()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 [P3] Minor

AuthFlowFeatureReducer 내에서 state.path.removeLast()가 여러 case에서 반복되고 있습니다. 이처럼 동일한 로직이 반복될 경우, 공통 Delegate 액션(e.g. .delegate(.popPath))을 정의하고 해당 액션에서 state.path.removeLast()를 처리하도록 리팩토링하여 중복을 줄일 수 있습니다. 이는 유지보수성을 높이는 데 도움이 됩니다.

TermsProfile 화면의 뒤로가기 로직은 동일하므로 하나의 delegate 액션으로 처리할 수 있습니다.

public var body: some View {
NavigationStack(path: $store.scope(state: \.path, action: \.path)) {
LoginView(store: store.scope(state: \.login, action: \.login))
.toolbar(.hidden, for: .navigationBar)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 [P4] Readability

커스텀 내비게이션 바 컴포넌트(NavigationPage, NavigationMain)를 사용함에 따라 기본 navigationBar를 숨기는 것은 적절합니다. 동일한 코드가 여러 .navigationDestination 뷰에 반복되고 있으므로, ViewModifier를 만들어서 적용하면 코드 중복을 줄일 수 있습니다.

Suggested change
.toolbar(.hidden, for: .navigationBar)
private extension View {
func hidesNavigationBar() -> some View {
toolbar(.hidden, for: .navigationBar)
}
}
// 사용 예시:
// LoginView(store: store.scope(state: \.login, action: \.login))
// .hidesNavigationBar()

guard new != nil else { return }
// 이미 토스트가 노출 중일 때도 재선택 시 다시 보여주기 위해 리셋 후 재발화
isToastVisible = false
Task { @MainActor in isToastVisible = true }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 [P3] Minor

isToastVisible = false 직후 Task { @MainActor in isToastVisible = true }를 사용하는 패턴은 SwiftUI 뷰 업데이트 사이클과 토스트 컴포넌트의 애니메이션 구현 방식에 따라 의도치 않은 깜빡임이나 애니메이션 불일치를 유발할 수 있습니다. 이미 토스트가 true인 상태에서 재선택 시 onChange가 다시 호출되어 false -> true가 될 때 애니메이션이 부자연스러울 가능성이 있습니다.

토스트 컴포넌트 내부에서 isVisible 상태 변화를 감지하여 false -> true 시 재시작 애니메이션을 명시적으로 처리하거나, 이 로직이 필요한 이유에 대한 추가적인 디자인/UX 요구사항이 있다면 해당 내용을 주석으로 명시하는 것이 좋습니다.

.overlay {
if isShowingMenu {
GeometryReader { geo in
DesignSystem.Menu(items: [
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 [P4] Readability

DesignSystem.Menu를 초기화할 때 selectedIndex 바인딩을 빠뜨렸습니다. 메뉴 항목을 탭했을 때 선택 상태가 반영되도록 selectedIndex 바인딩을 추가하는 것이 좋습니다. 현재 코드에서는 단순히 isShowingMenu = false만 실행됩니다.

Suggested change
DesignSystem.Menu(items: [
DesignSystem.Menu(
selectedIndex: .constant(nil), // 또는 @State로 관리되는 실제 selectedIndex 바인딩
items: [

.frame(maxWidth: .infinity, alignment: .leading)
.padding(Spacing.spacing250)
.background(
RoundedRectangle(cornerRadius: 20)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 [P4] Readability

매직 넘버(20) 대신 DesignSystem에 정의된 BorderRadius 토큰을 사용하는 것이 좋습니다. 일관된 디자인 시스템 적용을 위해 토큰 사용을 권장합니다.

Suggested change
RoundedRectangle(cornerRadius: 20)
RoundedRectangle(cornerRadius: BorderRadius.borderRadius400)

@@ -20,7 +20,9 @@ public extension View {
}

func pretendardCustomFont(textStyle: CustomSizeFont) -> some View {
return self.modifier(PretendardFont(family: textStyle.fontFamily, size: textStyle.size))
modifier(PretendardFont(family: textStyle.fontFamily, size: textStyle.size))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 [P4] Readability

return 키워드는 단일 표현식 함수 본문(single-expression function body)에서 생략 가능합니다. 일관성을 위해 return을 제거하는 것을 권장합니다.

Suggested change
modifier(PretendardFont(family: textStyle.fontFamily, size: textStyle.size))
modifier(PretendardFont(family: textStyle.fontFamily, size: textStyle.size))

@khyeji98 khyeji98 merged commit 7e418ab into develop May 21, 2026
1 check passed
@khyeji98 khyeji98 deleted the feature/#35 branch May 21, 2026 03:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

add feature New feature or request refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants