Skip to content

[Feature/#267] 플랫폼 연동 플로우 (Naver·Meta·Google 복귀·연동 해제)#284

Merged
YermIm merged 7 commits into
developfrom
feature/#267
Jul 9, 2026
Merged

[Feature/#267] 플랫폼 연동 플로우 (Naver·Meta·Google 복귀·연동 해제)#284
YermIm merged 7 commits into
developfrom
feature/#267

Conversation

@YermIm

@YermIm YermIm commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

close #267

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

Naver

  • apiKey/secretKey AES 암호화 후 연동 API 호출
  • 연동(POST) / 재연동(PATCH) 모달 분기
  • 연동 해제 후 platformAccountId가 남아 있으면 PATCH로 재연동

Google

  • OAuth 완료 후 /integrations?status=&provider= 쿼리 처리 (useIntegrationOAuthReturn)

Meta

  • OAuth 완료 후 /oauth2/meta/result 결과 페이지 및 복귀 처리 (useMetaOAuthReturn)
  • status별 toast (success / partial / denied / error) 후 /integrations 이동

공통

  • 연동 해제 DELETE /api/platform/{orgId}/accounts/{accountId} + 확인 모달

😅 미완성 작업

  • Google OAuth 엑세스 오류
  • Meta 운영 E2E — main 배포 후 결과 페이지 동작 확인

📢 논의 사항 및 참고 사항

  • Google: OAuth 연동 시 액세스 오류가 있어 해결 중입니다.
  • Meta: MetaOAuthResultPage 배포 후 운영(www.whereyouad.com)에서 /oauth2/meta/result → toast → /integrations 흐름 확인이 필요합니다.
  • 연동 해제 권한: Swagger 기준 ADMIN + 최초 연동자만 해제 가능하나, ADMIN 권한 분기(버튼 숨김/비활성)는 추후 작업 예정입니다.

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

  • New Features
    • 네이버 계정 연동이 재연동 모드까지 지원되며, 고객 ID가 모드에 맞게 자동 설정/읽기 전용 처리됩니다.
    • 플랫폼 계정 연동 해제 확인 모달을 추가했습니다.
    • Meta OAuth 연동 결과 페이지와 결과 안내(성공/부분/거부 등) 및 연동 목록 자동 갱신을 제공합니다.
  • Bug Fixes
    • 네이버 연동 요청에 민감정보 암호화 전송이 적용되었습니다.
    • 연동/해제 성공·실패 토스트 표시와 중복 실행 방지가 개선되었습니다.

@YermIm YermIm requested review from Seojegyeong and jjjsun July 6, 2026 19:20
@YermIm YermIm self-assigned this Jul 6, 2026
@YermIm YermIm added the 📬 API 서버 API 통신 label Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 79e79d09-d578-4c2d-8c14-833dc414fdaf

📥 Commits

Reviewing files that changed from the base of the PR and between 5fd364a and 61e55d1.

📒 Files selected for processing (4)
  • src/components/integration/NaverConnectModal.tsx
  • src/components/integration/PlatformDisconnectModal.tsx
  • src/pages/integration/PlatformIntegrationsPage.tsx
  • src/utils/integration/encryptAesCbcBase64.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/utils/integration/encryptAesCbcBase64.ts
  • src/components/integration/PlatformDisconnectModal.tsx
  • src/components/integration/NaverConnectModal.tsx
  • src/pages/integration/PlatformIntegrationsPage.tsx

📝 Walkthrough

Walkthrough

Naver 연동 요청 바디 암호화, 플랫폼 연동 해제 API/모달, OAuth 복귀 처리 훅과 결과 페이지, 그리고 플랫폼 통합 페이지의 연결 흐름이 추가되거나 갱신됐습니다.

Changes

플랫폼 연동 완료 플로우

Layer / File(s) Summary
Naver 연동 암호화와 API
src/utils/integration/encryptAesCbcBase64.ts, src/api/integration/naver.ts
AES-CBC Base64 암호화 유틸이 추가되고, Naver 연동 요청이 암호화된 바디를 사용하도록 바뀌었으며 updateNaverAccount가 추가됨.
Naver 재연동 모달
src/components/integration/NaverConnectModal.tsx
재연동 모드, 초기 고객 ID, 모드별 제출/표시 문구와 입력 상태가 추가됨.
연동 해제 API와 확인 모달
src/api/integration/platformAccounts.ts, src/components/integration/PlatformDisconnectModal.tsx
플랫폼 계정 해제 DELETE API와 연동 해제 확인 모달이 추가됨.
OAuth 복귀 처리와 결과 페이지
src/hooks/integration/useIntegrationOAuthReturn.ts, src/hooks/integration/useMetaOAuthReturn.ts, src/pages/integration/MetaOAuthResultPage.tsx, src/routes/AuthRoutes.tsx
OAuth 콜백 쿼리 처리 훅과 Meta 결과 페이지, 해당 라우트가 추가됨.
PlatformIntegrationsPage 배선
src/pages/integration/PlatformIntegrationsPage.tsx
연동/재연동/해제 상태와 핸들러가 페이지에 연결되고, 카드와 모달 콜백이 갱신됨.

Estimated code review effort: 4 (Complex) | ~60분

Possibly related PRs

Suggested reviewers: Seojegyeong

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning [#267] OAuth 복귀, 연동 해제, Naver 재연동은 반영됐지만 최초/수동 동기화 API 연동은 확인되지 않습니다. 초기/수동 동기화 API를 실제로 추가했는지 반영하고, 없다면 작업 범위에서 제외된 이유를 명시해 주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 플랫폼 연동 복귀, 재연동, 연동 해제라는 핵심 변경점을 잘 요약하고 있어 제목과 변경 내용이 잘 맞습니다.
Description check ✅ Passed 관련 이슈, 변경사항, 작업 내용, 미완성 작업, 참고 사항이 모두 있어 템플릿 요구를 대부분 충족합니다.
Out of Scope Changes check ✅ Passed 추가된 변경들은 모두 Naver, Meta, Google 연동 및 해제 흐름과 직접 연결되어 있어 범위 밖 변경은 보이지 않습니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#267

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.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

항목 링크
📖 Storybook https://69a147b60a56365d9e2185ef-mdteojbewa.chromatic.com/
🔍 Chromatic https://www.chromatic.com/build?appId=69a147b60a56365d9e2185ef&number=400

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0e51f7b and 5fd364a.

⛔ Files ignored due to path filters (2)
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by none
📒 Files selected for processing (10)
  • src/api/integration/naver.ts
  • src/api/integration/platformAccounts.ts
  • src/components/integration/NaverConnectModal.tsx
  • src/components/integration/PlatformDisconnectModal.tsx
  • src/hooks/integration/useIntegrationOAuthReturn.ts
  • src/hooks/integration/useMetaOAuthReturn.ts
  • src/pages/integration/MetaOAuthResultPage.tsx
  • src/pages/integration/PlatformIntegrationsPage.tsx
  • src/routes/AuthRoutes.tsx
  • src/utils/integration/encryptAesCbcBase64.ts

Comment thread src/components/integration/NaverConnectModal.tsx
Comment thread src/components/integration/PlatformDisconnectModal.tsx
Comment thread src/pages/integration/PlatformIntegrationsPage.tsx Outdated
Comment thread src/utils/integration/encryptAesCbcBase64.ts Outdated
Comment thread src/utils/integration/encryptAesCbcBase64.ts
@YermIm YermIm added the ✨ Feature 기능 개발 label Jul 6, 2026

@Seojegyeong Seojegyeong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4: 확인했습니다!

@jjjsun jjjsun left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4: 확인했습니다!

@YermIm YermIm merged commit 97afd1b into develop Jul 9, 2026
3 checks passed
@YermIm YermIm deleted the feature/#267 branch July 9, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📬 API 서버 API 통신 ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ [Feature] 플랫폼 연동 완료 플로우 및 관리 API 연동

3 participants