Skip to content

[#275] 토스트를 통해 undo 액션이 구현되어 있을 경우 서버사이드로 책임을 이관하도록 개선한다#276

Merged
opficdev merged 11 commits intodevelopfrom
refactor/#275-undo-client2server
Mar 16, 2026
Merged

[#275] 토스트를 통해 undo 액션이 구현되어 있을 경우 서버사이드로 책임을 이관하도록 개선한다#276
opficdev merged 11 commits intodevelopfrom
refactor/#275-undo-client2server

Conversation

@opficdev
Copy link
Copy Markdown
Owner

@opficdev opficdev self-assigned this Mar 16, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 푸시 알림 및 웹 페이지 삭제 기능의 Undo 로직을 클라이언트에서 서버사이드로 전환하여 시스템의 견고성과 사용자 경험을 향상시키는 것을 목표로 합니다. Firebase Functions를 활용하여 삭제 요청 시 일정 유예 기간을 두어 사용자가 삭제를 취소할 수 있도록 하며, 이 기간이 지나면 데이터가 최종적으로 삭제됩니다. 이를 통해 클라이언트의 복잡성을 줄이고 데이터 일관성을 보장합니다.

Highlights

  • 서버사이드 Undo 기능 구현: 푸시 알림 및 웹 페이지 삭제에 대한 Undo 기능을 클라이언트에서 서버사이드로 이관하여 구현했습니다.
  • Firebase Functions 활용: Firebase Functions를 사용하여 삭제 요청, 삭제 취소, 최종 삭제 로직을 처리합니다.
  • 일시적 삭제 상태 도입: 삭제 요청 시 deletingAt 필드를 추가하여 일시적인 삭제 상태를 표시하고, 일정 시간(5초) 내에 Undo가 가능하도록 합니다.
  • 클라이언트 로직 변경: ViewModel에서 삭제 및 Undo 로직을 Firebase Functions 호출로 변경하고, UI 상태 관리 로직을 업데이트했습니다.
  • 의존성 주입 업데이트: 새로운 Undo UseCase를 등록하고 관련 Repository 및 Service에 의존성을 주입했습니다.
Changelog
  • DevLog/App/Assembler/DomainAssembler.swift
    • 푸시 알림 및 웹 페이지 삭제 취소 UseCase를 등록했습니다.
  • DevLog/Data/Repository/PushNotificationRepositoryImpl.swift
    • 푸시 알림 삭제 취소 기능을 추가했습니다.
  • DevLog/Data/Repository/WebPageRepositoryImpl.swift
    • 웹 페이지 삭제 취소 기능을 추가했습니다.
  • DevLog/Domain/Protocol/PushNotificationRepository.swift
    • 푸시 알림 삭제 취소 프로토콜을 추가했습니다.
  • DevLog/Domain/Protocol/WebPageRepository.swift
    • 웹 페이지 삭제 취소 프로토콜을 추가했습니다.
  • DevLog/Domain/UseCase/PushNotification/Delete/UndoDeletePushNotificationUseCase.swift
    • 푸시 알림 삭제 취소 UseCase 프로토콜을 추가했습니다.
  • DevLog/Domain/UseCase/PushNotification/Delete/UndoDeletePushNotificationUseCaseImpl.swift
    • 푸시 알림 삭제 취소 UseCase 구현체를 추가했습니다.
  • DevLog/Domain/UseCase/WebPage/Upsert/UndoDeleteWebPageUseCase.swift
    • 웹 페이지 삭제 취소 UseCase 프로토콜을 추가했습니다.
  • DevLog/Domain/UseCase/WebPage/Upsert/UndoDeleteWebPageUseCaseImpl.swift
    • 웹 페이지 삭제 취소 UseCase 구현체를 추가했습니다.
  • DevLog/Infra/Service/PushNotificationService.swift
    • Firebase Functions를 임포트하고 Functions 인스턴스를 초기화했습니다.
    • 푸시 알림 삭제 요청 및 삭제 취소 로직을 Firebase Functions 호출로 변경했습니다.
  • DevLog/Infra/Service/WebPageService.swift
    • Firebase Functions를 임포트하고 Functions 인스턴스를 초기화했습니다.
    • 웹 페이지 삭제 요청 및 삭제 취소 로직을 Firebase Functions 호출로 변경했습니다.
    • deletingAt 필드를 사용하여 일시적으로 삭제된 웹 페이지를 필터링하는 로직을 추가했습니다.
  • DevLog/Presentation/ViewModel/HomeViewModel.swift
    • isWebPageInputLoading 상태 변수를 isAppending으로 변경했습니다.
    • Todo 추가 액션 이름을 upsertTodo에서 addTodo로 변경했습니다.
    • 웹 페이지 삭제 취소 UseCase를 주입하고 관련 로직을 업데이트했습니다.
    • 삭제된 웹 페이지의 URL을 추적하는 deletedWebPageURLString 변수를 추가했습니다.
    • 웹 페이지 삭제 및 삭제 취소 로직을 서버사이드 연동에 맞춰 수정했습니다.
    • UI 상태 업데이트 및 로딩 인디케이터 로직을 조정했습니다.
  • DevLog/Presentation/ViewModel/PushNotificationListViewModel.swift
    • confirmDelete 액션을 제거했습니다.
    • 푸시 알림 삭제 취소 UseCase를 주입하고 관련 로직을 업데이트했습니다.
    • 삭제된 푸시 알림 ID를 추적하는 undoDeleteNotificationId 변수를 추가했습니다.
    • 푸시 알림 삭제 및 삭제 취소 로직을 서버사이드 연동에 맞춰 수정했습니다.
    • UI 상태 업데이트 및 로딩 인디케이터 로직을 조정했습니다.
  • DevLog/UI/Common/Component/WebItemRow.swift
    • 코드 포맷팅을 수정했습니다.
  • DevLog/UI/Common/MainView.swift
    • HomeViewModel과 PushNotificationListViewModel에 새로운 Undo UseCase를 주입했습니다.
  • DevLog/UI/Home/HomeView.swift
    • TodoEditorView의 onSubmit 액션을 .upsertTodo에서 .addTodo로 변경했습니다.
    • 웹 페이지 삭제 토스트의 onDismiss 액션을 제거했습니다.
    • 로딩 오버레이에 isWebPageInputLoading 대신 isAppending 상태를 사용하도록 변경했습니다.
    • 최근 Todo 및 웹 페이지 섹션의 로딩 및 빈 상태 표시 로직을 개선했습니다.
  • DevLog/UI/PushNotification/PushNotificationListView.swift
    • 푸시 알림 삭제 토스트의 onDismiss 액션을 제거했습니다.
  • Firebase/functions/src/common/error.ts
    • 오류 객체를 정규화하는 normalizeError 유틸리티 함수를 추가했습니다.
  • Firebase/functions/src/index.ts
    • 푸시 알림 및 웹 페이지 삭제/취소 관련 Firebase Functions를 임포트하고 익스포트했습니다.
  • Firebase/functions/src/notification/deletion.ts
    • 푸시 알림 삭제 요청, 삭제 취소, 최종 삭제를 처리하는 Firebase Functions를 추가했습니다.
  • Firebase/functions/src/todo/deletion.ts
    • normalizeError 함수를 common/error.ts로 이동하고 기존 정의를 제거했습니다.
  • Firebase/functions/src/webPage/deletion.ts
    • 웹 페이지 삭제 요청, 삭제 취소, 최종 삭제를 처리하는 Firebase Functions를 추가했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

이번 PR은 토스트 메시지를 통한 '삭제 실행 취소' 기능의 책임을 클라이언트에서 서버로 성공적으로 이관했습니다. Firebase Functions와 Cloud Tasks를 활용하여 지연 삭제(deferred deletion) 패턴을 구현한 점이 인상적이며, 이를 통해 앱의 안정성과 데이터 정합성이 크게 향상될 것으로 기대됩니다.

전반적으로 훌륭한 개선이지만, 코드의 명확성과 유지보수성을 더욱 높일 수 있는 몇 가지 부분을 발견하여 리뷰 코멘트를 남겼습니다. ViewModel에서의 비동기 처리 로직을 일부 단순화하고, Firebase Functions의 중복 코드를 추상화하는 방안을 제안했습니다. 확인 부탁드립니다.

Comment thread DevLog/Presentation/ViewModel/HomeViewModel.swift
Comment on lines +158 to +167
case .undoDelete(let notificationId):
Task {
do {
try await undoDeleteUseCase.execute(notificationId)
send(.fetchNotifications)
} catch {
send(.setAlert(isPresented: true))
send(.fetchNotifications)
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

undoDelete 사이드 이펙트 처리 시, undoDeleteUseCase.execute가 실패하더라도 send(.fetchNotifications)를 호출하고 있습니다. 삭제 취소에 실패했는데 목록을 다시 불러오면 사용자가 삭제했던 항목이 그대로 사라져 있어 혼란을 줄 수 있습니다. 삭제 취소 실패 시에는 오류 알림만 표시하고, 목록을 다시 로드하지 않는 것이 더 나은 사용자 경험을 제공할 것입니다.

        case .undoDelete(let notificationId):
            Task {
                do {
                    try await undoDeleteUseCase.execute(notificationId)
                    send(.fetchNotifications)
                } catch {
                    send(.setAlert(isPresented: true))
                }
            }

Comment on lines 168 to 176
case .toggleRead(let notificationId):
Task {
do {
defer { send(.setLoading(false)) }
send(.setLoading(true))
try await toggleReadUseCase.execute(todoId)
try await toggleReadUseCase.execute(notificationId)
} catch {
send(.setAlert(isPresented: true))
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

run 함수의 toggleRead 사이드 이펙트 처리부에서 notificationId라는 파라미터명을 사용하고 있지만, 실제로는 reduceByUser에서 item.todoId를 전달하고 있습니다. 이는 코드의 의도를 파악하는 데 혼란을 줄 수 있으므로, 실제 전달되는 값의 의미에 맞게 파라미터명을 todoId로 명확하게 변경하는 것이 좋겠습니다.

        case .toggleRead(let todoId):
            Task {
                do {
                    defer { send(.setLoading(false)) }
                    send(.setLoading(true))
                    try await toggleReadUseCase.execute(todoId)
                } catch {
                    send(.setAlert(isPresented: true))
                }
            }

Comment thread Firebase/functions/src/notification/deletion.ts
@opficdev opficdev merged commit 602f80b into develop Mar 16, 2026
2 checks passed
@opficdev opficdev deleted the refactor/#275-undo-client2server branch March 16, 2026 01:31
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.

토스트를 통해 undo 액션이 구현되어 있을 경우 서버사이드로 책임을 이관하도록 개선한다

1 participant