[Feature/#267] 플랫폼 연동 플로우 (Naver·Meta·Google 복귀·연동 해제)#284
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughNaver 연동 요청 바디 암호화, 플랫폼 연동 해제 API/모달, OAuth 복귀 처리 훅과 결과 페이지, 그리고 플랫폼 통합 페이지의 연결 흐름이 추가되거나 갱신됐습니다. Changes플랫폼 연동 완료 플로우
Estimated code review effort: 4 (Complex) | ~60분 Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
📚 Storybook 배포 완료
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (3)
src/routes/AuthRoutes.tsx (1)
10-10: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
MetaOAuthResultPage만 eager import로 번들에 포함됨
FindEmail,FindPw,Login,RedirectPage는 모두loadable(lazy(() => import(...)))패턴으로 코드 스플리팅되는데,MetaOAuthResultPage는 Line 10에서 직접 import되어 이 패턴을 따르지 않아요. 자주 방문하지 않는 OAuth 콜백 결과 페이지이므로 다른 라우트들과 일관되게 lazy 로딩하는 게 초기 번들 크기 관리에 유리합니다.♻️ 제안
-import MetaOAuthResultPage from "`@/pages/integration/MetaOAuthResultPage`"; +import { loadable } from "`@/lib/loadable`"; + +const MetaOAuthResultPage = loadable( + lazy(() => import("`@/pages/integration/MetaOAuthResultPage`")), + <AuthFormSkeleton />, +);Also applies to: 68-71
🤖 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/routes/AuthRoutes.tsx` at line 10, `MetaOAuthResultPage` is being eagerly imported in `AuthRoutes`, unlike `FindEmail`, `FindPw`, `Login`, and `RedirectPage` which use `loadable(lazy(() => import(...)))`; update the `MetaOAuthResultPage` route to follow the same lazy-loading pattern so the OAuth callback result page is code-split and not included in the initial bundle.src/hooks/integration/useIntegrationOAuthReturn.ts (1)
28-57: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win전체 쿼리 파라미터 초기화 방식 재검토 필요
orgId/processedRef가드 로직과QUERY_KEYS.platform.connections(orgId)무효화 흐름은 잘 짜여 있어요. 다만 Line 56에서setSearchParams({}, { replace: true })로 쿼리 스트링 전체를 비우고 있는데, 지금은status/provider/detail만 쓰지만 나중에/integrations에 필터/페이지네이션 같은 다른 쿼리 파라미터가 추가되면 이 로직이 그 값들까지 통째로 날려버립니다. 관련 파라미터만 선택적으로 지우는 방식이 더 안전합니다.♻️ 제안
- void queryClient.invalidateQueries({ - queryKey: QUERY_KEYS.platform.connections(orgId), - }); - - setSearchParams({}, { replace: true }); + void queryClient.invalidateQueries({ + queryKey: QUERY_KEYS.platform.connections(orgId), + }); + + const next = new URLSearchParams(searchParams); + next.delete("status"); + next.delete("provider"); + next.delete("detail"); + setSearchParams(next, { replace: true });🤖 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/integration/useIntegrationOAuthReturn.ts` around lines 28 - 57, The query reset in useIntegrationOAuthReturn currently clears every search parameter, which can accidentally remove unrelated `/integrations` state. Update the useLayoutEffect in useIntegrationOAuthReturn so it only removes the OAuth return params it consumes (status, provider, and detail) while preserving any other existing query parameters. Keep the existing orgId, processedRef, and QUERY_KEYS.platform.connections(orgId) flow intact, and adjust the setSearchParams call to perform selective cleanup instead of replacing the full query string.src/pages/integration/MetaOAuthResultPage.tsx (1)
6-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win처리 중 상태에 ARIA 라이브 리전 부재
현재는
<p>텍스트만 렌더링해서 스크린 리더 사용자는 "처리 중" → 리다이렉트 흐름을 인지하기 어렵습니다.role="status"또는aria-live="polite"를 추가하면 상태 변화를 알릴 수 있습니다. 경로 지침에도 시맨틱 HTML/ARIA 속성 사용을 검토하도록 되어 있습니다.♿ 제안
- <p className="font-body1 text-text-muted animate-pulse"> + <p role="status" aria-live="polite" className="font-body1 text-text-muted animate-pulse"> Meta 연동 결과를 처리하는 중... </p>As per path instructions, "7. 접근성: 시맨틱 HTML, ARIA 속성 사용 확인."
🤖 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/pages/integration/MetaOAuthResultPage.tsx` around lines 6 - 12, 현재 MetaOAuthResultPage의 처리 중 문구는 단순 텍스트로만 렌더링되어 스크린 리더에 상태 변경이 전달되지 않습니다. 이 컴포넌트의 상태 표시 영역에 role="status" 또는 aria-live="polite"를 추가해 처리 중/리다이렉트 흐름을 알릴 수 있도록 수정하고, 시맨틱 HTML과 ARIA 속성 사용이 적절한지 함께 점검하세요.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/components/integration/NaverConnectModal.tsx`:
- Around line 127-134: In NaverConnectModal’s Input for customerId, remove the
disabled state that is tied to reconnect mode and keep only readOnly there,
since disabling the field prevents React Hook Form from submitting customerId
and can break updateNaverAccount when it calls customerId.trim(). Keep disabled
only for isSubmitting, and use the existing register("customerId") field so the
value remains part of the form payload in reconnect mode.
In `@src/components/integration/PlatformDisconnectModal.tsx`:
- Around line 34-40: `PlatformDisconnectModal`의 `Modal`에 직접 넘기는 `onClose`가 로딩
중에도 호출되어 모달이 닫히는 문제가 있습니다. `isLoading` 상태를 확인하는 `handleClose` 같은 래퍼를 만들어, 요청 진행
중에는 오버레이 클릭·Escape·닫기 버튼의 닫힘 동작을 무시하도록 `Modal`의 `onClose`에 그 래퍼를 연결하세요.
`isLoading`, `onClose`, `PlatformDisconnectModal`, `Modal` 연결 부분을 기준으로 수정하면 됩니다.
In `@src/pages/integration/PlatformIntegrationsPage.tsx`:
- Around line 37-38: The disconnect flow in PlatformIntegrationsPage is using
the current render’s orgId from closure, which can change after the confirmation
modal opens. Update the disconnect mutation setup and the disconnectTarget state
handled by setDisconnectTarget / the disconnect action so that the selected item
also stores orgId at selection time and the DELETE request uses that captured
orgId instead of the latest render value. Use the existing symbols useState,
disconnectTarget, and the mutation around the disconnect handler to keep the
request fixed to the originally selected organization.
In `@src/utils/integration/encryptAesCbcBase64.ts`:
- Around line 3-8: The parseKeyOrIv helper currently only trims and parses the
value, so invalid AES lengths can pass through and fail later during Java
AES/CBC/PKCS5Padding decryption. Update parseKeyOrIv in encryptAesCbcBase64.ts
to validate the byte length after Utf8 parsing: allow only 16/24/32 bytes for
the key and exactly 16 bytes for the IV, and throw a clear error using the
existing label-based message when the length is invalid.
- Around line 16-32: The AES-CBC client-side encryption in encryptAesCbcBase64
uses VITE_NAVER_AES_SECRET and VITE_NAVER_AES_IV from the browser bundle, which
exposes the symmetric key material. Move the credential-handling flow out of the
client so apiKey/secretKey are encrypted or processed on the server instead, or
replace this with a server-public-key-based approach if client-side protection
is still required. Update encryptAesCbcBase64 and any callers so no sensitive
네이버 자격증명 depends on browser-visible secrets.
---
Nitpick comments:
In `@src/hooks/integration/useIntegrationOAuthReturn.ts`:
- Around line 28-57: The query reset in useIntegrationOAuthReturn currently
clears every search parameter, which can accidentally remove unrelated
`/integrations` state. Update the useLayoutEffect in useIntegrationOAuthReturn
so it only removes the OAuth return params it consumes (status, provider, and
detail) while preserving any other existing query parameters. Keep the existing
orgId, processedRef, and QUERY_KEYS.platform.connections(orgId) flow intact, and
adjust the setSearchParams call to perform selective cleanup instead of
replacing the full query string.
In `@src/pages/integration/MetaOAuthResultPage.tsx`:
- Around line 6-12: 현재 MetaOAuthResultPage의 처리 중 문구는 단순 텍스트로만 렌더링되어 스크린 리더에 상태
변경이 전달되지 않습니다. 이 컴포넌트의 상태 표시 영역에 role="status" 또는 aria-live="polite"를 추가해 처리
중/리다이렉트 흐름을 알릴 수 있도록 수정하고, 시맨틱 HTML과 ARIA 속성 사용이 적절한지 함께 점검하세요.
In `@src/routes/AuthRoutes.tsx`:
- Line 10: `MetaOAuthResultPage` is being eagerly imported in `AuthRoutes`,
unlike `FindEmail`, `FindPw`, `Login`, and `RedirectPage` which use
`loadable(lazy(() => import(...)))`; update the `MetaOAuthResultPage` route to
follow the same lazy-loading pattern so the OAuth callback result page is
code-split and not included in the initial bundle.
🪄 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
Run ID: a1ba388d-af81-4281-af79-bcb7cfa6e70b
⛔ Files ignored due to path filters (2)
package.jsonis excluded by none and included by nonepnpm-lock.yamlis excluded by!**/pnpm-lock.yaml,!pnpm-lock.yamland included by none
📒 Files selected for processing (10)
src/api/integration/naver.tssrc/api/integration/platformAccounts.tssrc/components/integration/NaverConnectModal.tsxsrc/components/integration/PlatformDisconnectModal.tsxsrc/hooks/integration/useIntegrationOAuthReturn.tssrc/hooks/integration/useMetaOAuthReturn.tssrc/pages/integration/MetaOAuthResultPage.tsxsrc/pages/integration/PlatformIntegrationsPage.tsxsrc/routes/AuthRoutes.tsxsrc/utils/integration/encryptAesCbcBase64.ts
🚨 관련 이슈
close #267
✨ 변경사항
✏️ 작업 내용
Naver
platformAccountId가 남아 있으면 PATCH로 재연동Google
/integrations?status=&provider=쿼리 처리 (useIntegrationOAuthReturn)Meta
/oauth2/meta/result결과 페이지 및 복귀 처리 (useMetaOAuthReturn)/integrations이동공통
DELETE /api/platform/{orgId}/accounts/{accountId}+ 확인 모달😅 미완성 작업
📢 논의 사항 및 참고 사항
MetaOAuthResultPage배포 후 운영(www.whereyouad.com)에서/oauth2/meta/result→ toast →/integrations흐름 확인이 필요합니다.Summary by CodeRabbit