Skip to content

perf: 산 좋아요 탭당 요청을 1건으로 줄이고 하트 상태를 likedByMe로 판정 - #230

Merged
howooyeon merged 2 commits into
mainfrom
howooyeon/perf-mountain-like-query
Oct 12, 2026
Merged

howooyeon merged 2 commits into
mainfrom
howooyeon/perf-mountain-like-query

Conversation

@howooyeon

Copy link
Copy Markdown
Member

🧩 작업 내용

저장한 산 하트가 버벅인다는 제보를 보다가, 요청 개수와 좋아요 상태 판정 구조 두 군데에 문제가 있어 함께 정리했습니다.

  • 좋아요 토글을 POST 단일 토글로 통일하고 응답의 liked로 캐시를 갱신 — 따라 나가던 GET /api/mountains/likes를 제거해 탭당 요청 1건
  • 하트 상태를 저장 목록 파생값 → 각 응답의 likedByMe 기반으로 전환
  • 낙관적 추가를 저장 목록 맨 앞 삽입으로 변경 (서버 createdAt DESC 정렬에 맞춤)
  • 스펙에 없는 DELETE /api/mountains/{id}/like 호출 제거
  • in-flight 가드를 isPending → ref로 교체해 같은 프레임 더블탭 차단
  • 캐시 동기화·중복 요청 차단 테스트 8건 추가

🐞 같이 고친 버그

저장한 산이 11개를 넘으면 하트가 틀어졌습니다.

기존에는 GET /api/mountains/likes를 page/size 없이 1회만 호출하고, 그 1페이지 content로 앱 전체의 하트 on/off를 판정했습니다. 서버 기본 page size가 10이라 11번째 이후로 저장한 산은 상세에 들어가도 하트가 꺼진 채 보이고, 그 하트를 누르면 이미 좋아요한 산에 좋아요 요청이 또 나갔습니다.

likedByMe 기반으로 바꾸면서 저장 목록 페이지네이션과 무관해졌습니다.

더블탭이 요청 2건을 보냈습니다.

isPending은 렌더 시점 값이라 같은 프레임에 두 번 눌리면 두 호출 모두 가드를 통과합니다. 테스트로 재현(POST 2건)한 뒤 ref로 동기 잠금했습니다. 서버에서 간헐적으로 관측된 동시 토글 500의 클라이언트 쪽 원인으로 보입니다.


📱 관련 화면 / 기능

  • 지도
  • 등산 기록
  • 코스 추천
  • 커뮤니티
  • 기타: 산 상세 / 저장한 산 목록

🔍 변경 전후

변경 전 변경 후
좋아요 ON POST + GET /likes (2건) POST (1건)
좋아요 OFF DELETE (스펙에 없음) POST (1건)
상세 진입 상세 + GET /likes 상세만
하트 상태 저장 목록 1페이지에 있는지 응답의 likedByMe
낙관적 추가 위치 목록 끝 (refetch 후 위로 점프) 목록 맨 앞

POST 단일 토글은 코스 좋아요(use-toggle-course-like.ts)·게시글 좋아요(use-post-like.ts)와 같은 컨벤션입니다. 산만 POST+DELETE를 쓰고 있었습니다.


✅ 검증

  • tsc --noEmit 통과
  • expo lint 0 errors (warning 19건은 모두 기존 파일)
  • jest 42건 통과 (신규 8건)

런타임 미검증 — 리뷰 때 확인 부탁드립니다

  1. GET /api/mountains/{id} 응답의 mountain.likedByMe가 실제로 채워지는지. 안 채워지면 상세 하트가 항상 꺼져 보입니다 (필드는 스펙에 존재)
  2. 최초 제보된 "버벅임"의 TTFB 측정은 별도로 진행 중입니다

💬 기타 사항

  • GET /api/mountains/likes 응답에 likedByMe를 추가하는 안은 필요 없어졌습니다. 하트가 더 이상 저장 목록을 읽지 않습니다
  • 서버에서 createdAt DESC, id DESC 정렬 고정과 멱등 토글 작업이 함께 진행 중입니다. 맨 앞 삽입은 그 정렬을 전제로 합니다
  • 별도 작업으로 남김: 저장한 산 목록 화면이 page/size 없이 1페이지만 불러와 최대 10개만 보입니다. 서버 정렬 고정이 머지된 뒤 무한스크롤로 붙이는 게 맞아 보여 이번 범위에서 제외했습니다

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 6 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: SEMOSAN/SEMOSAN_FE/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b9953f26-44b3-46df-8a59-3bcfaeb9bad7

📥 Commits

Reviewing files that changed from the base of the PR and between 8e9e4cd and 52b5e98.


📒 Files selected for processing (5)
  • app/mountains/[id].tsx
  • app/mypage/saved-mountains.tsx
  • features/mountains/components/mountain-bookmark-button.tsx
  • features/mountains/hooks/__tests__/use-mountain-bookmark.test.tsx
  • features/mountains/hooks/use-mountain-bookmark.ts

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@JioCoder

Copy link
Copy Markdown
Contributor

확인했습니다!

@howooyeon
howooyeon merged commit 7f46500 into main Oct 12, 2026
3 checks passed
@howooyeon
howooyeon deleted the howooyeon/perf-mountain-like-query branch October 12, 2026 12:13
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.

2 participants