feat: 기사·견적 상세 카카오톡 공유 및 OG 메타 추가 - #34
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough견적·기사 상세 라우트가 동적 메타데이터와 ID 검증을 사용하도록 변경되었습니다. 카카오 SDK 커스텀 공유, 템플릿 데이터 생성, 공유 UI 연결이 추가되었고, 기사 상세에는 서버 프리패치와 hydration이 적용되었습니다. Changes공유 및 메타데이터
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant DetailPage
participant EstimateDetailShare
participant KakaoShareHook
participant KakaoSDK
DetailPage->>EstimateDetailShare: 카카오 템플릿 데이터 전달
EstimateDetailShare->>KakaoShareHook: 커스텀 공유 호출
KakaoShareHook->>KakaoSDK: SDK 로드·초기화 및 sendCustom
KakaoSDK-->>EstimateDetailShare: 성공 또는 오류 콜백
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/lib/kakao/sdk.ts (1)
4-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff브라우저 SDK 부수효과를
src/lib밖으로 분리하세요.SDK script 삽입·초기화·공유 전송은 모두 브라우저 부수효과입니다. 클라이언트 훅 또는 UI 어댑터로 옮기고,
src/lib에는 순수한 템플릿 인자·설정 변환만 남기세요.
src/lib/kakao/sdk.ts#L4-L57:window/document기반 SDK 로딩과 초기화를 클라이언트 전용 훅 또는 어댑터로 이동하세요.src/lib/kakao/shareCustom.ts#L49-L77:ensureKakaoSdk()및sendCustom()호출을 해당 클라이언트 계층으로 이동하세요.As per path instructions,
src/lib/**/*.ts: “순수 함수로 작성하고 부수효과를 두지 않습니다.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/kakao/sdk.ts` around lines 4 - 57, Move the browser-dependent SDK loading and initialization from ensureKakaoSdk in src/lib/kakao/sdk.ts (lines 4-57) into a client-only hook or UI adapter, leaving src/lib with only pure configuration or template transformations. Also move the ensureKakaoSdk and sendCustom calls from src/lib/kakao/shareCustom.ts (lines 49-77) into that client layer; both sites must be updated so src/lib/**/*.ts contains no window/document access or browser side effects.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/kakao/sdk.ts`:
- Around line 13-25: Update the existing-script handling in the Kakao SDK loader
so a load failure removes that script element from the document before
rejecting. Ensure the error listener in the existing-script branch removes the
failed element, allowing subsequent calls to insert and await a fresh script
while preserving the current rejection behavior.
In `@src/lib/share/openGraph.ts`:
- Around line 28-35: Update the hostname check in the URL handling block to
match picsum.photos only when the hostname is exactly picsum.photos or is a
valid subdomain ending with .picsum.photos, preventing unrelated domains such as
notpicsum.photos from matching.
---
Nitpick comments:
In `@src/lib/kakao/sdk.ts`:
- Around line 4-57: Move the browser-dependent SDK loading and initialization
from ensureKakaoSdk in src/lib/kakao/sdk.ts (lines 4-57) into a client-only hook
or UI adapter, leaving src/lib with only pure configuration or template
transformations. Also move the ensureKakaoSdk and sendCustom calls from
src/lib/kakao/shareCustom.ts (lines 49-77) into that client layer; both sites
must be updated so src/lib/**/*.ts contains no window/document access or browser
side effects.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 270782fe-54bb-4c42-9df8-225fc0418b7c
📒 Files selected for processing (18)
src/app/estimates/[estimateId]/page.tsxsrc/app/estimates/pending/[estimateId]/page.tsxsrc/app/estimates/requests/[estimateRequestId]/page.tsxsrc/app/movers/[moverId]/page.tsxsrc/components/estimate/detail/EstimateDetailShare.tsxsrc/components/estimate/detail/EstimateDetailView.tsxsrc/components/estimate/pending/PendingEstimateDetailView.tsxsrc/components/estimate/requests/EstimateRequestDetailView.tsxsrc/components/mover/detail/MoverDetailView.tsxsrc/lib/api/movers.tssrc/lib/kakao/sdk.tssrc/lib/kakao/shareCustom.tssrc/lib/share/copy.tssrc/lib/share/metadata.tssrc/lib/share/openGraph.tssrc/lib/utils/appUrl.tssrc/lib/utils/parsePositiveIntId.tssrc/types/kakao.d.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/hooks/kakao/share.ts (1)
18-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHook이 아닌 공유 유틸을
src/hooks밖으로 이동하세요.이 파일은 React Hook이 아니라 이벤트 핸들러에서 호출되는 SDK 공유 유틸입니다.
src/lib/kakao/share.ts로 옮기고 현재 import 경로를 갱신해 Hook 규칙과 모듈 역할을 일치시키세요.As per path instructions,
src/hooks/**/*.{ts,tsx}files and functions must start withuse.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/hooks/kakao/share.ts` around lines 18 - 44, Move the non-hook sendKakaoCustomShare utility from the hooks module to src/lib/kakao/share.ts, then update every import and caller to use the new module path. Preserve its existing configuration checks, SDK sharing behavior, and error callbacks.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/kakao/shareTemplate.ts`:
- Around line 24-25: Update the template ID validation in the parsing logic
around trimmed environment values to accept only positive safe integers. Replace
the finite-number check with Number.isSafeInteger(templateId) and a templateId >
0 condition, returning null for negative, zero, fractional, unsafe, or
non-numeric values before they reach sendCustom.
---
Nitpick comments:
In `@src/hooks/kakao/share.ts`:
- Around line 18-44: Move the non-hook sendKakaoCustomShare utility from the
hooks module to src/lib/kakao/share.ts, then update every import and caller to
use the new module path. Preserve its existing configuration checks, SDK sharing
behavior, and error callbacks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d48d5294-1af8-4268-937f-cd88d4ae198a
📒 Files selected for processing (8)
src/components/estimate/detail/EstimateDetailShare.tsxsrc/components/estimate/detail/EstimateDetailView.tsxsrc/components/estimate/pending/PendingEstimateDetailView.tsxsrc/components/estimate/requests/EstimateRequestDetailView.tsxsrc/components/mover/detail/MoverDetailView.tsxsrc/hooks/kakao/sdk.tssrc/hooks/kakao/share.tssrc/lib/kakao/shareTemplate.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/mover/detail/MoverDetailView.tsx
juengseulki
left a comment
There was a problem hiding this comment.
📋 PR 리뷰
👍 좋았던 점
- 카카오 공유 템플릿 데이터 생성과 SDK 로드·전송 로직을 분리해 역할이 명확했습니다.
- Kakao SDK가 이미 존재하는지와 초기화 여부를 확인해 중복 로드 및 중복 초기화를 방지했습니다.
- SDK 로드 실패 시 script를 제거해 이후 재시도가 가능하도록 처리한 점이 좋았습니다.
환경변수가 누락된 경우와 SDK 실행 중 오류가 발생한 경우를 구분해 사용자에게 Toast로 전달했습니다. - 기사 상세와 견적 상세에서 사용하는 공유 문구와 OG 메타 생성 규칙을 공통 모듈로 정리해 이후 문구 수정 범위를 줄였습니다.
- 기사 상세는 getMoverDetailCached와 React Query prefetch, HydrationBoundary를 함께 사용해 서버에서 조회한 데이터를 클라이언트 초기 캐시에도 전달하도록 구성했습니다.
- OG 이미지 URL을 절대 경로로 변환하고, 스크랩이 불안정할 수 있는 이미지에는 기본 이미지를 적용하는 방어 로직도 확인했습니다.
🔍 확인 및 제안
인라인 코멘트로 아래 내용을 남겼습니다!
- 기사 상세의 prefetch는 서버 요청 재사용뿐 아니라 React Query 초기 캐시를 제공하는 목적도 있으므로 현재 구조를 유지해도 괜찮아 보입니다.
- 카카오 템플릿 ID는 양의 정수 여부까지 검증하면 환경변수 오설정을 조금 더 명확하게 방어할 수 있습니다.
전체적으로 카카오 공유 기능 자체는 공유 UI, 템플릿 데이터, SDK 부수효과, OG 생성 로직을 역할별로 잘 분리했습니다. 다만 견적 상세 페이지는 인증이 필요한 개인 데이터이기 때문에, 외부 크롤러가 해당 데이터를 조회할 수 있는지에 따라 동적 OG의 실제 동작 여부가 달라질 것 같습니다. 이 부분만 먼저 확인한 뒤 승인하는 것이 안전해 보여요. 수고하셨습니다! 😊
1ff0a14 to
09b9f36
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/components/estimate/detail/EstimateDetailShare.tsx (2)
155-160: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win페이스북 버튼을 유휴 상태에서도 비활성화하세요.
현재는
isBusy일 때만 비활성화되어 평소에는shareFacebook이 실행됩니다. PR 목표대로 비활성 상태를 유지하려면 항상disabled처리하고 클릭 핸들러를 제거하세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/estimate/detail/EstimateDetailShare.tsx` around lines 155 - 160, Update the Facebook share button in EstimateDetailShare so it is always disabled, regardless of isBusy, and remove its shareFacebook onClick handler. Keep the existing aria-label and aria-busy attributes unchanged.
140-145: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win커스텀 공유도 단일 실행 상태에 포함하세요.
커스텀 분기는
usePageShare의busyAction을 설정하지 않아 SDK 로딩 중에도 버튼이 활성 상태로 남습니다. 연속 클릭하면sendCustom()이 여러 번 실행될 수 있으니, 커스텀 전송도 공통 exclusive 실행 경로로 감싸세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/estimate/detail/EstimateDetailShare.tsx` around lines 140 - 145, Update the custom share branch in EstimateDetailShare, using the existing usePageShare busyAction/exclusive execution path, so custom sending is marked busy during SDK loading and sendCustom cannot run concurrently. Keep the current Kakao share behavior unchanged and ensure the custom button remains disabled while the shared action is in progress.src/lib/kakao/share.ts (1)
3-103: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift카카오 SDK 로더를 하나로 통합하고 실패한 script는 제거하세요.
src/lib/kakao/share.ts와src/hooks/kakao/sdk.ts가 각각kakao.min.js를 다른 URL(2.7.4/2.7.5)로 넣고,src/lib/kakao/share.ts는 에러 난 script를 DOM에 남깁니다. 같은 화면에서usePageShare와EstimateDetailShare가 둘 다 이 경로를 타면 중복 로드/경합으로 공유가 멈출 수 있으니, 단일 로더 + 단일 버전으로 합치고 실패 시 script를 정리하세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/kakao/share.ts` around lines 3 - 103, Unify the Kakao SDK loading and sharing paths across src/lib/kakao/share.ts (lines 3-103), src/hooks/kakao/sdk.ts (lines 3-64), and src/hooks/kakao/share.ts (lines 18-78) behind one shared loader using a single SDK version and shared in-flight promise. Update all affected callers to reuse that loader, and ensure failed script loads remove the script element and reset loader state before rejecting; preserve the existing initialization and sharing behavior.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/kakao/shareTemplate.ts`:
- Around line 24-25: Update the templateId validation to require
Number.isSafeInteger(templateId) and templateId > 0 instead of Number.isInteger,
ensuring values beyond JavaScript’s safe integer range are rejected before
transmission.
In `@src/lib/share/metadata.ts`:
- Around line 59-80: Refactor generateReceivedEstimateMetadata so it no longer
calls fetchReceivedEstimateDetail or handles ApiError responses. Move the fetch
and 404/fallback policy to the route or src/lib/api layer, and make the share
utility accept received-estimate detail data and only build Metadata through
buildEstimateDetailMetadata while preserving the existing mover and image
fields.
---
Outside diff comments:
In `@src/components/estimate/detail/EstimateDetailShare.tsx`:
- Around line 155-160: Update the Facebook share button in EstimateDetailShare
so it is always disabled, regardless of isBusy, and remove its shareFacebook
onClick handler. Keep the existing aria-label and aria-busy attributes
unchanged.
- Around line 140-145: Update the custom share branch in EstimateDetailShare,
using the existing usePageShare busyAction/exclusive execution path, so custom
sending is marked busy during SDK loading and sendCustom cannot run
concurrently. Keep the current Kakao share behavior unchanged and ensure the
custom button remains disabled while the shared action is in progress.
In `@src/lib/kakao/share.ts`:
- Around line 3-103: Unify the Kakao SDK loading and sharing paths across
src/lib/kakao/share.ts (lines 3-103), src/hooks/kakao/sdk.ts (lines 3-64), and
src/hooks/kakao/share.ts (lines 18-78) behind one shared loader using a single
SDK version and shared in-flight promise. Update all affected callers to reuse
that loader, and ensure failed script loads remove the script element and reset
loader state before rejecting; preserve the existing initialization and sharing
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 4251d848-d7bf-46f3-a313-fb92a68444be
📒 Files selected for processing (21)
src/app/estimates/[estimateId]/page.tsxsrc/app/estimates/pending/[estimateId]/page.tsxsrc/app/estimates/requests/[estimateRequestId]/page.tsxsrc/app/movers/[moverId]/page.tsxsrc/components/estimate/RejectedRequestsPage.tsxsrc/components/estimate/detail/EstimateDetailShare.tsxsrc/components/estimate/detail/EstimateDetailView.tsxsrc/components/estimate/pending/PendingEstimateDetailView.tsxsrc/components/estimate/requests/EstimateRequestDetailView.tsxsrc/components/mover/detail/MoverDetailView.tsxsrc/hooks/kakao/sdk.tssrc/hooks/kakao/share.tssrc/lib/api/movers.tssrc/lib/kakao/share.tssrc/lib/kakao/shareTemplate.tssrc/lib/share/copy.tssrc/lib/share/metadata.tssrc/lib/share/openGraph.tssrc/lib/utils/appUrl.tssrc/lib/utils/parsePositiveIntId.tssrc/types/kakao.d.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/lib/utils/parsePositiveIntId.ts
- src/types/kakao.d.ts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/estimate/detail/EstimateDetailShare.tsx (1)
81-173: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win카카오 공유 요청도 버튼 잠금 상태에 포함하세요.
isBusy는 링크 복사·Facebook만 추적합니다.ensureKakaoSdk()를 기다리는 동안 반복 클릭하면sendCustom이 여러 번 호출될 수 있습니다. 카카오 공유도 ref 기반 가드와 pending state로 감싸고, 세 버튼의disabled/aria-busy에 반영하세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/estimate/detail/EstimateDetailShare.tsx` around lines 81 - 173, Update handleKakaoShare to use a ref-based re-entry guard and pending state while awaiting ensureKakaoSdk/sendCustom, preventing repeated Kakao share calls. Include the Kakao pending state in the shared busy/disabled logic, and expose it through the Kakao button’s aria-busy and disabled attributes alongside the existing copy and Facebook states.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/components/estimate/detail/EstimateDetailShare.tsx`:
- Around line 81-173: Update handleKakaoShare to use a ref-based re-entry guard
and pending state while awaiting ensureKakaoSdk/sendCustom, preventing repeated
Kakao share calls. Include the Kakao pending state in the shared busy/disabled
logic, and expose it through the Kakao button’s aria-busy and disabled
attributes alongside the existing copy and Facebook states.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: ad12f46c-f74a-4114-a2c5-048449b3c122
📒 Files selected for processing (10)
src/components/estimate/detail/EstimateDetailShare.tsxsrc/components/estimate/detail/EstimateDetailView.tsxsrc/components/estimate/pending/PendingEstimateDetailView.tsxsrc/components/estimate/requests/EstimateRequestDetailView.tsxsrc/hooks/kakao/share.tssrc/hooks/usePageShare.tssrc/lib/kakao/share.tssrc/lib/share/metadata.tssrc/lib/share/shareText.tssrc/lib/share/shareUrl.ts
💤 Files with no reviewable changes (1)
- src/lib/kakao/share.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/lib/share/metadata.ts
- copyLink(클립보드)와 구분되도록 OG·카카오용 문구 파일명 변경
263e91d to
29b2d59
Compare
📋 작업 내용
기사/견적 상세 페이지에서 카카오톡 공유 기능을 구현하고, OG 메타를 추가합니다.
🔥 변경 사항
카카오 공유
hooks/kakao/sdk.ts로 분리sendCustom기반 공유:hooks/kakao/share.tslib/kakao/shareTemplate.tsOG 메타
lib/share/openGraph.ts,metadata.ts,shareText.ts추가generateMetadata연동공유 UI (
EstimateDetailShare)usePageShare+copyLink.tsfacebookShare.ts연동 유지, 버튼은 배포 URL·OG 준비 전까지 비활성화 (FACEBOOK_SHARE_UI_ENABLED = false)linkAccess="owner"): 권한 안내 인라인 표시적용 페이지
movers/[moverId]— 기사 상세 (generateMetadata+ 상세 prefetch(HydrationBoundary))estimates/[estimateId]— 받은 견적 상세estimates/pending/[estimateId]— 대기 견적 상세estimates/requests/[estimateRequestId]— 보낸 견적 요청 상세✅ 체크리스트
📷 스크린샷 (선택)
견적 상세 페이지: 인라인 문구 표시
기사 상세 페이지 공유
견적 상세 페이지 공유 (일반 고객이 보낸 견적 / 기사가 보낸 견적)
기사 상세 페이지 Sharing Debugger로 테스트
💬 To Reviewer
sendCustom)만 사용합니다.sendDefault경로는 제거했습니다.FACEBOOK_SHARE_UI_ENABLED만 true로 바꾸면 됩니다.NEXT_PUBLIC_APP_URL,NEXT_PUBLIC_KAKAO_JS_KEY,NEXT_PUBLIC_KAKAO_*_SHARE_TEMPLATE_ID환경 변수 추가가 필요합니다. 실제 값은 노션 문서에 추가해놓았습니다!generateMetadata용으로 서버에서 이미 가져온 데이터를 클라이언트 React Query에도 prefetch해서 같은 요청을 두 번 하지 않도록 했습니다. (getMoverDetailCached+prefetch).fetch와 화면용useQuery둘 다 존재함)Summary by CodeRabbit