Skip to content

Feat/#15 피드 업로드 화면 UI 구현#21

Merged
DongChyeon merged 23 commits intodevelopfrom
feat/#15-upload-ui
Feb 7, 2026
Merged

Feat/#15 피드 업로드 화면 UI 구현#21
DongChyeon merged 23 commits intodevelopfrom
feat/#15-upload-ui

Conversation

@DongChyeon
Copy link
Member

@DongChyeon DongChyeon commented Feb 6, 2026

🛠 Related issue

closed #15

어떤 변경사항이 있었나요?

  • 🐞 BugFix Something isn't working
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (Junit, etc.)

✅ CheckPoint

PR이 다음 요구 사항을 충족하는지 확인하세요.

  • PR 컨벤션에 맞게 작성했습니다. (필수)
  • merge할 브랜치의 위치를 확인해 주세요(main❌/develop⭕) (필수)
  • Approve된 PR은 assigner가 머지하고, 수정 요청이 온 경우 수정 후 다시 push를 합니다. (필수)
  • BugFix의 경우, 버그의 원인을 파악하였습니다. (선택)

✏️ Work Description

default.mp4
  • 피드 올리기 화면 UI 구현
  • Dialog랑 BottomSheet 자체 내에서 뒤로 가기 누르면 닫히는 옵션이 있어서 BackHandler는 AlertDialog 떠있지 않으면 뜨게 하는 용도로만 사용했습니다.

😅 Uncompleted Tasks

N/A

📢 To Reviewers

image

어제 수정한 BottomSheet 사용하니 하단 dim 영역이 의도대로 잡히지 않아서
수정해보다가... 결국 원상복구시켰습니다.

그리고 초반에 #13으로 잘못 커밋된 내용이 있긴 한데 고치려면 rebase 과정도 필요해서 이건 감안해주심 좋겠습니다.

📃 RCA 룰

  • R: 꼭 반영해 주세요. 적극적으로 고려해 주세요. (Request changes)
  • C: 웬만하면 반영해 주세요. (Comment)
  • A: 반영해도 좋고 넘어가도 좋습니다. 그냥 사소한 의견입니다. (Approve)

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 업로드 화면: 이미지 선택, 카테고리/가격/내용 입력 및 뒤로가기 처리 추가
    • 카메라·원화 아이콘 및 말풍선(Bubble) 쉐이프 추가
  • UI 개선

    • 알림 대화상자 패딩/텍스트 색상 조정
    • 하단 시트 모양 파라미터화 및 클리핑 개선
    • FAB 아이콘 회전 처리 개선
    • 하단 네비게이션 바 제거로 인터페이스 단순화
  • 버그 수정

    • 소프트 키보드 표시 시 화면 자동 조정(adjustResize) 적용
  • 의존성

    • 이미지 로딩(Compose) 라이브러리 추가

@DongChyeon DongChyeon self-assigned this Feb 6, 2026
@DongChyeon DongChyeon added ✨ FEAT 기능 개발 (애매하면 기능 개발로 두도록 하자) 💪 동현동현동현 labels Feb 6, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 6, 2026

Warning

Rate limit exceeded

@DongChyeon has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 0 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

업로드 화면에 후방 네비게이션 콜백을 추가하고 UploadScreen을 재구성했으며, 하단 네비게이션 바 관련 로직을 제거했습니다. 디자인시스템에는 새로운 Shape(BubbleShape), 아이콘(Camera, Won), BottomSheet/OptionSheet의 sheetShape 파라미터, AlertDialog/ExpandableFab 수정 등이 추가되었고, Manifest와 빌드에 소프트입력·Coil 의존성이 반영되었습니다.

Changes

Cohort / File(s) Summary
네비게이션 호스트 & 호출부
app/src/main/java/.../BuyOrNotNavHost.kt, feature/upload/src/main/java/.../UploadNavigation.kt
Upload 호출에 onNavigateBack 전달하도록 변경; navigateToUpload(navOptions: NavOptions? = null) 확장 함수 추가 및 uploadScreen(onNavigateBack: () -> Unit = {}) 시그니처 도입.
업로드 화면 (UI·로직 추가)
feature/upload/src/main/java/.../UploadScreen.kt
UploadRoute() 제거, 공개 API를 UploadScreen(modifier: Modifier = ..., onNavigateBack: () -> Unit = {})로 교체. 이미지 선택, 카테고리 선택, 가격/내용 입력, BackHandler·제출 가능성 로직 등 대규모 UI 및 상태 추가(많은 라인 변경).
앱 호스트 / AndroidManifest
app/src/main/java/.../BuyOrNotApp.kt, app/src/main/AndroidManifest.xml
하단 네비게이션 바 및 관련 아이템 제거로 Scaffold 단순화, consumeWindowInsets 적용; Manifest에 android:windowSoftInputMode="adjustResize" 추가.
디자인 시스템: BottomSheet / OptionSheet
core/designsystem/src/main/java/.../BottomSheet.kt, .../OptionSheet.kt
BottomSheet/OptionSheet에 sheetShape: Shape = RoundedCornerShape(26.dp) 파라미터 추가 및 클리핑/shape 적용; 그라디언트 색상 조정.
디자인 시스템: 컴포넌트·스타일
core/designsystem/src/main/java/.../AlertDialog.kt, .../ExpandableFab.kt
AlertDialog 가로 패딩 감소(28.dp→18.dp) 및 서브텍스트 색상 변경; FAB 아이콘 회전을 graphicsLayer 기반으로 변경.
새 Shape 및 아이콘 리소스
core/designsystem/src/main/java/.../shape/BubbleShape.kt, core/designsystem/src/main/java/.../icon/BuyOrNotIcons.kt, core/designsystem/src/main/res/drawable/ic_camera.xml, .../ic_won.xml
새로운 BubbleShape 클래스 추가(말풍선 꼬리 포함) 및 Camera, Won 아이콘 리소스 추가와 대응 벡터 드로어블 추가.
빌드·의존성 변경
feature/upload/build.gradle.kts, gradle/libs.versions.toml
feature/upload에 coil.compose 의존성 추가; libs.versions.tomlandroidx-compose-material 항목 추가.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant NavHost
    participant NavController
    participant UploadScreen
    participant System as Activity/Launcher

    User->>NavHost: 요청(업로드 화면 진입)
    NavHost->>NavController: navigateToUpload()
    NavController->>UploadScreen: composable 호출(onNavigateBack 제공)
    UploadScreen->>System: 이미지 선택 요청 (Gallery/Camera launcher)
    System-->>UploadScreen: 선택된 이미지 반환
    User->>UploadScreen: 뒤로가기 또는 제출
    alt 뒤로가기
        UploadScreen->>NavController: onNavigateBack() -> popBackStack()
        NavController-->>NavHost: 화면 복귀
    else 제출
        UploadScreen->>NavController: 제출 후 네비게이션(선택적)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Imagine-Choi
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 피드 업로드 화면 UI 구현이라는 주요 변경사항을 명확하게 요약하고 있으며, 전체 changeset과 일치합니다.
Linked Issues check ✅ Passed PR은 linked issue #15의 요구사항인 '피드 업로드 화면 UI 구현'을 완전히 충족하고 있습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항은 피드 업로드 화면 UI 구현과 관련된 범위 내에 있으며, 불필요한 변경사항은 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#15-upload-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@feature/upload/src/main/java/com/sseotdabwa/buyornot/feature/upload/ui/UploadScreen.kt`:
- Around line 484-498: The touch target for the image remove button (the Box in
UploadScreen.kt that currently uses Modifier.size(20.dp) and .clickable {
onRemove() }) is too small; update the Modifier chain for that Box to preserve
the 20dp visual circle but expand the interactive area to at least 48dp by
applying minimumInteractiveComponentSize() (or by adding transparent padding
around the visual size) before .clickable so the onRemove() hit target meets
accessibility guidelines; keep the CircleShape background/clip and visual size
the same while ensuring the clickable area is enlarged.

In `@gradle/libs.versions.toml`:
- Line 39: libs.versions.toml에 추가된 materialNavigation("1.7.0")과 카탈로그 항목
androidx-compose-material 및 androidx-compose-material-navigation이 현재 어떤
build.gradle.kts에서도 임포트되어 사용되지 않습니다; 해당 아티팩트가 실제로 사용될 모듈에서 Compose Navigation 관련
의존성(import/implementation)을 추가하거나 사용 계획이 없다면 libs.versions.toml에서
materialNavigation 및 관련 카탈로그 항목(androidx-compose-material,
androidx-compose-material-navigation)을 삭제하여 버전 카탈로그를 정리하세요.
🧹 Nitpick comments (6)
core/designsystem/src/main/java/com/sseotdabwa/buyornot/core/designsystem/shape/BubbleShape.kt (1)

19-22: layoutDirection 미사용 — RTL 레이아웃 고려

현재 layoutDirection 파라미터를 사용하지 않아, RTL 환경에서도 화살표가 항상 오른쪽을 가리킵니다. 한국어 앱 특성상 당장 문제는 없지만, 추후 다국어 지원 시 화살표 방향을 layoutDirection에 따라 반전하는 처리가 필요할 수 있습니다.

♻️ RTL 지원 예시
 override fun createOutline(
     size: Size,
     layoutDirection: LayoutDirection,
     density: Density,
 ): Outline =
     Outline.Generic(
         Path().apply {
             val cornerRadiusPx = with(density) { cornerRadius.toPx() }
             val arrowWidthPx = with(density) { arrowWidth.toPx() }
             val arrowHeightPx = with(density) { arrowHeight.toPx() }
+            val isRtl = layoutDirection == LayoutDirection.Rtl

-            addRoundRect(
-                RoundRect(
-                    rect = Rect(0f, 0f, size.width - arrowWidthPx, size.height),
-                    cornerRadius = CornerRadius(cornerRadiusPx),
-                ),
-            )
+            val bodyRect = if (isRtl) {
+                Rect(arrowWidthPx, 0f, size.width, size.height)
+            } else {
+                Rect(0f, 0f, size.width - arrowWidthPx, size.height)
+            }
+            addRoundRect(RoundRect(rect = bodyRect, cornerRadius = CornerRadius(cornerRadiusPx)))

-            moveTo(size.width - arrowWidthPx, size.height / 2 - arrowHeightPx / 2)
-            lineTo(size.width, size.height / 2)
-            lineTo(size.width - arrowWidthPx, size.height / 2 + arrowHeightPx / 2)
+            if (isRtl) {
+                moveTo(arrowWidthPx, size.height / 2 - arrowHeightPx / 2)
+                lineTo(0f, size.height / 2)
+                lineTo(arrowWidthPx, size.height / 2 + arrowHeightPx / 2)
+            } else {
+                moveTo(size.width - arrowWidthPx, size.height / 2 - arrowHeightPx / 2)
+                lineTo(size.width, size.height / 2)
+                lineTo(size.width - arrowWidthPx, size.height / 2 + arrowHeightPx / 2)
+            }
             close()
         },
     )
core/designsystem/src/main/java/com/sseotdabwa/buyornot/core/designsystem/components/BottomSheet.kt (1)

120-130: 드래그 핸들 색상이 하드코딩되어 있습니다.

다른 모든 색상(gray0, gray1000 등)은 BuyOrNotTheme.colors를 통해 참조하고 있는데, 드래그 핸들만 Color(0xFFD9D9D9)로 하드코딩되어 있습니다. 다크 모드 지원이나 디자인 시스템 변경 시 누락될 수 있으므로, 가능하면 테마 색상을 사용하는 것이 좋습니다.

♻️ 테마 색상 사용 제안
                             .background(
-                                color = Color(0xFFD9D9D9),
+                                color = BuyOrNotTheme.colors.gray300, // 또는 적절한 테마 색상
                                 shape = RoundedCornerShape(18.dp),
                             ),
app/src/main/AndroidManifest.xml (1)

14-14: windowSoftInputMode<activity> 레벨로 이동하는 것을 권장합니다.

현재 <application> 레벨에 설정되어 있어 향후 추가되는 모든 Activity에 일괄 적용됩니다. 단일 Activity 앱이므로 당장 문제는 없지만, 의도를 명확히 하려면 Line 17의 <activity> 태그에 직접 지정하는 편이 낫습니다.

제안
     <application
         android:name=".BuyOrNotApplication"
         android:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
         android:fullBackupContent="@xml/backup_rules"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
-        android:windowSoftInputMode="adjustResize"
         android:theme="@style/Theme.BuyOrNot">
         <activity
             android:name=".MainActivity"
             android:exported="true"
             android:label="@string/app_name"
-            android:theme="@style/Theme.BuyOrNot">
+            android:theme="@style/Theme.BuyOrNot"
+            android:windowSoftInputMode="adjustResize">
app/src/main/java/com/sseotdabwa/buyornot/ui/BuyOrNotApp.kt (1)

59-67: bottomBarPadding 함수명이 현재 역할과 맞지 않습니다.

하단 네비게이션 바가 제거되었으므로 이 함수는 실질적으로 시스템 인셋 패딩 적용 여부를 결정합니다. scaffoldPadding 또는 systemInsetsPadding 등으로 이름을 변경하면 의도가 더 명확해집니다.

feature/upload/src/main/java/com/sseotdabwa/buyornot/feature/upload/ui/UploadScreen.kt (2)

549-579: customShadowpublic으로 노출되어 있습니다.

이 파일 내 ToolTip에서만 사용되므로 private으로 제한하거나, 재사용이 필요하다면 core/designsystem 모듈의 유틸리티 파일로 이동하는 것이 좋습니다.

제안
-fun Modifier.customShadow(
+private fun Modifier.customShadow(

265-323: 가격 입력 포매팅 로직이 잘 구현되어 있습니다.

커서 위치 재계산이 정확하며, 10자리 제한(최대 ~99억)이 Long 범위 내에 있어 안전합니다.

한 가지 참고: DecimalFormat("#,###")은 로케일에 따라 그룹 구분자가 달라질 수 있습니다. 한국 타겟 앱이므로 현재는 문제없지만, 다국어 지원 시 DecimalFormat("#,###", DecimalFormatSymbols(Locale.KOREA))로 명시하면 더 안전합니다.

Copy link
Member

@Imagine-Choi Imagine-Choi left a comment

Choose a reason for hiding this comment

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

짱!!!!!!!! 수고하셨습니다~~

selectedImageUri = uri
}

val isSubmitEnabled = selectedCategory != null && priceRaw.isNotEmpty() && selectedImageUri != null
Copy link
Member

Choose a reason for hiding this comment

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

C: 현재 기능은 잘 동작합니다! :) 짱짱

다만 궁금한 사항이 있습니다!

현재 특정 필드만 수정되어도 다른 필드 및 부모까지 리컴포지션이 추가로 일어나는데 ,
isSubmitEnabled 변수가 UploadScreen 최상단에 있어서
여기서 참조하는 값이 하나라도 바뀌면 화면 전체가 리컴포지션 대상이 될 확률도 있을까요?

궁금해서 여쭤봅니다!!

Copy link
Member Author

Choose a reason for hiding this comment

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

안녕하세요. 제 코드에 관심가져주셔서 감사합니다.
derivedStateOf를 사용하면 리컴포지션 횟수를 더 줄일 수 있는 점 찾아내서 반영했습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@feature/upload/src/main/java/com/sseotdabwa/buyornot/feature/upload/ui/UploadScreen.kt`:
- Around line 421-468: The Surface currently uses Modifier.clickable which
prevents the ripple from being clipped to RoundedCornerShape(12.dp); remove the
Modifier.clickable(onClick = onClick) usage and instead use the Material3
Surface clickable overload by passing onClick directly to the Surface (i.e.,
Surface(onClick = onClick, shape = RoundedCornerShape(12.dp), ...)) while
keeping the size modifier and other properties; update any imports if needed and
ensure no duplicate clickable modifiers remain in Column or children.
🧹 Nitpick comments (5)
core/designsystem/src/main/java/com/sseotdabwa/buyornot/core/designsystem/components/OptionSheet.kt (1)

36-43: KDoc에 sheetShape 파라미터 설명이 누락되어 있습니다.

새로 추가된 sheetShape 파라미터에 대한 @param 문서가 빠져 있습니다. 다른 파라미터들은 모두 설명이 있으므로 일관성을 위해 추가해 주세요.

feature/upload/src/main/java/com/sseotdabwa/buyornot/feature/upload/ui/UploadScreen.kt (4)

293-329: 가격 입력 커서 위치 계산 시 엣지 케이스 확인이 필요합니다.

digitsBeforeCursor > 0인데 formattedText의 모든 자릿수를 순회해도 digitCountdigitsBeforeCursor에 도달하지 못하면 newCursorPos0으로 남아 커서가 맨 앞으로 이동합니다. 현재 로직상 formattedTextnewDigits에서 파생되므로 이론적으로 불가능하지만, 방어 코드로 루프 종료 후 newCursorPosformattedText.length로 fallback 처리하면 더 안전합니다.

🛡️ 방어 코드 제안
                     var digitCount = 0
                     var newCursorPos = 0
                     for (i in formattedText.indices) {
                         if (formattedText[i].isDigit()) {
                             digitCount++
                         }
                         if (digitCount == digitsBeforeCursor) {
                             newCursorPos = i + 1
                             break
                         }
                     }
+                    // fallback: 루프에서 매칭되지 않은 경우 끝으로
+                    if (digitCount < digitsBeforeCursor) {
+                        newCursorPos = formattedText.length
+                    }
                     if (digitsBeforeCursor == 0) {
                         newCursorPos = 0
                     }

351-391: ContentInputFieldBasicTextFieldsingleLine = false 명시 또는 줄바꿈 제한 여부를 확인해 주세요.

현재 BasicTextFieldsingleLine이 설정되지 않아 기본값 false로 여러 줄 입력이 가능합니다. 의도된 동작이라면 괜찮지만, 글자 수 제한(100자)만 있고 줄 수 제한이 없어서 과도한 줄바꿈으로 레이아웃이 늘어날 수 있습니다.


106-112: 갤러리에서 받은 Uri의 읽기 권한 지속성에 주의하세요.

ActivityResultContracts.GetContent()으로 받은 Uri는 일시적 권한만 부여됩니다. 현재는 UI-only 구현이라 문제없지만, 추후 업로드 기능 구현 시 ContentResolver.takePersistableUriPermission()을 호출하거나 즉시 파일을 복사하는 처리가 필요합니다.


262-267: 카테고리 텍스트에만 clickable이 적용되어 있어 터치 영역이 좁습니다.

"카테고리 추가" 텍스트만 클릭 가능하지만, 사용자는 화살표 아이콘이나 "투표 등록" 텍스트까지 포함한 Row 전체를 탭할 것으로 기대할 수 있습니다. clickableRow에 적용하는 것을 고려해 주세요.

@DongChyeon DongChyeon merged commit 0a49bed into develop Feb 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ FEAT 기능 개발 (애매하면 기능 개발로 두도록 하자) 💪 동현동현동현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Feature - 피드 업로드 화면 UI 구현

2 participants