Skip to content

[Deploy] develop → main 배포 반영 - #335

Merged
Seojegyeong merged 67 commits into
mainfrom
develop
Jul 28, 2026
Merged

Seojegyeong merged 67 commits into
mainfrom
develop

Conversation

@Seojegyeong

@Seojegyeong Seojegyeong commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

#276 #277 #305 #306 #313 #318 #319 #324 #325

✨ 변경사항

  • 🐞 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.)

✏️ 작업 내용

  • 랜딩 · 로그인/회원가입/아이디·비밀번호 찾기 · 대시보드 · 캠페인 관리 모바일 반응형 적용 및 세부 스타일(폰트, 여백, 카드 레이아웃, 목업 데이터) 조정
  • 플랫폼별 비교 API 요청 기간을 2026-03-23 ~ 2026-07-07로 수정
  • 단일/전체 플랫폼 실시간 트래픽 SSE 연동 및 mock 데이터 제거
  • 클릭 스트림 providerType 지원, 이상 클릭 탐지 UI 연동 및 해제 시 잔존 마커/버블 제거, aria-describedby 연결(접근성)
  • 모달 focus trap 및 키보드 네비게이션 구현
  • CSP 보안 헤더 CloudFront Function 추가 및 CI 배포 자동화
  • Lighthouse CI 파이프라인 구축 및 CI 빌드 크래시(VITE_API_BASE_URL 누락) 트러블슈팅
  • ESLint no-unused-vars/prettier 설정 정리
  • setting 페이지 클릭수/주간리포트 알림설정 UI, 워크스페이스 알림/로딩 상태 개선

😅 미완성 작업

N/A

📢 논의 사항 및 참고 사항

  • 배포 후 반응형(모바일/태블릿/데스크탑) 및 플랫폼별 비교 랭킹 정상 노출 여부 실기기 확인 필요

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

Summary by CodeRabbit

  • 새 기능

    • 대시보드 트래픽 차트가 플랫폼별 실시간 데이터와 이상 징후 정보를 표시합니다.
    • 차트 로딩, 빈 데이터, 전체·부분 오류 상태를 구분해 안내합니다.
    • 모달 내 첫 포커스 요소와 키보드 포커스 순환을 지원합니다.
    • 랜딩 페이지에 모바일 메뉴와 애니메이션 FAQ 아코디언을 추가했습니다.
    • 워크스페이스 알림 설정(클릭 알림, 주간 리포트)을 제공합니다.
  • 개선 사항

    • 모바일 화면의 제목, KPI 그리드, 타임라인 레이아웃을 개선했습니다.
    • 타임라인 상태에 ‘진행 대기’와 ‘저성과’ 표시를 반영했습니다.
    • 랜딩 타임라인과 가이드 콘텐츠 구성을 조정했습니다.

YermIm and others added 30 commits July 21, 2026 00:37
[Feature/#305] 플랫폼 대시보드 실시간 트래픽 SSE 연동
- Vitest 환경 구축 (vitest.config.ts, @/* alias, src/__tests__ 범위 한정)
- METRIC_REGISTRY 포맷 함수 검증: 통화(₩ 올림), percent(toFixed2), delta(Math.abs)
- metricsToKpis: title/value/trend.direction/trend.value 및 경계값(delta=0, clicks=0)
- CI 파이프라인에 unit test 단계 추가 (lint → test → build)
[Bugfix/#313] 타임라인 성과 상태 UnderPerform/Pending 정리
[Test/#269] metricsToKpis · METRIC_REGISTRY 단위 테스트 추가
- lighthouserc.js 생성: /login, numberOfRuns 3, warn 임계값
  (LCP 4s / CLS 0.1 / TBT 600ms — #277에서 실측 후 확정)
- ci.yaml에 lhci autorun 스텝 추가 (build 후 실행)
- @lhci/cli 설치
"type": "module" 환경에서 LHCI가 ESM lighthouserc.js를 인식하지 못해
staticDistDir 자동 감지로 fallback → SPA 라우팅 실패 → NO_FCP 발생.
.cjs 확장자 + module.exports 형식으로 변경해 config 파일이 정상 로드되도록 수정.
axiosInstance.ts 모듈 최상위에서 PROD 환경에 BASE_URL이 없으면
throw를 던져 React 마운트 자체가 실패함. .env는 gitignore 대상이므로
CI 빌드 스텝에 VITE_API_BASE_URL: / 를 명시적으로 주입.
CI yaml에 하드코딩된 env 주입 방식 대신 Vite 컨벤션에 따라
.env.production에 VITE_API_BASE_URL=/ 를 커밋.
비밀값이 아닌 프로덕션 환경변수는 env 파일에서 관리하는 것이 관심사 분리에 맞음.
lighthouse:no-pwa preset이 color-contrast, meta-description,
robots-txt 등 error 레벨 assertion을 자동 추가 → CI exit code 1.
측정 목적에 필요한 LCP/CLS/TBT 3개 warn assertion만 유지.
[Setting/#276] Lighthouse CI 파이프라인 구축
[Refactor/#277] Lighthouse CI 임계값 warn → error 상향
[Feature/#318] 모달 focus trap 및 키보드 네비게이션 구현
Seojegyeong and others added 21 commits July 27, 2026 21:14
[Feature/#308] 플랫폼 실시간 트래픽 이상 클릭 마커/버블 UI
[Feature/#306] Setting 페이지 내 클릭수/주간리포트 알림 UI
[Refactor/#324] 통합 대시보드 - 플랫폼별 비교 API 요청 기간 수정
[Refactor/#325] 랜딩·인증·대시보드 모바일 반응형 적용
- scripts/cloudfront-functions/csp-headers.js: Report-Only 검증 완료 후 enforcing 전환
- main.yaml: 배포 시 CloudFront Function 자동 업데이트·게시 스텝 추가
[Setting/#319] CSP 보안 헤더 CloudFront Function 코드 추가 및 CI 배포 자동화
@Seojegyeong Seojegyeong self-assigned this Jul 28, 2026
@Seojegyeong Seojegyeong added the 🌏 Deploy 배포 관련 label Jul 28, 2026
@Seojegyeong
Seojegyeong requested review from YermIm and jjjsun July 28, 2026 07:15
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jjjsun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a2281af7-28f9-4313-bb99-d99aa6446f3e

📥 Commits

Reviewing files that changed from the base of the PR and between ffd9333 and 3eaf490.

📒 Files selected for processing (2)
  • src/pages/setting/Setting.tsx
  • src/types/setting/notification.ts
📝 Walkthrough

Walkthrough

대시보드 실시간 스트림과 이상 징후 표시, 모바일 랜딩 UI, 알림 설정, 타임라인 상태 모델, 모달 포커스 관리, 반응형 스타일 및 KPI 테스트가 업데이트되었습니다.

Changes

실시간 트래픽 대시보드

Layer / File(s) Summary
스트림 계약과 데이터 연결
src/hooks/dashboard/useClickStream.ts, src/types/dashboard/overview.ts, src/components/dashboard/platform/..., src/components/dashboard/charts/TrafficChart.tsx
useClickStreammodeproviderType 옵션을 받고 플랫폼별 데이터·이상 징후 정보를 차트에 전달합니다. 기존 플랫폼 목데이터는 제거되었습니다.
차트 상태와 이상 징후 표시
src/components/dashboard/platform/..., src/components/dashboard/charts/useAnomalyMarkerPos.ts
로딩·실패·빈 데이터 UI, 전체 시리즈 기준 X축, 이상 징후 마커·핑·버블 및 포커스 동작이 추가되었습니다.

반응형 및 랜딩 UI

Layer / File(s) Summary
반응형 타이포그래피와 그리드
src/styles/utilities.css, src/components/auth/..., src/pages/auth/Login.tsx, src/components/landing/LandingHero.tsx, src/components/landing/LandingSectionHeader.tsx, src/pages/dashboard/overview/sections/OverviewKpiSection.tsx
반응형 폰트 클래스와 모바일 1열 그리드가 추가되고 인증·랜딩 제목 스타일에 적용되었습니다.
모바일 랜딩 내비게이션과 콘텐츠
src/components/landing/LandingHeader.tsx, src/components/landing/LandingFAQ.tsx, src/components/landing/LandingGuide.tsx, src/components/landing/GuideTimeline.tsx, src/constants/landing/timeline.ts
모바일 메뉴·스크롤 잠금·Escape 종료, FAQ 아코디언, 가이드 레이아웃, 타임라인 데이터 및 모바일 라벨 표시가 변경되었습니다.

알림 설정

Layer / File(s) Summary
채널·워크스페이스 알림 계약과 화면
src/types/setting/notification.ts, src/components/setting/NotificationSection.tsx
알림 설정이 채널과 워크스페이스 섹션으로 분리되고 워크스페이스 선택 전 토글 비활성화 및 안내 표시가 추가되었습니다.
설정 상태와 저장 처리
src/pages/setting/Setting.tsx
채널·워크스페이스 draft/saved 상태, 변경 감지, 워크스페이스 조회, 저장 및 선택 변경 초기화가 연결되었습니다.

타임라인 상태 표시

Layer / File(s) Summary
성과 상태 타입과 스타일
src/types/timeline/*, src/constants/timeline/statusStyle.ts, src/types/timeline/timeline.mock.ts
AT_RISKUNDERPERFORM으로 변경되고 UI 전용 PENDING 상태, 기본 정규화 및 스타일이 추가되었습니다.
범례 레이아웃
src/components/timeline/TimelineStatusLegend.tsx, src/pages/dashboard/timeline/Timeline.tsx
상태 범례가 가로 스크롤 방식으로 배치되고 타임라인 툴바 간격과 flex 동작이 조정되었습니다.

접근성 및 검증

Layer / File(s) Summary
모달 포커스 트랩
src/components/common/modal/Modal.tsx
모달 오픈 시 첫 포커스 가능 요소를 선택하고 Tab·Shift+Tab 포커스를 모달 내부에서 순환합니다.
KPI 테스트와 분석 기간
src/utils/dashboard/__tests__/*, src/constants/dashboard/overviewMetricsRange.ts
KPI 라벨·포맷·추세·경계값과 바인딩 순서를 검증하고 분석 기간을 갱신했습니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: 🎨 Html&css, ✨ Feature, ✅ Test, 🐞 BugFix

Suggested reviewers: jjjsun, yermim

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 배포 반영이라는 제목이 실제 변경 범위(개발→메인 배포)와 일치하고, 짧고 명확합니다.
Description check ✅ Passed 필수 섹션(이슈, 변경사항, 작업 내용, 미완성 작업, 논의 사항)을 모두 포함해 템플릿을 대부분 충족합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

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.

[Feature/#328] 알림 설정 API Request/Response 타입 정의

@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: 16

🧹 Nitpick comments (9)
src/components/dashboard/platform/AllPlatformTrafficChart.tsx (2)

182-186: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

부분 실패 안내 문구에 aria-live 적용을 고려해주세요.

hasPartialError가 true가 될 때 나타나는 안내 텍스트가 일반 <p>라서, 스크린리더 사용자는 데이터 로딩이 끝나고 나서야(또는 우연히 포커스가 이동해야) 이 상태 변화를 인지하게 됩니다. aria-live="polite"를 추가하면 이 전환을 즉시 안내할 수 있습니다. src/** 리뷰 기준에 접근성(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/components/dashboard/platform/AllPlatformTrafficChart.tsx` around lines
182 - 186, Update the hasPartialError status message in AllPlatformTrafficChart
to include aria-live="polite" so screen readers announce its appearance without
interrupting the user; preserve the existing text and rendering condition.

Source: Path instructions


25-36: 🚀 Performance & Scalability | 🔵 Trivial

참고: 동시 SSE 연결 수 증가.

이 컴포넌트 하나만으로도 GOOGLE/NAVER/META 3개의 개별 EventSource 연결이 동시에 열립니다. 같은 대시보드 페이지에 TrafficChart 등 다른 스트림 컴포넌트가 함께 마운트된다면 커넥션 수가 더 늘어나는데, 백엔드/프록시가 HTTP/1.1이라면 브라우저의 호스트당 동시 연결 제한에 걸릴 수 있습니다. HTTP/2 멀티플렉싱을 쓰고 있다면 문제 없으니, 인프라 구성만 한 번 확인해보시면 좋겠습니다.

🤖 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/dashboard/platform/AllPlatformTrafficChart.tsx` around lines
25 - 36, Verify the dashboard’s backend and proxy support HTTP/2 multiplexing
for the three concurrent EventSource connections created by useClickStream in
AllPlatformTrafficChart, including any co-mounted stream components such as
TrafficChart. If HTTP/2 is not guaranteed, consolidate or otherwise limit these
streams to avoid exceeding the browser’s per-host HTTP/1.1 connection limit.
src/components/dashboard/platform/PlatformTrafficChart.tsx (1)

113-147: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

이상 징후 매칭 로직이 TrafficChart.tsx와 중복됩니다.

suspectDetail.timestamp를 분 단위로 변환해 매칭하고, 실패 시 최댓값 지점으로 fallback하는 이 30여 줄 로직이 TrafficChart.tsx의 이상 징후 계산부와 사실상 동일합니다. 공통 유틸 함수(예: findAnomalyPoint(seriesData, suspectDetail))로 추출하면 두 파일 모두에서 재사용할 수 있고, 향후 로직 변경 시 한 곳만 고치면 됩니다.

🤖 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/dashboard/platform/PlatformTrafficChart.tsx` around lines 113
- 147, Extract the duplicated anomaly-point selection logic from the useMemo
block and TrafficChart.tsx into a shared utility such as
findAnomalyPoint(seriesData, suspectDetail). Preserve minute-based timestamp
matching and the maximum-y fallback, then update both PlatformTrafficChart and
TrafficChart to reuse the utility and retain their existing empty-data behavior.
src/constants/landing/timeline.ts (1)

33-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

colEnd: 4.8의 의도를 주석으로 남겨주세요.

다른 카드는 정수 컬럼 경계를 쓰는데 여기만 소수라, 폭 미세 조정 의도인지 오타인지 구분이 안 됩니다. GuideTimeline에서 (colEnd - colStart) * colWidth로 계산되므로 렌더 자체는 안전합니다.

🤖 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/constants/landing/timeline.ts` around lines 33 - 43, In the timeline card
configuration containing colStart 1 and colEnd 4.8, add a concise comment
documenting that the fractional colEnd is an intentional width fine-tuning
choice for GuideTimeline rendering, not a typo. Leave the existing values and
behavior unchanged.
src/components/landing/LandingGuide.tsx (1)

121-129: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

반응형 타이포 표현 방식이 인증 화면과 갈립니다.

같은 PR의 인증/랜딩 제목들은 font-heading2-rsp 같은 유틸로 반응형 크기를 캡슐화했는데, 여기서는 font-heading2 md:font-heading1 조합을 씁니다. 동작은 문제없지만 이후 타이포 스케일 조정 시 두 군데를 따로 관리해야 합니다. 여유가 될 때 utilities.css-rsp 유틸로 통일하는 걸 권장합니다.

🤖 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/landing/LandingGuide.tsx` around lines 121 - 129, Update the
responsive typography in LandingGuide’s page number span to use the existing
font-heading2-rsp utility from utilities.css instead of the separate
font-heading2 and md:font-heading1 classes, matching the responsive heading
convention used by the authentication and landing screens.
src/components/landing/GuideTimeline.tsx (1)

76-76: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

92번 줄은 colWidth로 통일됐지만 헤더 날짜 컬럼(76번)은 w-13.75로 하드코딩이 남아 있습니다.

현재는 13.75 * 4px = 55px로 우연히 일치하지만, colWidth를 바꾸면 헤더와 그리드/카드가 어긋납니다. 헤더도 인라인 style로 colWidth를 참조하도록 맞춰 두는 게 안전합니다.

♻️ 제안 수정
-                className="flex w-13.75 justify-center font-caption text-text-placeholder"
+                className="flex shrink-0 justify-center font-caption text-text-placeholder"
+                style={{ width: `${colWidth}px` }}

Also applies to: 92-92

🤖 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/landing/GuideTimeline.tsx` at line 76, Update the header date
column in GuideTimeline so its width uses the existing colWidth value via inline
style instead of the hard-coded w-13.75 class. Keep the header width aligned
with the grid/card column width wherever colWidth is applied, including the
corresponding column reference around the reported second location.
src/components/landing/LandingHeader.tsx (1)

220-296: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

모바일 메뉴에 포커스 관리가 없습니다.

이번 PR에서 모달에는 focus trap과 초기 포커스를 넣었는데, 이 모바일 내비게이션 패널은 열려도 포커스가 이동하지 않고 Tab이 배경 콘텐츠로 빠져나갑니다. 닫을 때 햄버거 버튼으로 포커스 복귀도 없습니다. 키보드/스크린리더 사용자 기준으로는 열린 메뉴를 인지·조작하기 어렵습니다.

Modal.tsx에 새로 만든 포커스 관리 로직을 훅으로 추출해 이 패널에도 재사용하는 방향을 권장합니다. 필요하면 훅 추출안을 만들어 드릴까요?

As per path instructions: "접근성: 시맨틱 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/components/landing/LandingHeader.tsx` around lines 220 - 296, 모바일 메뉴 패널에
모달과 동일한 키보드 접근성 동작이 없으므로, Modal.tsx의 포커스 관리 로직을 재사용 가능한 훅으로 추출하고 LandingHeader의
menuOpen 패널에 적용하세요. 메뉴가 열리면 패널 내부로 초기 포커스를 이동하고 Tab 이동을 패널 내부에 가두며, 닫힐 때 햄버거
버튼으로 포커스를 복귀시키고 열린 패널에 적절한 dialog/nav ARIA 의미를 연결하세요.

Source: Path instructions

src/components/setting/NotificationSection.tsx (1)

12-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Props 타입 네이밍을 I*Props 규칙에 맞춰주세요.

TNotificationSectionProps는 컴포넌트 props 타입인데 T 접두사를 사용하고 있어요. 이 타입은 이 파일 안에서만 쓰이므로 리네이밍 영향 범위도 작습니다.

♻️ 제안
-type TNotificationSectionProps = {
+interface INotificationSectionProps {
   email: string;
   ...
-};
+}

As per coding guidelines, "Type naming conventions: API/request-response use I* (e.g., ILoginRequest), unions/options use T*, component props use I*Props."

🤖 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/setting/NotificationSection.tsx` around lines 12 - 26, Rename
the component props type TNotificationSectionProps to INotificationSectionProps
and update every reference within NotificationSection.tsx, preserving the
existing props shape and behavior.

Source: Coding guidelines

src/pages/setting/Setting.tsx (1)

59-66: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

알림 관련 상태/이펙트/저장 로직을 커스텀 훅으로 분리하는 것을 고려해보세요.

이번 변경으로 채널/워크스페이스 알림 관련 state(59-66), 파생값 계산(79-91), 변경감지 메모(108-125), 저장·리셋 로직(194-251)이 Setting.tsx에 상당히 누적되었습니다. useNotificationSettings(selectedOrgId) 같은 커스텀 훅으로 분리하면 페이지 컴포넌트는 조합/렌더링에 집중할 수 있고, 알림 로직 자체도 독립적으로 테스트하기 쉬워집니다.

As per path instructions, "2. 구조와 책임 분리: 페이지에 비즈니스 로직이 과도하지 않은지 확인. 커스텀 훅으로의 분리 여부 검토."

🤖 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/setting/Setting.tsx` around lines 59 - 66, Extract the
notification-related state, derived values, change detection, and save/reset
logic from Setting into a useNotificationSettings(selectedOrgId) custom hook.
Have the hook expose the values and handlers required by the page, then update
Setting to focus on composing the hook and rendering the UI while preserving
existing notification 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/components/common/modal/Modal.tsx`:
- Around line 17-36: Update FOCUSABLE_SELECTORS and getFocusable so the result
matches actual tab order: broaden the selectors to include potentially focusable
controls and contenteditable elements, then use el.matches(":disabled") to
exclude controls disabled through an ancestor fieldset. Preserve the existing
visibility, aria-hidden, inert, and tabIndex filtering.

In `@src/components/dashboard/charts/TrafficChart.tsx`:
- Line 105: Update the TrafficChart useClickStream call so its mode is not
permanently hardcoded to "dummy"; remove the unused real-time branch or connect
mode to the existing runtime state/URL parameter used to select real versus
dummy data. Ensure toggleDummyClicks and platform-specific charts receive the
selected mode, and use "real" for production behavior when no dummy mode is
explicitly requested.

In `@src/components/dashboard/platform/AllPlatformTrafficChart.tsx`:
- Around line 25-36: Update the three useClickStream calls in
AllPlatformTrafficChart—googleStream, naverStream, and metaStream—to use the
real click-stream mode instead of STREAM_MODE when it resolves to "dummy", while
preserving their existing platform providerType values.

In `@src/components/dashboard/platform/PlatformTrafficChart.tsx`:
- Around line 305-315: Update the anomaly marker button in
PlatformTrafficChart’s marker-rendering block to include an explicit
focus-visible ring or equivalent visible focus indicator alongside its existing
opacity styling. Ensure keyboard focus remains visually apparent without
changing the existing focus handlers or AnomalyBubble behavior.
- Around line 246-253: Wrap the chartOptions construction in
PlatformTrafficChart with useMemo so anomaly hover/focus state changes do not
recreate the options object or trigger unnecessary chart updates. Follow the
existing TrafficChart pattern and include the dependencies required by
chartOptions.

In `@src/components/dashboard/platform/SinglePlatformView.tsx`:
- Around line 75-83: Update the useClickStream call in SinglePlatformView so its
mode uses the real-time production mode instead of the hardcoded "dummy" value.
Preserve the existing platform providerType and error/data handling so the
platform traffic view receives live SSE data after deployment.

In `@src/components/landing/LandingFAQ.tsx`:
- Around line 33-63: Update the FAQ toggle in LandingFAQ so each button uses
aria-controls pointing to a unique id assigned to its corresponding motion.div
panel, and mark ChevronDownIcon as aria-hidden. Preserve the existing toggle
behavior and animations.

In `@src/components/landing/LandingHeader.tsx`:
- Around line 81-86: Update the menu state/effect in LandingHeader so entering
the md-and-above breakpoint closes the open menu and releases its scroll lock,
while preserving locks owned by other components instead of unconditionally
clearing document.body.style.overflow on mount or cleanup. Use the existing
menuOpen state and responsive breakpoint mechanism.

In `@src/components/timeline/TimelineStatusLegend.tsx`:
- Line 26: Update the horizontal scroll container in TimelineStatusLegend to be
keyboard focusable by adding tabIndex={0}, an appropriate accessible name, and a
visible focus style while preserving its existing scrolling behavior.

In `@src/constants/dashboard/overviewMetricsRange.ts`:
- Around line 3-4: Update OVERVIEW_DAILY_METRICS_RANGE so its endDate is derived
from the current date or an authoritative server configuration instead of the
fixed 2026-07-07 value, ensuring useAiAnalysisReport() includes newly available
data in its default getAll range while preserving the intended start-date
behavior.

In `@src/hooks/dashboard/useClickStream.ts`:
- Around line 15-23: Update useClickStream so production defaults and new-client
callers use the real SSE mode instead of "dummy", and replace the hardcoded test
orgId with the currently selected organization. Remove the test TODO and ensure
the dummy path is explicitly isolated to intentional demo/test usage.
- Line 1: useClickStream의 기본 모드를 dummy에서 real로 변경하고, 전역 및 플랫폼별 차트 호출부도 실제 SSE
모드를 사용하도록 전환하세요. 테스트용 orgId 1 고정값을 제거하고 selectedOrgId를 기반으로 SSE 경로가 구성되도록 복구해 실제
조직 데이터를 사용하게 하세요.

In `@src/pages/setting/Setting.tsx`:
- Around line 247-251: Update the selectedOrgId effect and related workspace
notification state so switching workspaces does not discard values saved by
handleSave: reload each workspace’s persisted setting through the appropriate
API, or, until persistence exists, consistently show the unselected default and
add UI guidance that settings are not currently retained until saved. Ensure
returning to a workspace restores its saved value when persistence is supported.
- Around line 79-91: Update workspaceNotifiDisabled in the Setting component to
remain true while isWorkspacesLoading is true, in addition to the existing null
selectedOrgId and missing currentWorkspaceName conditions. Keep
NotificationSection disabled until the workspace list has loaded and the
selected workspace name is confirmed.
- Around line 194-213: Update the workspace notification save condition in the
surrounding save handler to also require workspaceNotifiDisabled to be false,
alongside hasWorkspaceNotifChanges and selectedOrgId != null. Apply the same
validity check when computing savedWorkspaceNotifiThisTime so invalidated
workspaces are not treated as saved or included in the success toast.

In `@src/styles/utilities.css`:
- Around line 118-124: Remove the empty base rule for .grid-mobile-1, leaving
the existing `@media` (max-width: 639px) rule and its grid-template-columns
declaration unchanged.

---

Nitpick comments:
In `@src/components/dashboard/platform/AllPlatformTrafficChart.tsx`:
- Around line 182-186: Update the hasPartialError status message in
AllPlatformTrafficChart to include aria-live="polite" so screen readers announce
its appearance without interrupting the user; preserve the existing text and
rendering condition.
- Around line 25-36: Verify the dashboard’s backend and proxy support HTTP/2
multiplexing for the three concurrent EventSource connections created by
useClickStream in AllPlatformTrafficChart, including any co-mounted stream
components such as TrafficChart. If HTTP/2 is not guaranteed, consolidate or
otherwise limit these streams to avoid exceeding the browser’s per-host HTTP/1.1
connection limit.

In `@src/components/dashboard/platform/PlatformTrafficChart.tsx`:
- Around line 113-147: Extract the duplicated anomaly-point selection logic from
the useMemo block and TrafficChart.tsx into a shared utility such as
findAnomalyPoint(seriesData, suspectDetail). Preserve minute-based timestamp
matching and the maximum-y fallback, then update both PlatformTrafficChart and
TrafficChart to reuse the utility and retain their existing empty-data behavior.

In `@src/components/landing/GuideTimeline.tsx`:
- Line 76: Update the header date column in GuideTimeline so its width uses the
existing colWidth value via inline style instead of the hard-coded w-13.75
class. Keep the header width aligned with the grid/card column width wherever
colWidth is applied, including the corresponding column reference around the
reported second location.

In `@src/components/landing/LandingGuide.tsx`:
- Around line 121-129: Update the responsive typography in LandingGuide’s page
number span to use the existing font-heading2-rsp utility from utilities.css
instead of the separate font-heading2 and md:font-heading1 classes, matching the
responsive heading convention used by the authentication and landing screens.

In `@src/components/landing/LandingHeader.tsx`:
- Around line 220-296: 모바일 메뉴 패널에 모달과 동일한 키보드 접근성 동작이 없으므로, Modal.tsx의 포커스 관리
로직을 재사용 가능한 훅으로 추출하고 LandingHeader의 menuOpen 패널에 적용하세요. 메뉴가 열리면 패널 내부로 초기 포커스를
이동하고 Tab 이동을 패널 내부에 가두며, 닫힐 때 햄버거 버튼으로 포커스를 복귀시키고 열린 패널에 적절한 dialog/nav ARIA 의미를
연결하세요.

In `@src/components/setting/NotificationSection.tsx`:
- Around line 12-26: Rename the component props type TNotificationSectionProps
to INotificationSectionProps and update every reference within
NotificationSection.tsx, preserving the existing props shape and behavior.

In `@src/constants/landing/timeline.ts`:
- Around line 33-43: In the timeline card configuration containing colStart 1
and colEnd 4.8, add a concise comment documenting that the fractional colEnd is
an intentional width fine-tuning choice for GuideTimeline rendering, not a typo.
Leave the existing values and behavior unchanged.

In `@src/pages/setting/Setting.tsx`:
- Around line 59-66: Extract the notification-related state, derived values,
change detection, and save/reset logic from Setting into a
useNotificationSettings(selectedOrgId) custom hook. Have the hook expose the
values and handlers required by the page, then update Setting to focus on
composing the hook and rendering the UI while preserving existing notification
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: a376cecc-d0ef-42aa-b6d3-520240cc963a

📥 Commits

Reviewing files that changed from the base of the PR and between 2b5a469 and ffd9333.

⛔ Files ignored due to path filters (9)
  • .env.production is excluded by none and included by none
  • .github/workflows/ci.yaml is excluded by none and included by none
  • .github/workflows/main.yaml is excluded by none and included by none
  • lighthouserc.cjs is excluded by none and included by none
  • 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
  • scripts/cloudfront-functions/csp-headers.js is excluded by none and included by none
  • tsconfig.node.json is excluded by none and included by none
  • vitest.config.ts is excluded by none and included by none
📒 Files selected for processing (39)
  • src/components/auth/common/PasswordForm.tsx
  • src/components/auth/flows/find-email/EnterPhoneStep.tsx
  • src/components/auth/flows/find-email/ShowEmailResultStep.tsx
  • src/components/auth/flows/reset-password/EmailVerificationStep.tsx
  • src/components/auth/flows/signup/EnterEmailStep.tsx
  • src/components/auth/flows/signup/ProfileSetupStep.tsx
  • src/components/common/modal/Modal.tsx
  • src/components/dashboard/charts/TrafficChart.tsx
  • src/components/dashboard/charts/useAnomalyMarkerPos.ts
  • src/components/dashboard/platform/AllPlatformTrafficChart.tsx
  • src/components/dashboard/platform/PlatformTrafficChart.tsx
  • src/components/dashboard/platform/SinglePlatformView.tsx
  • src/components/landing/GuideTimeline.tsx
  • src/components/landing/GuideWorkspace.tsx
  • src/components/landing/LandingFAQ.tsx
  • src/components/landing/LandingGuide.tsx
  • src/components/landing/LandingHeader.tsx
  • src/components/landing/LandingHero.tsx
  • src/components/landing/LandingSectionHeader.tsx
  • src/components/setting/NotificationSection.tsx
  • src/components/timeline/TimelineStatusLegend.tsx
  • src/constants/dashboard/overviewMetricsRange.ts
  • src/constants/landing/timeline.ts
  • src/constants/timeline/statusStyle.ts
  • src/hooks/dashboard/useClickStream.ts
  • src/pages/auth/Login.tsx
  • src/pages/dashboard/overview/sections/OverviewKpiSection.tsx
  • src/pages/dashboard/platform/platformDashboard.mock.ts
  • src/pages/dashboard/timeline/Timeline.tsx
  • src/pages/setting/Setting.tsx
  • src/styles/utilities.css
  • src/types/dashboard/overview.ts
  • src/types/setting/notification.ts
  • src/types/timeline/api.ts
  • src/types/timeline/summary.ts
  • src/types/timeline/timeline.mock.ts
  • src/types/timeline/ui.ts
  • src/utils/dashboard/__tests__/metricRegistry.test.ts
  • src/utils/dashboard/__tests__/metricsToKpis.test.ts
💤 Files with no reviewable changes (1)
  • src/pages/dashboard/platform/platformDashboard.mock.ts

Comment thread src/components/common/modal/Modal.tsx
Comment thread src/components/dashboard/charts/TrafficChart.tsx
Comment thread src/components/dashboard/platform/AllPlatformTrafficChart.tsx
Comment thread src/components/dashboard/platform/PlatformTrafficChart.tsx
Comment thread src/components/dashboard/platform/PlatformTrafficChart.tsx
Comment thread src/hooks/dashboard/useClickStream.ts
Comment thread src/pages/setting/Setting.tsx
Comment thread src/pages/setting/Setting.tsx
Comment thread src/pages/setting/Setting.tsx
Comment thread src/styles/utilities.css
@Seojegyeong
Seojegyeong merged commit af341d9 into main Jul 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌏 Deploy 배포 관련

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants