Skip to content

[FEAT] mock data를 활용해 임시 UI 구성 - #4

Merged
suwonthugger merged 6 commits into
mainfrom
feat/2-add-api-mock
Jul 22, 2026
Merged

[FEAT] mock data를 활용해 임시 UI 구성#4
suwonthugger merged 6 commits into
mainfrom
feat/2-add-api-mock

Conversation

@suwonthugger

@suwonthugger suwonthugger commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

👥 작업 배경 및 목적

UI는 완성됐지만 모든 화면이 정적 목데이터(lib/data.ts)를 동기 함수로 직접 읽고 있었습니다. 실제 백엔드 연동을 위해 ky + TanStack Query 클라이언트 세팅 → MSW 목킹 → 컴포넌트 연동 순서로 데이터 계층을 교체했습니다.

🛠️ 주요 변경 사항

신규 파일

파일 역할
src/lib/http.ts 공통 ky 클라이언트 (prefix: /api, tim
src/lib/queries.ts /api fetch 함수 + TanStack Query 훅 (useNewsQuery 등 5개)
src/mocks/handlers.ts /api 5개 엔드포인트 MSW 목 핸들
src/mocks/browser.ts MSW 브라우저 워커 설정
src/client.tsx 개발 모드에서 MSW 기동 후 하이드레이션( 포함)

수정 파일

파일 변경
NewsList, MobileNewsBar, AnalysisPanel, VerifyView, BriefingSheet, Header, GraphPanel lib/api.ts/lib/data.ts 직접 호출 → 쿼리 훅으로 교체
root-provider.tsx QueryClient 기본 옵션(staleTime/retry) 추가
  • 기존 lib/api.ts 동기 함수는 삭제하지 않고 placeholderData(즉시 표시) + MSW 응답 생성에 재사용 → 네트워크 없어도 화면 즉시 렌더
  • 리뷰 포인트: GraphPanel.tsxbuildFocusScene/buildAll인자로 받도록 시그니처 변경됨. 좌표 계산(lib/layout.ts`)은의도적으로 그대로 둠(정적 데이터 소스 공유라 지금은 문제 없음)

🧪 테스트 결과

  • 실제 브라우저 구동 확인: 뉴스 선택→그래프 애니메이션 / 전체리핑 / 예측 검증 화면 정상 동작
  • /api/* 5개 요청 전부 200 + MSW 응답(fromServiceWorker: true), 콘솔 에러 없음
  • pnpm lint / pnpm check / pnpm build 통과

📡 API 명세 (백엔드 공유용)

Base URL /api · 인증 없음

Method Path Request Response
GET /news query: sector?, limit? { items: NewsListItem[] }
GET /news/{id}/analysis path: id NewsAnalysis (없으면 404)
GET /graph - { nodes: OntologyNode[], edges: OntologyEdge[] }
POST /briefing body: { tickers: string[] } BriefingResult
GET /verify query: days? (기본 30) { daily: VerifyDaily[], news: VerifyEntry[] }
응답 예시 (JSON)
// GET /news
{ "items": [{ "id": "n1", "title": "...", "press": "연합뉴스", "publishedAt": "2026-07-18T09:12:00+09:00", "sector": "반도체" }] }

// GET /news/n1/analysis
{
  "newsId": "n1",
  "article": { "summary": ["요약1", "요약2", "요약3"], "origiss": "연합뉴스", "publishedAt": "..." },
  "main": { "nodeId": "sk", "name": "SK하이닉스", "ticker": "000660", "direction": "UP", "reason": "..." },
  "related": [{ "nodeId": "hanmi", "name": "한미반도체", "tic": "UP", "relation": "장비 공급", "chain": ["sk", "hanmi"] }],
  "rationale": { "event": "...", "propagation": "...", "precedent": "..." }
}

// GET /graph
{                                                                                                                                                "nodes": [{ "id": "sk", "name": "SK하이닉스", "kind": "COMP"sector": "반도체", "marketCap": 1200000 }],
  "edges": [{ "id": "e0", "source": "sk", "target": "hanmi", "relation": "장비 공급", "polarity": 1 }]                                         }
                                                                                                                                               // POST /briefing  (req: { "tickers": ["005930","042700"] })
{                                                                                                                                                "totalNews": 20,
  "matched": [{ "ticker": "042700", "name": "한미반도체", "direction": "UP", "relation": "장비 공급", "chain": ["sk","hanmi"], "newsId": "n1", "newsTitle": "..." }],
  "unmatched": [{ "ticker": "005930", "name": "삼성전자" }]
}

// GET /verify
{
  "daily": [{ "date": "2026-07-17", "hitRate": 0.71 }],
  "news": [{ "newsId": "v1", "date": "07-17", "sector": "반도체", "title": "...", "items": [{ "name": "한미반도체", "predicted": "UP",
"actualReturn": 3.42, "hit": true, "pathLabel": "장비 공급 ·
}
direction/predicted: "UP" | "DOWN" · polarity: 1(동조) | -1( PRODUCT" | "THEME" | "MATERIAL" · 타입 전체는src/types/index.ts 참고
</details>

Summary by CodeRabbit

Summary

  • New Features
    • 뉴스/뉴스 분석/그래프/검증 화면을 쿼리 기반 로딩으로 전환
    • 뉴스와 검증 목록에 커서 기반 무한 스크롤 적용
    • 브리핑 “조회” 버튼에 로딩 상태 반영 및 중복 요청 방지
    • 목록 하단 자동 로딩을 위한 공용 무한 스크롤 트리거 추가
  • Bug Fixes
    • 동일 쿼리 데이터 기준으로 화면 표시가 더 일관되게 동작
  • Refactor
    • API 호출·캐싱·새로고침 동작을 공통화해 로딩 흐름 정리
    • 헤더의 노드/관계 요약이 최신 그래프 결과로 갱신
  • Documentation
    • 커서 페이징 및 무한 스크롤 규칙 관련 문서 구체화

suwonthugger and others added 3 commits July 21, 2026 22:30
/api 명세(GET news/graph/verify, GET news/{id}/analysis, POST briefing)에
맞춘 ky 인스턴스와 쿼리 훅을 추가한다. placeholderData는 lib/api.ts의 기존
동기 함수를 재사용해 실 백엔드가 없어도 즉시 데이터가 보이게 한다. 아직
어떤 컴포넌트도 이 훅을 쓰지 않으므로 기존 동작에는 영향이 없다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
lib/api.ts의 동기 함수를 그대로 응답 생성에 재사용하는 MSW 핸들러로
GET/POST /api/* 를 가로챈다. 개발 모드에서는 커스텀 client.tsx 엔트리가
하이드레이션 전에 워커 시작을 기다려 첫 쿼리부터 목 응답을 받는다.
프로덕션 빌드에서는 import.meta.env.DEV 분기로 관련 코드가 빠진다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
NewsList/MobileNewsBar/AnalysisPanel/VerifyView/BriefingSheet/Header/
GraphPanel의 lib/api.ts·lib/data.ts 직접 호출을 lib/queries.ts 훅으로
교체한다. GraphPanel은 buildFocusScene/buildAllScene이 훅에서 받은
analysis/graph 데이터를 인자로 받도록 시그니처를 바꿨고, 결정론적 좌표를
계산하는 lib/layout.ts는 기존 그대로 lib/data.ts를 소스로 유지한다(MSW도
같은 소스를 쓰므로 지금은 데이터 불일치가 없다).

public/mockServiceWorker.js가 eslint 대상에서 빠지도록 ignore 추가.

Chromium으로 실제 흐름을 구동해 확인: 뉴스 선택→그래프 애니메이션, 전체
관계망 전환, 관심종목 브리핑 뮤테이션, 예측 검증 화면이 모두 정상 동작하고
5개 /api 요청이 전부 MSW(fromServiceWorker)로 200 응답, 콘솔 에러 없음.
프로덕션 빌드 결과물에는 MSW 코드가 포함되지 않음을 확인.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@suwonthugger suwonthugger self-assigned this Jul 21, 2026
@suwonthugger suwonthugger linked an issue Jul 21, 2026 that may be closed by this pull request
3 tasks
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

ky와 TanStack Query 데이터 계층, 커서 기반 뉴스·검증 조회, MSW 브라우저 모킹, 개발 환경 워커 초기화가 추가되었습니다. 화면 컴포넌트는 쿼리와 뮤테이션을 사용해 뉴스, 분석, 그래프, 검증 및 브리핑 데이터를 처리합니다.

Changes

쿼리 및 MSW 통합

Layer / File(s) Summary
커서 기반 API 계약 및 데이터
src/types/index.ts, src/lib/api.ts, src/lib/data.ts, src/routes/index.tsx, docs/..., CLAUDE.md
뉴스와 검증 응답을 nextCursor를 포함하는 페이지 형태로 변경하고 분석 응답에 제목과 섹터를 추가합니다. 관련 샘플 데이터와 API 문서를 갱신합니다.
HTTP 및 쿼리 데이터 계층
src/lib/http.ts, src/lib/queries.ts, src/integrations/tanstack-query/root-provider.tsx
공유 HTTP 클라이언트, 쿼리 키, 조회·뮤테이션 훅과 QueryClient 기본 설정을 추가합니다.
MSW 브라우저 런타임 및 핸들러
package.json, eslint.config.js, src/mocks/*, public/mockServiceWorker.js, src/client.tsx
MSW를 설정하고 API 모킹 핸들러와 서비스 워커를 추가하며, 개발 환경에서 워커 시작 후 애플리케이션을 하이드레이션합니다.
쿼리 기반 화면 컴포넌트
src/components/Header.tsx, src/components/analysis/*, src/components/briefing/*, src/components/graph/*, src/components/news/*, src/components/verify/*, src/lib/useInfiniteScrollTrigger.ts
화면 데이터 조회를 쿼리 훅과 뮤테이션으로 전환하고 뉴스·검증 목록에 커서 기반 무한 스크롤을 연결합니다.

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

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant ClientEntrypoint
  participant TanStackQuery
  participant MSWWorker
  participant MockHandlers
  Browser->>ClientEntrypoint: 개발 환경 초기화
  ClientEntrypoint->>MSWWorker: 워커 시작
  Browser->>TanStackQuery: 뉴스·분석·그래프 조회
  TanStackQuery->>MSWWorker: API 요청
  MSWWorker->>MockHandlers: 엔드포인트 핸들러 실행
  MockHandlers-->>MSWWorker: JSON 응답 반환
  MSWWorker-->>TanStackQuery: 응답 전달
  TanStackQuery-->>Browser: 쿼리 데이터 렌더링
Loading

Possibly related PRs

Suggested labels: feature

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.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 핵심 변경인 mock data 기반 임시 UI 구성과 잘 맞는 간결한 제목입니다.
Description check ✅ Passed 배경, 주요 변경 사항, 테스트 결과가 포함되어 템플릿을 대부분 충족합니다.
Linked Issues check ✅ Passed MSW, ky, TanStack Query 세팅과 주요 화면 연동이 이슈 #2의 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 목적과 무관한 뚜렷한 코드 변경은 보이지 않으며, 추가된 작업도 mock UI 구현을 지원합니다.
✨ 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 feat/2-add-api-mock

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Comment @coderabbitai help to get the list of available commands.

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

🧹 Nitpick comments (2)
src/lib/http.ts (1)

7-11: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Retry compounds with TanStack Query's own retry.

retry: { limit: 1 } here plus the QueryClient's retry: 1 default (root-provider.tsx) means a failing GET can be attempted up to ~4 times (ky retries once per query attempt, and the query itself is retried once). Consider owning retry at a single layer — e.g. set retry: 0 here and let TanStack Query manage retries for queries, since it's more aware of query-vs-mutation semantics.

🤖 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/http.ts` around lines 7 - 11, Update the `http` ky client
configuration to disable ky-level retries by setting its `retry.limit` to zero,
leaving retry ownership to TanStack Query’s `QueryClient` configuration.
Preserve the existing base URL and timeout settings.
src/client.tsx (1)

12-27: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add error handling around enableMocking().

No .catch() on the promise chain — if worker.start() rejects, hydration silently never happens, leaving a blank dev app with only an unhandled-rejection trace.

🛡️ Proposed fix
-enableMocking().then(() => {
-  startTransition(() => {
-    hydrateRoot(
-      document,
-      <StrictMode>
-        <StartClient />
-      </StrictMode>,
-    )
-  })
-})
+enableMocking()
+  .catch((error) => {
+    console.error('[msw] failed to start worker, hydrating without mocks', error)
+  })
+  .finally(() => {
+    startTransition(() => {
+      hydrateRoot(
+        document,
+        <StrictMode>
+          <StartClient />
+        </StrictMode>,
+      )
+    })
+  })
🤖 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/client.tsx` around lines 12 - 27, Add rejection handling to the
enableMocking() promise chain so failures from worker.start() are surfaced
explicitly and do not silently prevent hydration. Preserve the existing
successful path that calls startTransition and hydrateRoot, and report the
caught error through the project’s established error-handling mechanism.
🤖 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/briefing/BriefingSheet.tsx`:
- Around line 56-66: Update the briefing request flow around
briefingMutation.mutate and its onSuccess handler to prevent stale responses
from repopulating the sheet: disable clearAll, ticker edit/removal, and
suggestion controls while the mutation is pending, or capture the submitted
ticker snapshot and ignore onSuccess when current tickers differ. Preserve
result updates only for responses matching the current ticker state.
- Around line 56-66: Add failure handling to the briefingMutation.mutate call in
run(), alongside the existing onSuccess callback, so rejected postBriefing
requests surface error feedback and do not leave stale results unexplained. Use
the mutation’s error state or error value through the existing UI
state/rendering path, referencing briefingMutation and the result display
without changing successful behavior.

In `@src/components/verify/VerifyView.tsx`:
- Around line 98-100: Update VerifyView’s useVerifyQuery handling to consume
isError (and isPlaceholderData when distinguishing placeholder results) instead
of treating failed or placeholder requests as real verification metrics. Render
an explicit error state for query failures, while preserving the existing
daily/news metric flow for successful fetched data.

In `@src/lib/http.ts`:
- Line 8: Update the prefix configuration in the HTTP client to fall back to
"/api" when VITE_API_BASE_URL is undefined, null, or an empty string; use a
presence check that treats empty-string values as missing while preserving
non-empty configured URLs.

---

Nitpick comments:
In `@src/client.tsx`:
- Around line 12-27: Add rejection handling to the enableMocking() promise chain
so failures from worker.start() are surfaced explicitly and do not silently
prevent hydration. Preserve the existing successful path that calls
startTransition and hydrateRoot, and report the caught error through the
project’s established error-handling mechanism.

In `@src/lib/http.ts`:
- Around line 7-11: Update the `http` ky client configuration to disable
ky-level retries by setting its `retry.limit` to zero, leaving retry ownership
to TanStack Query’s `QueryClient` configuration. Preserve the existing base URL
and timeout settings.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 70e5cd88-f080-43c9-b721-a1eab1540eaf

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc7304 and ff5d811.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • eslint.config.js
  • package.json
  • public/mockServiceWorker.js
  • src/client.tsx
  • src/components/Header.tsx
  • src/components/analysis/AnalysisPanel.tsx
  • src/components/briefing/BriefingSheet.tsx
  • src/components/graph/GraphPanel.tsx
  • src/components/news/MobileNewsBar.tsx
  • src/components/news/NewsList.tsx
  • src/components/verify/VerifyView.tsx
  • src/integrations/tanstack-query/root-provider.tsx
  • src/lib/http.ts
  • src/lib/queries.ts
  • src/mocks/browser.ts
  • src/mocks/handlers.ts

Comment thread src/components/briefing/BriefingSheet.tsx
Comment thread src/components/verify/VerifyView.tsx Outdated
Comment thread src/lib/http.ts
@suwonthugger

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/graph/GraphPanel.tsx (1)

90-94: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

조회한 그래프와 정적 그래프 인덱스를 혼용하지 마세요.

ids와 엣지는 graph에서 만들지만 focusBuild, nodeBuild, FULL_LAYOUT, graphIndex, tierOf, 엣지 polarity는 정적 ontology를 계속 사용합니다. API 응답에 정적 데이터에 없는 노드가 포함되면 Line 194와 Line 315의 ! 조회에서 런타임 오류가 발생할 수 있고, 파급 엣지 ID·관계 방향·색상도 실제 응답과 어긋날 수 있습니다. 빌더와 렌더링 메타데이터를 동일한 graph payload에서 파생하도록 통합하세요.

Also applies to: 157-162, 172-179, 197-203, 212-219

🤖 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/graph/GraphPanel.tsx` around lines 90 - 94, Update
buildFocusScene and the related graph-building/rendering paths so focusBuild,
nodeBuild, layout metadata, graphIndex, tierOf, and edge polarity all derive
from the same API graph payload used to build ids and edges, rather than static
ontology data. Remove assumptions that response nodes exist in static indexes,
including non-null assertions, and ensure propagation edge IDs, relationship
directions, and colors reflect the returned graph consistently.
🤖 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/client.tsx`:
- Around line 18-27: Update the enableMocking() promise flow in the client
bootstrap so import() or worker.start() failures are logged and do not prevent
the existing startTransition/hydrateRoot path from running. Ensure hydration
proceeds both when mocking succeeds and when it rejects, without changing the
existing <StartClient /> rendering setup.

---

Outside diff comments:
In `@src/components/graph/GraphPanel.tsx`:
- Around line 90-94: Update buildFocusScene and the related
graph-building/rendering paths so focusBuild, nodeBuild, layout metadata,
graphIndex, tierOf, and edge polarity all derive from the same API graph payload
used to build ids and edges, rather than static ontology data. Remove
assumptions that response nodes exist in static indexes, including non-null
assertions, and ensure propagation edge IDs, relationship directions, and colors
reflect the returned graph consistently.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 823244e0-c142-400c-b0d5-7239154100f6

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc7304 and ff5d811.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • eslint.config.js
  • package.json
  • public/mockServiceWorker.js
  • src/client.tsx
  • src/components/Header.tsx
  • src/components/analysis/AnalysisPanel.tsx
  • src/components/briefing/BriefingSheet.tsx
  • src/components/graph/GraphPanel.tsx
  • src/components/news/MobileNewsBar.tsx
  • src/components/news/NewsList.tsx
  • src/components/verify/VerifyView.tsx
  • src/integrations/tanstack-query/root-provider.tsx
  • src/lib/http.ts
  • src/lib/queries.ts
  • src/mocks/browser.ts
  • src/mocks/handlers.ts

Comment thread src/client.tsx
Comment on lines +18 to +27
enableMocking().then(() => {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<StartClient />
</StrictMode>,
)
})
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

printf '\n== src/client.tsx ==\n'
cat -n src/client.tsx

printf '\n== search enableMocking ==\n'
rg -n "enableMocking|worker.start|msw|hydrateRoot" src --hidden

printf '\n== candidate files ==\n'
git ls-files | rg 'src/.*(mock|msw|client|worker).*'

Repository: koscom-team01/koslink-fe

Length of output: 1659


🏁 Script executed:

set -euo pipefail

printf '\n== src/mocks/browser.ts ==\n'
cat -n src/mocks/browser.ts

printf '\n== package.json (MSW deps) ==\n'
cat -n package.json | sed -n '1,220p'

printf '\n== search service worker config ==\n'
rg -n "mockServiceWorker|serviceWorker|setupWorker|worker.start|onUnhandledRequest" src package.json --hidden

Repository: koscom-team01/koslink-fe

Length of output: 3032


MSW 초기화 실패 시에도 하이드레이션을 계속 진행하세요.

src/client.tsx:18에서 enableMocking()import() 또는 worker.start()에서 reject되면 .then()이 실행되지 않아 hydrateRoot()가 호출되지 않습니다. MSW가 선택적 개발 목킹이라면 오류를 로그로 남긴 뒤 하이드레이션은 이어가야 합니다.

🔧 Proposed fix
-enableMocking().then(() => {
+void enableMocking()
+  .catch((error) => {
+    console.error('MSW worker 초기화에 실패했습니다.', error)
+  })
+  .then(() => {
   startTransition(() => {
     hydrateRoot(
       document,
       <StrictMode>
         <StartClient />
       </StrictMode>,
     )
   })
-})
+  })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
enableMocking().then(() => {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<StartClient />
</StrictMode>,
)
})
})
void enableMocking()
.catch((error) => {
console.error('MSW worker 초기화에 실패했습니다.', error)
})
.then(() => {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<StartClient />
</StrictMode>,
)
})
})
🤖 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/client.tsx` around lines 18 - 27, Update the enableMocking() promise flow
in the client bootstrap so import() or worker.start() failures are logged and do
not prevent the existing startTransition/hydrateRoot path from running. Ensure
hydration proceeds both when mocking succeeds and when it rejects, without
changing the existing <StartClient /> rendering setup.

@suwonthugger

suwonthugger commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

api 재검토 예정

  • 페이징 api check (검증 목록 어떻게 할지?)

suwonthugger and others added 2 commits July 22, 2026 00:41
GET /api/news가 전체 목록을 한 번에 반환하던 것을 cursor/nextCursor
기반 페이징으로 바꾼다. useNewsQuery를 useInfiniteQuery로 전환하고,
NewsList는 IntersectionObserver sentinel로 하단 도달 시 다음 페이지를
자동 요청한다. MobileNewsBar의 이전/다음 탐색도 로드된 페이지 끝에서
다음 페이지를 이어 받도록 처리.

뉴스 목록이 페이지네이션되면서 AnalysisPanel이 선택된 뉴스를 찾으려고
전체 목록을 별도 조회하던 방식은 깨지므로, NewsAnalysis 응답에
title/sector를 추가해 분석 패널이 목록 없이도 동작하도록 함께 고쳤다.

lib/api.ts의 getNews는 이제 { sector?, cursor?, limit? } → { items,
nextCursor } 시그니처. MSW 핸들러와 docs/KOSLINK-FRONTEND.md §5.1/5.2도
동일하게 갱신. cursor는 클라이언트가 해석하지 않는 opaque 값으로 문서화.

Chromium으로 확인: limit=3으로 커서를 이어 요청하면 6건이 정확히
2페이지(n1-3 → n4-6, 두 번째 페이지 nextCursor=null)로 나뉨, analysis
응답에 title/sector 포함, 기존 화면 동작 회귀 없음.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
기존 6건은 기본 limit(20)보다 적어 무한 스크롤이 실제로는 한 번도
트리거되지 않았다. 기존 온톨로지 노드·엣지만 재사용하는 뉴스 19건을
추가해 총 25건으로 늘려, 첫 페이지 20건 + 다음 페이지 5건으로 나뉘도록
했다.

Chromium으로 확인: GET /api/news 기본 호출이 20건+nextCursor를 반환하고
다음 페이지가 나머지 5건+nextCursor:null을 반환. 뉴스 패널을 끝까지
스크롤하면 IntersectionObserver sentinel이 실제로 다음 페이지를 불러와
n25까지 렌더링됨을 확인. 신규 뉴스의 /analysis 응답도 정상(200).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@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.

🧹 Nitpick comments (1)
docs/KOSLINK-FRONTEND.md (1)

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

펜스드 코드 블록에 언어 지정 누락 (MD040).

정적 분석 도구가 131행 코드 블록에 언어가 지정되지 않았음을 지적했습니다. http 등 언어 태그를 붙이면 해결됩니다.

📝 제안
-```
+```http
 GET /api/news?limit=20&sector=반도체&cursor=n3
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/KOSLINK-FRONTEND.md around lines 131 - 133, 문서의 GET 요청 예시 코드 블록에 http
언어 태그를 추가하여 Markdown 언어 지정 누락을 해결하세요.


</details>

<!-- cr-comment:v1:04359e8b0b26e7d250289870 -->

_Source: Linters/SAST tools_

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @docs/KOSLINK-FRONTEND.md:

  • Around line 131-133: 문서의 GET 요청 예시 코드 블록에 http 언어 태그를 추가하여 Markdown 언어 지정
    누락을 해결하세요.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: Organization UI

**Review profile**: CHILL

**Plan**: Pro Plus

**Run ID**: `bbaed94d-2aa9-41b9-a1e9-618aa2fb596a`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between ff5d8114c553c080dee0dcb783e083237ff946d7 and d0a8d7d85198a118aabcc964a2e689b474191e85.

</details>

<details>
<summary>📒 Files selected for processing (10)</summary>

* `docs/KOSLINK-FRONTEND.md`
* `src/components/analysis/AnalysisPanel.tsx`
* `src/components/news/MobileNewsBar.tsx`
* `src/components/news/NewsList.tsx`
* `src/lib/api.ts`
* `src/lib/data.ts`
* `src/lib/queries.ts`
* `src/mocks/handlers.ts`
* `src/routes/index.tsx`
* `src/types/index.ts`

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* src/mocks/handlers.ts
* src/lib/queries.ts

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

GET /api/verify의 news 배열이 전체를 한 번에 반환하던 것을 뉴스 목록과
동일한 cursor/nextCursor 방식으로 바꾼다. daily(적중률 추이)는 섹터·
페이지와 무관한 전체 집계라 페이징 대상에서 제외.

코드 중복 제거:
- lib/api.ts: getNews/getVerify가 공유하는 paginate()/bySector() 헬퍼로
  커서 탐색·슬라이싱 로직을 한 곳에 모음
- lib/queries.ts: news/verify가 공유하는 pageSearchParams() 헬퍼
- mocks/handlers.ts: sector/cursor/limit 쿼리스트링 파싱을 readPageParams()로 통합
- src/lib/useInfiniteScrollTrigger.ts(신규): IntersectionObserver 기반
  무한 스크롤 트리거를 훅으로 추출해 NewsList/VerifyList가 공유

버그 수정: 훅이 IntersectionObserver의 root를 지정하지 않아 브라우저
뷰포트 기준으로 교차를 판정하고 있었다. 뉴스 패널은 우연히 화면 상단에
붙어 있어 동작했지만, 검증 패널처럼 목록이 페이지 아래쪽에 있으면 내부
스크롤을 끝까지 내려도 sentinel의 실제 좌표가 뷰포트 밖이라 전혀
트리거되지 않았다. 실제 스크롤 컨테이너를 root로 명시하도록 고쳤고, 이
과정에서 검증 화면도 같은 버그를 안고 있었음을 확인했다.

문서 동기화: CLAUDE.md·docs/KOSLINK-FRONTEND.md·design-constraints 스킬의
"검증 화면 페이지네이션 없음" 문구를 "페이지 번호 UI 없음(둘 다 커서 기반
무한 스크롤)"로 갱신.

Chromium으로 확인: GET /api/verify 기본 호출이 10건+nextCursor 반환,
다음 페이지가 나머지 4건+nextCursor:null 반환. 검증 목록을 끝까지
스크롤하면 실제로 14건까지 로드됨(수정 전엔 10건에서 멈춤). 뉴스 목록
무한 스크롤도 회귀 없음 재확인.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

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

🤖 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 `@docs/KOSLINK-FRONTEND.md`:
- Line 250: Update the HTTP request code fence at the affected documentation
example to declare the http language, changing the opening fence from an
unspecified block to an http-labeled fence while preserving the request content.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a3172e37-981f-4f4c-91b2-139a35a3d1e2

📥 Commits

Reviewing files that changed from the base of the PR and between d0a8d7d and 619156c.

📒 Files selected for processing (11)
  • .claude/skills/koslink-design-constraints/SKILL.md
  • CLAUDE.md
  • docs/KOSLINK-FRONTEND.md
  • src/components/news/NewsList.tsx
  • src/components/verify/VerifyList.tsx
  • src/components/verify/VerifyView.tsx
  • src/lib/api.ts
  • src/lib/queries.ts
  • src/lib/useInfiniteScrollTrigger.ts
  • src/mocks/handlers.ts
  • src/types/index.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/news/NewsList.tsx
  • src/components/verify/VerifyView.tsx
  • src/mocks/handlers.ts

Comment thread docs/KOSLINK-FRONTEND.md
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.

[FEAT] mock data를 활용해 임시 UI 구성

1 participant