[FEAT] mock data를 활용해 임시 UI 구성 - #4
Conversation
/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>
📝 WalkthroughWalkthroughky와 TanStack Query 데이터 계층, 커서 기반 뉴스·검증 조회, MSW 브라우저 모킹, 개발 환경 워커 초기화가 추가되었습니다. 화면 컴포넌트는 쿼리와 뮤테이션을 사용해 뉴스, 분석, 그래프, 검증 및 브리핑 데이터를 처리합니다. Changes쿼리 및 MSW 통합
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: 쿼리 데이터 렌더링
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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
ESLint install timed out. The project may have too many dependencies for the sandbox. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
src/lib/http.ts (1)
7-11: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winRetry compounds with TanStack Query's own retry.
retry: { limit: 1 }here plus the QueryClient'sretry: 1default (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. setretry: 0here 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 winAdd error handling around
enableMocking().No
.catch()on the promise chain — ifworker.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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
eslint.config.jspackage.jsonpublic/mockServiceWorker.jssrc/client.tsxsrc/components/Header.tsxsrc/components/analysis/AnalysisPanel.tsxsrc/components/briefing/BriefingSheet.tsxsrc/components/graph/GraphPanel.tsxsrc/components/news/MobileNewsBar.tsxsrc/components/news/NewsList.tsxsrc/components/verify/VerifyView.tsxsrc/integrations/tanstack-query/root-provider.tsxsrc/lib/http.tssrc/lib/queries.tssrc/mocks/browser.tssrc/mocks/handlers.ts
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
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·관계 방향·색상도 실제 응답과 어긋날 수 있습니다. 빌더와 렌더링 메타데이터를 동일한graphpayload에서 파생하도록 통합하세요.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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
eslint.config.jspackage.jsonpublic/mockServiceWorker.jssrc/client.tsxsrc/components/Header.tsxsrc/components/analysis/AnalysisPanel.tsxsrc/components/briefing/BriefingSheet.tsxsrc/components/graph/GraphPanel.tsxsrc/components/news/MobileNewsBar.tsxsrc/components/news/NewsList.tsxsrc/components/verify/VerifyView.tsxsrc/integrations/tanstack-query/root-provider.tsxsrc/lib/http.tssrc/lib/queries.tssrc/mocks/browser.tssrc/mocks/handlers.ts
| enableMocking().then(() => { | ||
| startTransition(() => { | ||
| hydrateRoot( | ||
| document, | ||
| <StrictMode> | ||
| <StartClient /> | ||
| </StrictMode>, | ||
| ) | ||
| }) | ||
| }) |
There was a problem hiding this comment.
🩺 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 --hiddenRepository: 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.
| 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.
api 재검토 예정
|
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>
There was a problem hiding this comment.
🧹 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§or=반도체&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.mdaround 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>
There was a problem hiding this comment.
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
📒 Files selected for processing (11)
.claude/skills/koslink-design-constraints/SKILL.mdCLAUDE.mddocs/KOSLINK-FRONTEND.mdsrc/components/news/NewsList.tsxsrc/components/verify/VerifyList.tsxsrc/components/verify/VerifyView.tsxsrc/lib/api.tssrc/lib/queries.tssrc/lib/useInfiniteScrollTrigger.tssrc/mocks/handlers.tssrc/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
👥 작업 배경 및 목적
UI는 완성됐지만 모든 화면이 정적 목데이터(
lib/data.ts)를 동기 함수로 직접 읽고 있었습니다. 실제 백엔드 연동을 위해 ky + TanStack Query 클라이언트 세팅 → MSW 목킹 → 컴포넌트 연동 순서로 데이터 계층을 교체했습니다.🛠️ 주요 변경 사항
신규 파일
src/lib/http.tsprefix: /api, timsrc/lib/queries.ts/apifetch 함수 + TanStack Query 훅 (useNewsQuery등 5개)src/mocks/handlers.ts/api5개 엔드포인트 MSW 목 핸들src/mocks/browser.tssrc/client.tsx수정 파일
NewsList,MobileNewsBar,AnalysisPanel,VerifyView,BriefingSheet,Header,GraphPanellib/api.ts/lib/data.ts직접 호출 → 쿼리 훅으로 교체root-provider.tsxlib/api.ts동기 함수는 삭제하지 않고placeholderData(즉시 표시) + MSW 응답 생성에 재사용 → 네트워크 없어도 화면 즉시 렌더GraphPanel.tsx는buildFocusScene/buildAll인자로 받도록 시그니처 변경됨. 좌표 계산(lib/layout.ts`)은의도적으로 그대로 둠(정적 데이터 소스 공유라 지금은 문제 없음)🧪 테스트 결과
/api/*5개 요청 전부 200 + MSW 응답(fromServiceWorker: true), 콘솔 에러 없음pnpm lint/pnpm check/pnpm build통과📡 API 명세 (백엔드 공유용)
Base URL
/api· 인증 없음/newssector?,limit?{ items: NewsListItem[] }/news/{id}/analysisidNewsAnalysis(없으면 404)/graph{ nodes: OntologyNode[], edges: OntologyEdge[] }/briefing{ tickers: string[] }BriefingResult/verifydays?(기본 30){ daily: VerifyDaily[], news: VerifyEntry[] }응답 예시 (JSON)
Summary by CodeRabbit
Summary