Skip to content

리액션 API 연동#85

Open
chanho0908 wants to merge 6 commits intofeat/#83-phopolog-api-changefrom
feat/#83-reaction-api
Open

리액션 API 연동#85
chanho0908 wants to merge 6 commits intofeat/#83-phopolog-api-changefrom
feat/#83-reaction-api

Conversation

@chanho0908
Copy link
Member

@chanho0908 chanho0908 commented Feb 13, 2026

이슈 번호

#83

리뷰/머지 희망 기한 (선택)

작업내용

  • 리액션 API 연동

결과물

ww.mp4

리뷰어에게 추가로 요구하는 사항 (선택)

  • 아요랑 이야기 했을 때 낙관적 업데이트를 사용한다고 해서 우리도 동일하게 적용했어 😄
  • 리액션 광클시 API 요청 과부화 방지를 위해 디바운싱을 사용했어
    600L를 기준으로 잡은 이유는 1000L로 설정했을 때 리액션을 누른 후 진짜 빠르게 뒤로가기 버튼을 누를 경우
    API 요청이 되기 전에 화면이 죽어버리는 현상이 발생하더라구

그래서 내가 테스트 했을 때 600L 정도면 뒤로가기 버튼을 누르기 전까지 API 요청을 보내기 충분해서 600L로 정했어 !

혹시 디바운싱 말고 좋은 방법이 있다면 제안해줘도 좋아 ☺️
참고로 가영이가 리액션 해제 기능은 없다고해 1

TODO

  • [] 리액션 광클시 Jank 현상 해결
    버튼을 10번정도 눌렀을 때 발생하는 리컴포지션 횟순데 리액션 버튼을 누를 때 마다 리컴포지션이 발생해서
    버벅임이 발생하는게 아닌지 추측 ...
스크린샷 2026-02-12 오후 6 26 09

@chanho0908 chanho0908 self-assigned this Feb 13, 2026
@chanho0908 chanho0908 added the Feature Extra attention is needed label Feb 13, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

워크스루

이번 PR은 포토로그(Photolog) 기능에 반응(Reaction) 기능을 추가하는 계층별 기능 구현입니다. 네트워크 계층에서 새로운 API 엔드포인트(PUT /api/v1/photologs/{photologId}/reaction)를 정의하고, 이를 데이터 계층의 저장소를 통해 도메인 모델로 매핑합니다. UI 계층의 ViewModel에서는 반응 이벤트를 처리하기 위해 공유 흐름(SharedFlow)과 디바운싱 로직을 도입하며, 화면 컴포넌트의 데이터 소스를 조정합니다.

추정 코드 리뷰 노력도

🎯 3 (Moderate) | ⏱️ ~25 minutes


상세 리뷰

✅ 우수한 점

계층별 책임 분리가 명확합니다.

  • 도메인 계층에서 인터페이스 정의 → 데이터 계층에서 구현 → 네트워크 계층에서 API 통신 처리라는 깔끔한 흐름이 잘 드러나 있습니다.
  • GoalReactionType.toRequest() 확장 함수를 통해 도메인 모델에서 네트워크 모델로의 변환을 명시적으로 처리하고 있습니다.

반응 이벤트 처리가 잘 설계되어 있습니다.

  • MutableSharedFlow를 활용한 이벤트 기반 아키텍처, 그리고 debouncedistinctUntilChanged를 조합하여 중복 요청을 방지하는 점이 좋습니다.

💭 검토가 필요한 부분

TaskCertificationDetailScreen의 데이터 소스 변경

현재 변경:

uiState.currentGoal.partnerPhotolog?.reaction
// 이전: uiState.photoLogs.partnerPhotologs.reaction

질문: currentGoal.partnerPhotologphotoLogs.partnerPhotologs가 동일한 데이터를 참조하는지 확인이 필요합니다. 두 경로가 실제로 같은 객체를 가리키고 있으며, 이 변경으로 인해 예상치 못한 데이터 불일치가 발생하지 않을지 검토해주세요.


TaskCertificationDetailViewModel의 초기화 순서

// init 블록 내부
collectReactionFlow()
// + 초기 페치 및 이벤트 수집

개선 제안: collectReactionFlow()collectEvents() 이후에 호출될 경우, 초기 이벤트 처리 중 반응이 발생했을 때 아직 flow가 수집 중이 아닐 수 있습니다. 초기화 순서에 대한 명시적인 문서화나, flow 수집을 먼저 시작하는 것을 고려해보세요.


DefaultPhotoLogRepository의 에러 처리

override suspend fun reactToPhotolog(
    photologId: Long, 
    reaction: GoalReactionType
): AppResult<Unit> {
    return safeApiCall { 
        service.reactToPhotolog(photologId, reaction.toRequest())
    }
}

개선 제안: 현재 구현이 safeApiCall로 포장되어 있어 API 실패 시 에러가 전파됩니다. ViewModel의 reactToPhotolog()에서 이 반환값을 무시하고 있는데, 사용자에게 실패 피드백을 제공할 필요가 있다면 에러 토스트나 로깅을 추가하는 것이 좋습니다.


ReactionFlow의 버퍼 설정

코드에 명시되지 않았지만, MutableSharedFlow의 버퍼 크기와 BufferOverflow 전략 선택이 적절한지 확인해주세요:

  • 매우 빠른 연타 클릭 시 버퍼 오버플로우가 발생하지 않나요?
  • 현재 디바운스 간격(DEBOUNCE_INTERVAL)이 사용자 경험상 적절한가요?

📋 체크리스트

  • currentGoal.partnerPhotolog?.reaction 데이터 소스 변경이 기존 기능에 영향을 주지 않는지 확인
  • ViewModel 초기화 순서 및 flow 수집 타이밍 재검토
  • API 실패 시 사용자 피드백 메커니즘 확인
  • 반응 이벤트 디바운싱 시간값이 적절한지 검증
  • 네트워크 통신 중 UI 로딩 상태 처리 필요 여부 검토

전반적으로 아키텍처가 잘 설계되어 있으며, 위의 세부 사항들을 확인하시면 안정적인 기능이 될 것 같습니다! 👍

🚥 Pre-merge checks | ✅ 2 | ❌ 2
❌ Failed checks (2 warnings)
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.
Merge Conflict Detection ⚠️ Warning ⚠️ Unable to check for merge conflicts: Invalid branch name format
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경 사항을 명확하게 설명합니다. 리액션 API 연동이 이 PR의 핵심 목표이며 코드 변경 사항과 일치합니다.
Description check ✅ Passed PR 설명이 리액션 API 연동 구현이라는 변경사항과 관련이 있으며, 작업 내용, 구현 방식(낙관적 업데이트, 디바운싱), 그리고 알려진 이슈(Jank 현상)를 구체적으로 설명하고 있습니다.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#83-reaction-api
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch feat/#83-reaction-api
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

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.

@chanho0908
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 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

@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/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetailViewModel.kt`:
- Around line 53-63: collectReactionFlow currently uses distinctUntilChanged
which suppresses consecutive identical GoalReactionType emits and causes
toggle-off actions to be dropped; update the flow to include the reaction
intent/state or remove distinctUntilChanged: either (1) change the type emitted
by reactionFlow to carry both the GoalReactionType and a nullable/boolean
intended state (e.g., ReactionIntent or Pair<GoalReactionType, Boolean?>) and
update reduceReaction to emit that combined value so collectReactionFlow
collects and passes it to reactToPhotolog, or (2) simply remove
distinctUntilChanged from collectReactionFlow so every emit (including rapid
toggles) reaches debounce and reactToPhotolog; adjust reactToPhotolog signature
accordingly if you choose option (1). Ensure DEBOUNCE_INTERVAL,
collectReactionFlow, reactionFlow, reactToPhotolog, and reduceReaction are
updated consistently.
- Around line 65-72: reactToPhotolog currently performs an optimistic update but
provides no rollback on failure (onSuccess = {}), so add error handling in
launchResult: implement onError to revert the optimistic UI change (restore the
previous reaction/state for currentState.currentGoal.partnerPhotolog) and/or
show a user-facing message (toast/snackbar). Locate reactToPhotolog, the
photologId retrieval (currentState.currentGoal.partnerPhotolog?.photologId), and
the launchResult call (block = { photologRepository.reactToPhotolog(...) }) and
in the launchResult options set an onError handler that restores the prior state
and surfaces an error to the user.
🧹 Nitpick comments (1)
feature/task-certification/src/main/java/com/twix/task_certification/detail/TaskCertificationDetail.kt (1)

222-251: ReactionSection의 리컴포지션 최적화를 고려해 보세요.

PR에서 언급된 Jank 현상과 관련하여, 현재 ReactionSectionGoalReactionType?을 직접 받고 있어 리액션이 변경될 때마다 전체가 리컴포지션됩니다.

ReactionBarReactionEffect가 독립적으로 리컴포지션될 수 있도록, 각각을 별도의 scope로 분리하면 불필요한 리컴포지션을 줄일 수 있습니다. 예를 들어 effectTarget 변경이 ReactionBar의 리컴포지션을 유발하지 않도록 분리하는 것을 검토해 보세요.

또한, onSelectReaction 람다 내에서 effectTarget 상태 변경과 onClickReaction 호출이 동시에 일어나면서 한 프레임에 두 번의 상태 변경이 발생할 수 있습니다. 이것이 PR에서 언급된 리컴포지션 횟수 증가의 원인일 수 있습니다.

Comment on lines -56 to +70
},
block = { photologRepository.reactToPhotolog(photologId, reaction) },
onSuccess = {},
Copy link
Member Author

Choose a reason for hiding this comment

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

낙관적 업데이트를 하는 상황에서 UI는 업데이트 됐는데 실패 메시지가 뜨는게 이상하다고 생각해서 에러 토스트는 안띄우게 만들었어

만약 에러 토스트를 띄운다면 동시에 이전에 선택했던 리액션으로 롤백도 같이 되야할거 같은데
그 것 보다 UI는 무조건 업데이트 되면서 API 요청에 실패했을 경우 사용자가 이 화면에 다시 왔을 때
롤백 되는게 자연스러울 것 같은데 현수는 어떻게 생각해 ?

@chanho0908 chanho0908 requested a review from dogmania February 13, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant