pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/YAPP-Github/27th-App-Team-2-Android/pull/155

6484da1f.css" /> [feat] #154 사진 추가 시 아카이빙 메인 화면 재갱신 by ikseong00 · Pull Request #155 · YAPP-Github/27th-App-Team-2-Android · GitHub
Skip to content

[feat] #154 사진 추가 시 아카이빙 메인 화면 재갱신#155

Merged
ikseong00 merged 6 commits intodevelopfrom
feat/#154-archive-result
Mar 2, 2026
Merged

[feat] #154 사진 추가 시 아카이빙 메인 화면 재갱신#155
ikseong00 merged 6 commits intodevelopfrom
feat/#154-archive-result

Conversation

@ikseong00
Copy link
Contributor

@ikseong00 ikseong00 commented Feb 26, 2026

🔗 관련 이슈

📙 작업 설명

  • Photo Upload 모듈에서 QR 혹은 갤러리를 통해 사진 업로드할 때, 기존 ArchiveMain 에서 Result 를 collect 해서 사진정보를 업데이트했지만,
  • 새롭게 Main 에서 Result 를 먼저 collect 하여 가로채기 때문에 ArchiveMain 쪽에서의 갱신 로직에 다다를 수 없었습니다.
  • 따라서 Main 에서 PhotoUpload Result 를 받으면, ArchiveMain 쪽으로 Result 를 보내도록 적용했습니다.
  • 추가적으로 추후 다른 변경 등으로 인해 ArchiveMain 쪽에서 Result 를 받을 가능성이 있으니 when 으로 처리하도록 했습니다.
  • 아카이빙 메인에서의 업로드 관련 로직은 dead code 가 되어서 제거했습니다.

아래 케이스들 모두 체크 완료했습니다. (앨범에 추가까지)

  1. 아카이빙 탑바 QR 스캔
  2. 사진 추가 > 갤러리
  3. 사진 추가 > QR 스캔

📸 스크린샷 또는 시연 영상 (선택)

기능 갤러리업로드 기능 QR스캔
사진 추가 > 갤러리 업로드
default.mp4
탑바 > QR 스캔
QR.mp4

💬 추가 설명 or 리뷰 포인트 (선택)

  • 기존에 ArchiveMain 이 먼저 생긴 상태에서, 그 시점의 channelMap 을 캡처해 LaunchedEffect 에서 체크합니다.
  • 하지만 그 channelMap 은 상태가 아니기 때문에 해당 Map 의 변화가 생겨도 LaunchedEffect 에서 자동적으로 체크하지 못합니다.
  • 따라서 mutableStateMapOf 으로 channelMap 을 수정해주었고, ResultEventBus@Stable 어노테이션을 추가했습니다.

Summary by CodeRabbit

  • 새로운 기능

    • 사진 업로드 완료 시 아카이브가 자동으로 새로고침됩니다.
    • 업로드 완료를 알리는 새로운 결과 타입이 추가되었습니다.
  • 개선 사항

    • 아카이브 갱신 로직이 결과 기반으로 통합되어 일관되게 동작합니다.
    • 업로드 후 알림(토스트) 외에 아카이브 새로고침이 함께 트리거됩니다.
  • 제거

    • 갤러리/앨범 선택 및 QR 스캔을 통한 업로드 관련 UI 및 내비게이션 경로가 제거되었습니다.

사진 업로드(갤러리, QR)가 완료된 후, 아카이브 메인 화면이 자동으로 새로고침되도록 기능을 추가했습니다.

`MainViewModel`에서 사진 업로드 성공 시 `RefreshArchive` 사이드 이펙트를 발생시키고, 이를 `MainScreen`에서 받아 `ResultBus`를 통해 `PhotoUploaded` 결과를 아카이브 기능으로 전달하여 화면을 갱신합니다.
사진 업로드, 삭제, 즐겨찾기 변경 후 화면 전체를 다시 불러오는 `RefreshArchiveMainScreen` 인텐트를 사진 목록만 새로고치도록 `RefreshArchiveMainPhotos`로 변경하고, 관련 로직을 수정했습니다. 이를 통해 불필요한 전체 데이터 요청을 줄이고 사진 영역만 효율적으로 갱신하도록 개선했습니다.
`ResultEventBus` 클래스에 `@Stable` 어노테이션을 추가하여 Compose 런타임이 해당 클래스를 안정적인 것으로 인식하고 불필요한 리컴포지션을 줄이도록 했습니다.
또한, `channelMap`의 구현을 `mutableMapOf`에서 `mutableStateMapOf`로 변경하여 상태 변경을 Compose가 올바르게 관찰할 수 있도록 수정했습니다.
@ikseong00 ikseong00 self-assigned this Feb 26, 2026
@ikseong00 ikseong00 added the feat label Feb 26, 2026
@github-actions github-actions bot requested a review from Ojongseok February 26, 2026 18:18
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between edb21bc and 08b4282.

📒 Files selected for processing (1)
  • core/navigation/src/main/java/com/neki/android/core/navigation/result/ResultEventBus.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/navigation/src/main/java/com/neki/android/core/navigation/result/ResultEventBus.kt

Walkthrough

메인에서 사진 업로드 성공 시 새 사이드이펙트와 결과 타입을 추가해 아카이브에 사진 업로드 이벤트를 전파하고, 아카이브 쪽의 업로드·갤러리·QR 관련 인텐트·사이드이펙트를 정리·단순화했습니다.

Changes

Cohort / File(s) Summary
Main: 사이드 이펙트 정의
app/src/main/java/com/neki/android/app/main/MainContract.kt
MainSideEffectRefreshArchive 싱글톤 데이터 객체 추가.
Main: 효과 처리 및 전송
app/src/main/java/com/neki/android/app/main/MainScreen.kt
MainSideEffect.RefreshArchive 처리 시 ArchiveResult.PhotoUploaded를 결과 버스로 전송하도록 추가.
Main: 업로드 로직(뷰모델)
app/src/main/java/com/neki/android/app/main/MainViewModel.kt
단일·다중 업로드 성공 경로에서 ShowToast 외에 RefreshArchive 사이드이펙트 추가 발행.
Archive API: 결과 타입
feature/archive/api/src/main/kotlin/com/neki/android/feature/archive/api/ArchiveResult.kt
ArchiveResultPhotoUploaded 데이터 객체(싱글톤) 추가.
Archive impl: 계약 및 의도 변경
feature/archive/impl/src/main/kotlin/.../main/ArchiveMainContract.kt
RefreshArchiveMainScreenRefreshArchiveMainPhotos로 이름 변경, 업로드·갤러리 관련 인텐트/사이드이펙트 제거 및 일부 인텐트 추가/재구성.
Archive impl: 뷰모델 변경
feature/archive/impl/src/main/kotlin/.../main/ArchiveMainViewModel.kt
업로드 관련 usecase 제거, 갤러리/업로드 흐름 제거, 리프레시 처리 경로를 fetchPhotos(size) 호출로 변경.
Archive impl: 네비게이션/엔트리
feature/archive/impl/src/main/kotlin/.../navigation/ArchiveEntryProvider.kt
ResultEffect 타입을 QRScanResultArchiveResult로 변경하고, PhotoUploaded 포함 결과에 대해 RefreshArchiveMainPhotos 인텐트로 통합. 네비게이션 파라미터(업로드 관련) 제거.
Core navigation: 결과 이벤트 버스
core/navigation/src/main/java/com/neki/android/core/navigation/result/ResultEventBus.kt
내부 channelMap을 Compose 관찰 가능한 mutableStateMapOf()로 변경(구현 내부 수정).
Archive UI: 화면 변경
feature/archive/impl/src/main/kotlin/.../main/ArchiveMainScreen.kt
ArchiveMainRoute에서 업로드/갤러리·QR 네비게이션 파라미터 제거, 런처·SelectWithAlbumDialog 등 관련 UI와 핸들러 제거.

Sequence Diagram(s)

sequenceDiagram
    participant MainScreen as Main 화면
    participant MainVM as MainViewModel
    participant ResultBus as ResultEventBus
    participant ArchiveVM as ArchiveMainViewModel
    participant PhotoRepo as PhotoRepository

    MainScreen->>MainVM: uploadSingleImage()/uploadMultipleImages()
    MainVM->>MainVM: 업로드 성공 처리 (발생: RefreshArchive)
    MainVM->>MainScreen: emit MainSideEffect.RefreshArchive
    MainScreen->>ResultBus: sendResult(ArchiveResult.PhotoUploaded)
    ResultBus->>ArchiveVM: deliver ArchiveResult.PhotoUploaded
    ArchiveVM->>ArchiveVM: 처리: ArchiveMainIntent.RefreshArchiveMainPhotos
    ArchiveVM->>PhotoRepo: getPhotos(size)
    PhotoRepo-->>ArchiveVM: photos 반환
    ArchiveVM->>ArchiveVM: 상태 업데이트 (photos)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Ojongseok

Poem

🐰 업로드 빛나, 토끼가 껑충
신호 훅 보냈더니 아카이브 번쩍
사진 모여 춤추네, 새로고침 팡팡
지나가는 바람도 박수 쿵쾅
토끼의 기쁨, 코드에 방긋 😊

🚥 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
Title check ✅ Passed PR 제목이 주요 변경사항인 아카이빙 메인 화면 재갱신을 명확하게 설명하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿을 따르며 관련 이슈, 작업 설명, 테스트 내역, 스크린샷/영상, 추가 설명을 포함하고 있습니다.
Linked Issues check ✅ Passed PR의 코드 변경사항이 #154의 요구사항(Main에서 ArchiveMain으로 Result 전달, ResultEventBus 추가)을 모두 만족합니다.
Out of Scope Changes check ✅ Passed ArchiveMain의 dead code 제거(업로드 관련 로직, UI 요소, 네비게이션)는 #154의 목표와 일관성 있는 범위 내 변경입니다.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#154-archive-result

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.

아카이빙 메인 화면(ArchiveMain)에서 사진 업로드와 관련된 로직을 제거했습니다.

주요 변경 사항:
- `ArchiveMainViewModel`에서 `UploadSinglePhotoUseCase`, `UploadMultiplePhotoUseCase` 및 관련 업로드 메서드를 삭제했습니다.
- 사진 선택(갤러리, QR 스캔 결과) 및 앨범 지정 여부를 묻는 다이얼로그 관련 상태와 인텐트 처리를 제거했습니다.
- `ArchiveMainScreen`과 `ArchiveEntryProvider`에서 더 이상 사용하지 않는 업로드 관련 탐색 로직과 UI 컴포넌트(`SelectWithAlbumDialog` 등)를 삭제했습니다.
- 이 변경으로 인해 아카이빙 화면은 사진 조회 및 앨범 관리에만 집중하게 됩니다.
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/navigation/ArchiveEntryProvider.kt (1)

76-87: ⚠️ Potential issue | 🟠 Major

PhotoUploaded 이벤트가 현재 화면에서 소모되어 ArchiveMain 갱신을 놓칠 수 있습니다.

Line 76-87, Line 115-126의 else -> {}ArchiveResult.PhotoUploaded도 no-op 처리합니다.
ResultEffect 기본값(withRemove = true)에서는 onResult 이후 결과가 제거되므로, AllPhoto/AlbumDetail이 활성 상태일 때 업로드 이벤트가 ArchiveMain까지 전달되지 않을 수 있습니다.

PhotoUploaded를 별도 결과 키/타입으로 분리하거나, 해당 이벤트를 이 화면들에서 소비하지 않도록 처리 구조를 분리하는 쪽이 안전합니다.

Also applies to: 115-126

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/navigation/ArchiveEntryProvider.kt`
around lines 76 - 87, 현재 ResultEffect<ArchiveResult> 블록에서 else -> {}로
ArchiveResult.PhotoUploaded를 no-op 처리해 결과가 제거되어 ArchiveMain이 갱신을 놓칠 수 있습니다; 수정
방법은 해당 화면에서 PhotoUploaded를 소비하지 않도록 명시적으로 처리하는 것입니다 — 즉, ResultEffect 생성자에서
withRemove = false로 설정하거나(결과 제거 방지) 해당 when에 is ArchiveResult.PhotoUploaded 분기를
추가해 이벤트를 무시하되 제거되지 않도록 처리하도록 변경하세요; 관련 식별자: ResultEffect<ArchiveResult>,
ArchiveResult.PhotoUploaded, withRemove, AllPhotoIntent(현재 소비되는 블록)을 참고하여 코드를
수정하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/navigation/ArchiveEntryProvider.kt`:
- Around line 76-87: 현재 ResultEffect<ArchiveResult> 블록에서 else -> {}로
ArchiveResult.PhotoUploaded를 no-op 처리해 결과가 제거되어 ArchiveMain이 갱신을 놓칠 수 있습니다; 수정
방법은 해당 화면에서 PhotoUploaded를 소비하지 않도록 명시적으로 처리하는 것입니다 — 즉, ResultEffect 생성자에서
withRemove = false로 설정하거나(결과 제거 방지) 해당 when에 is ArchiveResult.PhotoUploaded 분기를
추가해 이벤트를 무시하되 제거되지 않도록 처리하도록 변경하세요; 관련 식별자: ResultEffect<ArchiveResult>,
ArchiveResult.PhotoUploaded, withRemove, AllPhotoIntent(현재 소비되는 블록)을 참고하여 코드를
수정하세요.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d72a0a4 and edb21bc.

📒 Files selected for processing (5)
  • core/navigation/src/main/java/com/neki/android/core/navigation/result/ResultEventBus.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/main/ArchiveMainContract.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/main/ArchiveMainScreen.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/main/ArchiveMainViewModel.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/navigation/ArchiveEntryProvider.kt
💤 Files with no reviewable changes (1)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/main/ArchiveMainScreen.kt

@ikseong00
Copy link
Contributor Author

ikseong00 commented Feb 26, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

1 similar comment
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Member

@Ojongseok Ojongseok left a comment

Choose a reason for hiding this comment

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

고생하셨습니다-!

아카이빙쪽 ViewModel/Contract 에서 업로드 관련 코드가 제거되고, Main쪽으로 이동하면서 아카이빙쪽 코드가 깔끔해졌네요! 오히려 업로드 관련 로직은 Main에서 처리되는게 적절한 것 같기도 하구요.

카톡에서 이야기 나눈 것 처럼 ArchiveMain에 대한 Result 처리는 이후에 진행하시죠!
(아카이빙 외 다른 탭에서도 FAB 통한 이미지 추가 시 정상적으로 추가되는 것 확인했습니다)

* It provides a solution for event based results.
*/
// https://github.com/android/nav3-recipes/blob/main/app/src/main/java/com/example/nav3recipes/results/event/README.md
@Stable
Copy link
Member

Choose a reason for hiding this comment

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

현재 상태에서 ResultEventBus.channelMap의 밸류에 직접 접근하는 부분이 없어 문제되지는 않을 것 같지만 Map의 밸류로 Cannel 타입을 갖기 때문에 @Stable 조건을 만족하지 못하는 것 같습니다!?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

지적 감사합니다!
말씀하신 대로 Channel이 @stable 조건을 엄밀히 만족하지 않는 건 맞습니다. 다만 @stable을 제거하면 ResultEventBus 자체가 unstable로 추론되어 불필요한 recomposition이 발생할 수 있습니다.

MainRoute 에서 리컴포지션이 발생하면, ResultEffect 는 unstable 해지기 때문에 반드시 리컴포지션이 발생합니다.
image

따라서 해당 ResultEventBus 클래스를 stable 하진 않지만 @Stable 하다고 명시하여 불필요한 리컴포지션을 줄일 수 있습니다!

매번 새로운 인스턴스를 반환하지 않고, 매번 같은 인스턴스를 사용하지만 unstable 하기에 @stable 추가.

Copy link
Member

Choose a reason for hiding this comment

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

말씀하신 부분은 이해가 되어 로그를 통해 실제로 리컴포지션을 줄일 수 있는지 확인을 해 보았는데요. ResultEffect의 경우 @Stable 어노테이션에 관계 없이 리컴포지션이 동일하게 발생하는 것 같습니다.?.?

제가 확인한 바로는 ResultEffect의 경우 inline 함수이고, MainRoute에서 리컴포지션이 발생하면 독립적인 리컴포지션의 대상이 아니기 때문에(inline 함수의 경우 접근할 때 그대로 함수를 가지고 오기 때문에) 항상 다시 작성되는 것으로 이해했습니다.
결국 ResultEffect() 내부의 LaunchedEffect 구문에 설정된 키의 영향을 받는데 키로 설정된 resultKey, resultEventBus.channelMap[resultKey]MainRoute가 리컴포지션 되더라도 각각 StringChannel<Any?> 타입이기 때문에 MainRoute의 리컴포지션과는 무관하게 설정된 키의 변화에 따라 LaunchedEffect 블럭의 코드가 트리거 되는 것 같습니다.

제가 확인하지 못한 MainRoute의 리컴포지션 시에 해당 키의 변화가 있는지, 추가적으로 확인한 내용이 올바르게 이해한 것인지는 모르겠네요...! 리컴포지션 어렵다어려워

Copy link
Contributor Author

Choose a reason for hiding this comment

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

아하, inline 함수가 된다면 실제 코드에서 이렇게 반영이 되는군요,
그래서 말씀하신 것처럼 ResultEffect 가 내부 함수로 펼쳐지기(?) 때문에 리컴포지션 대상 자체가 안되네요!
inline 이 기본 함수에만 작동되는 줄 알았는데 코틀린 기본 개념처럼 진짜 코드 인라인에 복사되는 거기 때문에 실행 환경에선 ResultEffect 가 없어진 거나 마찬가지가 되어 해당 함수의 Stability 를 설정할 필요가 없네요.
(무작정 복붙 가져오기의 폐해...)

LaunchedEffect 의 키에는 ResultEventBus 인스턴스 자체는 상관이 없으니 @Stable 어노테이션이 의미가 없겠네요.

fun MainRoute(...) {                                                                                                                                                        
    val resultBus = LocalResultEventBus.current
                                                                                                                                                                            
    // ...                                                                                                                                                                

    // ---- ResultEffect가 여기에 펼쳐짐 ----
    Log.d("ResultEffect", "Recompose")
    LaunchedEffect(resultKey, resultBus.channelMap[resultKey]) {
        resultBus.getResultFlow<QRScanResult>(resultKey)?.collect { result ->
            // ...
        }
    }
    // ---- 여기까지 ----

    // ...
}

08b4282 불필요한 @Stable 어노테이션 제거했습니다!

`ResultEventBus` 클래스에 적용되어 있던 `@Stable` 어노테이션과 관련 임포트를 제거했습니다.
@ikseong00 ikseong00 merged commit 07dfb56 into develop Mar 2, 2026
3 checks passed
@ikseong00 ikseong00 deleted the feat/#154-archive-result branch March 2, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 사진 업로드 후 아카이빙 메인 사진 갱신 로직 추가

2 participants

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy