-
Notifications
You must be signed in to change notification settings - Fork 2
[refactor] 객체 추론 모드 스위치 정리 #433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
[refactor] 객체 추론 모드 스위치 정리 #433
Conversation
📝 WalkthroughSummary by CodeRabbit
Walkthrough클라이언트/서버 검출 모드 도입으로 ONNX 모델 워밍업·프리로드 로직을 훅으로 분리하고, 검출 관련 쿼리·캐시·프리페치 흐름을 환경변수 기반 토글과 imageId 안전 검사로 리팩토링했습니다. API 시그니처·캐시 스키마·훅 인터페이스 일부가 변경되었습니다. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
빌드 결과빌드 성공 🎊 |
🎨 Storybook 빌드 완료!📚 Storybook: https://686a831b8e000345a949970a-iutdqpupbf.chromatic.com/ 📊 빌드 정보
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58b848402e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
🤖 Fix all issues with AI agents
In `@src/layout/RootLayout.tsx`:
- Around line 1-4: ESLint import/order is violated in RootLayout.tsx because
external package import (Outlet from 'react-router-dom') is not separated by a
blank line from internal aliased imports (useScrollToTop from
'@/shared/hooks/useScrollToTop' and useGenerateWarmup from
'@pages/generate/hooks/useGenerateWarmup'); fix by grouping imports and
inserting a single empty line between the external import group and the internal
alias group so that the imports for Outlet are separated from useScrollToTop and
useGenerateWarmup.
In `@src/pages/generate/constants/curationDetectionMode.ts`:
- Around line 3-6: Replace the explicit type annotation for
CURATION_DETECTION_MODE with the TypeScript satisfies operator so the value
retains literal inference while still conforming to CurationDetectionMode:
update the declaration of CURATION_DETECTION_MODE to use "satisfies
CurationDetectionMode" on the computed value (the import.meta.env check
expression) instead of the current ": CurationDetectionMode" annotation,
ensuring the runtime ternary ('client' : 'server') remains unchanged and the
constant still exports the same value.
- Around line 8-9: The export for IS_CLIENT_DETECTION_ENABLED is split across
two lines causing a Prettier formatting error; collapse it into a single line so
the expression uses a single-line declaration, e.g. update the declaration that
references CURATION_DETECTION_MODE and IS_CLIENT_DETECTION_ENABLED to remove the
unnecessary newline and trailing spaces.
In `@src/pages/generate/hooks/useFurnitureCuration.ts`:
- Around line 141-146: The enabled check wrongly uses Boolean(imageId) which
treats 0 as falsy; update the null check used by isCategoryQueryEnabled to
verify imageId !== null (so numeric 0 is allowed) where the query is configured
(the query options that call getGeneratedImageCategories and
getCategoryQueryDetectedObjects inside useFurnitureCuration.ts); keep the rest
of the mode logic in getCategoryQueryDetectedObjects and isCategoryQueryEnabled
unchanged.
In `@src/pages/generate/hooks/useGenerateWarmup.ts`:
- Around line 12-17: GENERATE_WARMUP_PATHS currently includes ROUTES.GENERATE
plus its subpaths ROUTES.GENERATE_RESULT and ROUTES.GENERATE_START, causing
redundant matching because the startsWith check on ROUTES.GENERATE already
covers those; either remove ROUTES.GENERATE_RESULT and ROUTES.GENERATE_START
from the array to eliminate duplication, or add an inline comment next to
GENERATE_WARMUP_PATHS documenting that the explicit subpaths are intentionally
included for clarity, referencing the symbols GENERATE_WARMUP_PATHS,
ROUTES.GENERATE, ROUTES.GENERATE_RESULT, and ROUTES.GENERATE_START so reviewers
can see the intent.
In `@src/pages/generate/hooks/useOnnxModel.ts`:
- Around line 225-228: The function signature for useONNXModel is split across
multiple lines, triggering Prettier's prettier/prettier rule; collapse the
signature into a single line so it reads exactly as: export function
useONNXModel(modelPath: string, options?: UseONNXModelOptions) { and keep the
body unchanged to satisfy formatting rules and ESLint/Prettier.
In `@src/pages/generate/hooks/useStartPageModelPreload.ts`:
- Around line 8-18: The server-side noop hook useStartPageModelPreloadServer is
intentionally empty to keep client/server hook counts stable; add a defensive
comment inside useStartPageModelPreloadServer (and optionally above the export
useStartPageModelPreload) stating that it must remain a noop to avoid hook-count
mismatches if someone later adds hooks to useStartPageModelPreloadClient or to
the server variant, and mention that any future hook logic must be mirrored on
both branches to preserve rules-of-hooks safety.
In `@src/pages/mypage/hooks/useDetectionPrefetch.client.ts`:
- Around line 21-24: PrefetchTask is declared as a type but represents an object
shape—change its declaration to an interface by replacing the "type PrefetchTask
= { ... }" with "interface PrefetchTask { imageId: number; imageUrl: string; }"
(keep the same property names and types) so it follows the guideline that object
shapes use interface; ensure any references to PrefetchTask in
useDetectionPrefetch (and related hooks/functions) continue to compile without
other changes.
- Around line 35-48: The loadImageElement promise can hang forever if the image
never loads; update loadImageElement to implement a timeout (using
AbortSignal.timeout or a setTimeout that rejects) so the promise rejects after a
configurable duration, ensure you clear the timeout and remove event handlers on
both success and failure to avoid leaks, and include the timeout rejection path
in the same Promise flow used by loadImageElement so callers get a timely error
instead of a permanently pending promise.
- Around line 59-66: The hook useDetectionPrefetchClient is missing cleanup on
unmount so in-flight inference and store writes continue; add an AbortController
(e.g., abortCtrlRef) stored in a ref and create a useEffect that returns a
cleanup which calls abortCtrlRef.current.abort(), clears queueRef and
pendingRef, sets a flag (or drainingRef) to stop dequeuing, and resolves/clears
waitersRef; update the runInference usage and any async worker loop to
pass/observe the abort signal (or check abortCtrlRef.current.signal.aborted)
before calling setEntry and before starting work so aborted tasks are skipped
and no further store writes occur after unmount.
- Around line 147-189: executePrefetch is closing over stale isLoading/error so
prefetch tasks are dropped while the model loads; change executePrefetch (in
useDetectionPrefetch) to read current model state from a ref or the detection
model store inside the function (e.g., modelLoadingRef.current or
useDetectionModelStore.getState()) instead of depending on the stale
isLoading/error in the closure, update dependencies to avoid capturing those
booleans, and ensure you retry the queue by adding an effect that calls
drainQueue when the model finishes loading (watching isLoading/error or the
ref/store state) so queued items are not lost; reference executePrefetch,
drainQueue, queueRef/pendingRef and the model loader hooks
(useONNXModel/useDetectionModelStore) when making changes.
- Around line 191-211: drainQueue currently empties queueRef into jobs then
awaits Promise.all(jobs), so tasks enqueued while awaiting are lost; change
drainQueue (the function using queueRef, drainingRef, runWithSemaphore,
executePrefetch, PREFETCH_DELAY_MS) to repeatedly drain until the queue remains
empty after awaiting — e.g. replace the single gather-and-await pass with a loop
that: shift a task, if none break, call/await runWithSemaphore(async () => {
await executePrefetch(...); await sleep(PREFETCH_DELAY_MS) }) (or after
collecting jobs await them and then re-check queueRef.length in a surrounding
loop) so any tasks added while awaiting are processed before clearing
drainingRef; keep drainingRef toggling and finally block as-is.
- Around line 122-145: processAndStore is redundantly re-filtering results
because mapHotspotsToDetectedObjects already applies
filterAllowedDetectedObjects; remove the extra filtering step in processAndStore
by assigning detectedObjects directly from
mapHotspotsToDetectedObjects(pipeline.hotspots) (keep pipeline =
buildHotspotsPipeline(...) and then call storeDetections(imageId, imageUrl,
processed, { hotspots: pipeline.hotspots, detectedObjects }) without calling
filterAllowedDetectedObjects again.
In `@src/pages/mypage/hooks/useDetectionPrefetch.server.ts`:
- Around line 3-7: PrefetchPriority and DetectionPrefetchOptions are duplicated
between client and server; extract them into a single shared type file (e.g.,
create useDetectionPrefetch.types.ts) that exports PrefetchPriority and
DetectionPrefetchOptions, then replace the local definitions in both
implementations to import those types; alternatively export the types from your
main useDetectionPrefetch.ts and import from there—update imports in the server
hook (useDetectionPrefetch.server.ts) and any client file to reference the new
shared definitions and run a compile to confirm no stale local definitions
remain.
| const processAndStore = useCallback( | ||
| ( | ||
| imageId: number, | ||
| imageUrl: string, | ||
| targetImage: HTMLImageElement, | ||
| processed: ProcessedDetections | ||
| ) => { | ||
| const pipeline = buildHotspotsPipeline(targetImage, processed); | ||
| const rawDetectedObjects = mapHotspotsToDetectedObjects( | ||
| pipeline.hotspots | ||
| ); | ||
| const detectedObjects = filterAllowedDetectedObjects(rawDetectedObjects, { | ||
| stage: 'prefetch-detection', | ||
| imageId, | ||
| hotspotCount: pipeline.hotspots.length, | ||
| }); | ||
|
|
||
| storeDetections(imageId, imageUrl, processed, { | ||
| hotspots: pipeline.hotspots, | ||
| detectedObjects, | ||
| }); | ||
| }, | ||
| [storeDetections] | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# detectedObjectMapper 파일 찾기
find . -name "*detectedObjectMapper*" -o -name "*detected*mapper*" | head -20Repository: TEAM-HOUME/HOUME-CLIENT
Length of output: 117
🏁 Script executed:
#!/bin/bash
# mapHotspotsToDetectedObjects 함수 찾기
rg -n "mapHotspotsToDetectedObjects" --type ts,tsx -A 30 | head -100Repository: TEAM-HOUME/HOUME-CLIENT
Length of output: 97
🏁 Script executed:
#!/bin/bash
# filterAllowedDetectedObjects 호출 위치 전체 확인
rg -n "filterAllowedDetectedObjects" --type ts,tsxRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 97
🏁 Script executed:
#!/bin/bash
# detectedObjectMapper.ts 파일 내용 읽기
cat -n ./src/pages/generate/utils/detectedObjectMapper.tsRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 2785
🏁 Script executed:
#!/bin/bash
# useDetectionPrefetch.client.ts 파일 내용 확인 (해당 줄 주변)
wc -l ./src/pages/mypage/hooks/useDetectionPrefetch.client.tsRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 126
🏁 Script executed:
#!/bin/bash
# filterAllowedDetectedObjects 모든 호출 위치 확인
rg -n "filterAllowedDetectedObjects" --type-list | grep -i tsRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 456
🏁 Script executed:
#!/bin/bash
# 다시 시도 - 올바른 문법으로
rg -n "filterAllowedDetectedObjects" -t tsRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 758
🏁 Script executed:
#!/bin/bash
# useDetectionPrefetch.client.ts의 processAndStore 함수 확인 (라인 122-145)
sed -n '120,150p' ./src/pages/mypage/hooks/useDetectionPrefetch.client.ts | cat -nRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 1171
🏁 Script executed:
#!/bin/bash
# useDetectionPrefetch.client.ts 임포트 부분도 확인
sed -n '1,20p' ./src/pages/mypage/hooks/useDetectionPrefetch.client.ts | cat -nRepository: TEAM-HOUME/HOUME-CLIENT
Length of output: 1140
mapHotspotsToDetectedObjects가 이미 필터링한 결과를 다시 필터링하고 있어요.
mapHotspotsToDetectedObjects는 내부에서 filterAllowedDetectedObjects를 호출하고 필터링된 배열을 반환합니다 (detectedObjectMapper.ts 라인 42-45). processAndStore에서 그 반환값을 다시 filterAllowedDetectedObjects에 전달하면 불필요한 중복 필터링이 발생합니다.
🐛 수정 제안
const processAndStore = useCallback(
(
imageId: number,
imageUrl: string,
targetImage: HTMLImageElement,
processed: ProcessedDetections
) => {
const pipeline = buildHotspotsPipeline(targetImage, processed);
- const rawDetectedObjects = mapHotspotsToDetectedObjects(
+ const detectedObjects = mapHotspotsToDetectedObjects(
pipeline.hotspots
);
- const detectedObjects = filterAllowedDetectedObjects(rawDetectedObjects, {
- stage: 'prefetch-detection',
- imageId,
- hotspotCount: pipeline.hotspots.length,
- });
storeDetections(imageId, imageUrl, processed, {
hotspots: pipeline.hotspots,
detectedObjects,
});
},
[storeDetections]
);🤖 Prompt for AI Agents
In `@src/pages/mypage/hooks/useDetectionPrefetch.client.ts` around lines 122 -
145, processAndStore is redundantly re-filtering results because
mapHotspotsToDetectedObjects already applies filterAllowedDetectedObjects;
remove the extra filtering step in processAndStore by assigning detectedObjects
directly from mapHotspotsToDetectedObjects(pipeline.hotspots) (keep pipeline =
buildHotspotsPipeline(...) and then call storeDetections(imageId, imageUrl,
processed, { hotspots: pipeline.hotspots, detectedObjects }) without calling
filterAllowedDetectedObjects again.
빌드 결과빌드 성공 🎊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pages/generate/stores/useCurationCacheStore.ts (1)
56-106: 🧹 Nitpick | 🔵 Trivial
groupId가드에서 0이 유효 ID로 처리되지 않는 기존 패턴이 있어요.이번 변경의
imageId추가 자체는 문제없지만, 기존if (!groupId) return(Line 65) 및if (!groupId || !categoryId) return(Line 86) 가드가0을 falsy로 평가해요.imageId에는!== null체크를 쓰고 있는데,groupId/categoryId도 동일 패턴으로 맞추는 것이 좋겠어요.♻️ 일관성 개선 제안
saveCategories: ({ groupId, imageId, response, detectedObjects, detectionSignature, }) => { - if (!groupId) return; + if (groupId === null || groupId === undefined) return;- saveProducts: ({ groupId, imageId, categoryId, response }) => { - if (!groupId || !categoryId) return; + saveProducts: ({ groupId, imageId, categoryId, response }) => { + if (groupId == null || categoryId == null) return;
🤖 Fix all issues with AI agents
In `@src/pages/generate/constants/curationDetectionMode.ts`:
- Around line 10-11: The function getCategoryQueryDetectedObjects currently
relies on inferred return type; explicitly annotate its signature to return T[]
| undefined to make the API contract clear (update the exported function
declaration signature to include the return type) and ensure any callers/readers
can immediately see that it may return an array of T or undefined.
- Around line 3-6: The CURATION_DETECTION_MODE export's formatting must follow
Prettier style: move the opening parenthesis so the assignment reads "export
const CURATION_DETECTION_MODE = ( ... )" with the closing parenthesis on its own
line immediately before "satisfies CurationDetectionMode" (adjust the expression
around CURATION_DETECTION_MODE accordingly), and also add a trailing comma to
any generic declarations (e.g., change occurrences of "<T>" to "<T,>" wherever
used in this module). Run Prettier (or apply the same formatting) to ensure the
file matches project formatting conventions.
In `@src/pages/generate/hooks/useGenerateWarmup.ts`:
- Around line 12-15: Prettier flagged the multi-line array for
GENERATE_WARMUP_PATHS; collapse the array into a single line by updating the
constant declaration (GENERATE_WARMUP_PATHS) so the elements are on one line
(e.g., const GENERATE_WARMUP_PATHS = [ROUTES.GENERATE, ROUTES.IMAGE_SETUP];) and
reformat/save so ESLint(prettier/prettier) no longer reports the rule.
In `@src/pages/generate/hooks/useOnnxModel.ts`:
- Around line 234-241: When enabled flips from true to false we should abort any
in-flight model download instead of just ignoring its result: add an
AbortController ref (e.g., abortControllerRef) to useOnnxModel, have
ensureModelLoad accept a signal (or read abortControllerRef.current.signal) and
pass that signal into the fetch/stream used to download the model, store the
controller when starting a load, and on the enabled=false branch call
abortControllerRef.current?.abort(), clear abortControllerRef.current and any
cached ensureModelLoad Promise, then proceed with
setSession(null)/ortRef.current=null/etc.; update ensureModelLoad and any helper
that performs fetch to handle AbortError cleanly.
In `@src/pages/mypage/hooks/useDetectionPrefetch.client.ts`:
- Around line 199-206: When falling back after loadImageElement fails, ensure
the AbortSignal is forwarded to prevent orphaned fetches: pass controller.signal
into loadCorsImage calls (and any other fallback loaders used in the same
try/catch, e.g., the SecurityError fallback path) and keep the existing
early-return check using controller.signal.aborted and isMountedRef.current;
update the calls to loadCorsImage(...) to accept and use the provided signal so
the fetch can be aborted when the controller is aborted or the component
unmounts.
- Around line 191-195: Several lines in useDetectionPrefetch.client.ts violate
Prettier formatting (missing newlines around the conditional blocks and a line
break for controller.abort()); run prettier --write on the file and adjust the
formatting around the referenced symbols: ensure the conditional block that
checks useDetectionCacheStore.getState().images[imageId],
modelStateRef.current.isLoading / modelStateRef.current.error, and
isMountedRef.current each have proper line breaks and that the
controller.abort() call is on its own line; after formatting, re-run lint to
verify no remaining Prettier errors.
- Around line 13-20: The imports violate the project's ESLint import/order rule:
remove the blank line between grouped imports and reorder so the local type
import (DetectionPrefetchOptions, PrefetchTask from './detectionPrefetch.types')
appears in the correct group before/after the other type imports per your
config; specifically ensure the import of './detectionPrefetch.types' is placed
in the proper group relative to FurnitureCategoryCode, FurnitureHotspot, and
ProcessedDetections and delete the empty line at the current separation to
satisfy the rule.
| export const getCategoryQueryDetectedObjects = <T>(detectedObjects: T[]) => | ||
| IS_CLIENT_DETECTION_ENABLED ? detectedObjects : undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
getCategoryQueryDetectedObjects의 반환 타입을 명시적으로 표기하면 API 계약이 더 명확해져요.
현재 추론된 타입은 T[] | undefined인데, 호출처에서 의도를 바로 파악하기 어려울 수 있어요. 선택적 제안이에요.
💡 타입 명시 제안
-export const getCategoryQueryDetectedObjects = <T>(detectedObjects: T[]) =>
- IS_CLIENT_DETECTION_ENABLED ? detectedObjects : undefined;
+export const getCategoryQueryDetectedObjects = <T>(
+ detectedObjects: T[]
+): T[] | undefined =>
+ IS_CLIENT_DETECTION_ENABLED ? detectedObjects : undefined;📝 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.
| export const getCategoryQueryDetectedObjects = <T>(detectedObjects: T[]) => | |
| IS_CLIENT_DETECTION_ENABLED ? detectedObjects : undefined; | |
| export const getCategoryQueryDetectedObjects = <T>( | |
| detectedObjects: T[] | |
| ): T[] | undefined => | |
| IS_CLIENT_DETECTION_ENABLED ? detectedObjects : undefined; |
🤖 Prompt for AI Agents
In `@src/pages/generate/constants/curationDetectionMode.ts` around lines 10 - 11,
The function getCategoryQueryDetectedObjects currently relies on inferred return
type; explicitly annotate its signature to return T[] | undefined to make the
API contract clear (update the exported function declaration signature to
include the return type) and ensure any callers/readers can immediately see that
it may return an array of T or undefined.
| if (!enabled) { | ||
| setSession(null); | ||
| ortRef.current = null; | ||
| setIsLoading(false); | ||
| setError(null); | ||
| setProgress(0); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
enabled=false 시 이미 로드 중인 모델 fetch를 취소하지 않는 점을 확인해 주세요.
enabled가 true→false로 전환될 때, 이미 진행 중인 ensureModelLoad Promise는 isMounted = false로 결과만 무시되지만 네트워크 요청 자체는 완료될 때까지 계속 돼요. 모델이 수십 MB인 점을 고려하면, AbortController를 도입해 불필요한 다운로드를 중단하는 것이 바람직해요.
현재 구조에서 ensureModelLoad가 Promise 캐시를 공유하므로 즉각적인 문제는 아니지만, 모바일 환경에서 대역폭 낭비가 될 수 있어요.
🤖 Prompt for AI Agents
In `@src/pages/generate/hooks/useOnnxModel.ts` around lines 234 - 241, When
enabled flips from true to false we should abort any in-flight model download
instead of just ignoring its result: add an AbortController ref (e.g.,
abortControllerRef) to useOnnxModel, have ensureModelLoad accept a signal (or
read abortControllerRef.current.signal) and pass that signal into the
fetch/stream used to download the model, store the controller when starting a
load, and on the enabled=false branch call abortControllerRef.current?.abort(),
clear abortControllerRef.current and any cached ensureModelLoad Promise, then
proceed with setSession(null)/ortRef.current=null/etc.; update ensureModelLoad
and any helper that performs fetch to handle AbortError cleanly.
| import type { FurnitureCategoryCode } from '@pages/generate/constants/furnitureCategoryMapping'; | ||
| import type { FurnitureHotspot } from '@pages/generate/hooks/useFurnitureHotspots'; | ||
| import type { ProcessedDetections } from '@pages/generate/types/detection'; | ||
|
|
||
| import type { | ||
| DetectionPrefetchOptions, | ||
| PrefetchTask, | ||
| } from './detectionPrefetch.types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ESLint import/order 위반이에요.
정적 분석 도구에서 다음 두 가지를 보고하고 있어요:
- Line 15: import 그룹 내 빈 줄이 있으면 안 됨
- Lines 17-20:
./detectionPrefetch.types타입 임포트가@pages/generate/constants/furnitureCategoryMapping타입 임포트보다 앞에 와야 함
♻️ 수정 제안
import {
filterAllowedDetectedObjects,
mapHotspotsToDetectedObjects,
} from '@pages/generate/utils/detectedObjectMapper';
-import type { FurnitureCategoryCode } from '@pages/generate/constants/furnitureCategoryMapping';
-import type { FurnitureHotspot } from '@pages/generate/hooks/useFurnitureHotspots';
-import type { ProcessedDetections } from '@pages/generate/types/detection';
-
import type {
DetectionPrefetchOptions,
PrefetchTask,
} from './detectionPrefetch.types';
+import type { FurnitureCategoryCode } from '@pages/generate/constants/furnitureCategoryMapping';
+import type { FurnitureHotspot } from '@pages/generate/hooks/useFurnitureHotspots';
+import type { ProcessedDetections } from '@pages/generate/types/detection';참고: 정확한 순서는 프로젝트 ESLint 설정의 import/order 규칙을 따라주세요. 위 제안은 로컬 임포트를 외부 임포트 앞에 두는 방향이지만, 실제 규칙과 다를 수 있어요.
🧰 Tools
🪛 ESLint
[error] 15-15: There should be no empty line within import group
(import/order)
[error] 17-20: ./detectionPrefetch.types type import should occur before type import of @pages/generate/constants/furnitureCategoryMapping
(import/order)
🤖 Prompt for AI Agents
In `@src/pages/mypage/hooks/useDetectionPrefetch.client.ts` around lines 13 - 20,
The imports violate the project's ESLint import/order rule: remove the blank
line between grouped imports and reorder so the local type import
(DetectionPrefetchOptions, PrefetchTask from './detectionPrefetch.types')
appears in the correct group before/after the other type imports per your
config; specifically ensure the import of './detectionPrefetch.types' is placed
in the proper group relative to FurnitureCategoryCode, FurnitureHotspot, and
ProcessedDetections and delete the empty line at the current separation to
satisfy the rule.
빌드 결과빌드 성공 🎊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@src/pages/generate/constants/curationDetectionMode.ts`:
- Around line 11-22: These three exported runtime helper functions
(getCategoryQueryDetectedObjects, isCategoryQueryEnabled,
shouldShowDetectionPending) should not live under constants; move them into a
more appropriate runtime utility or hook module (e.g.,
src/utils/curationDetection.ts or src/hooks/useCurationDetection.ts), update
their imports where used, and keep their signatures and behavior unchanged;
ensure any file that imported from constants/curationDetectionMode.ts now
imports from the new module and delete the original file or replace it with only
true compile-time constants if needed.
- Around line 11-12: The TypeScript generic in getCategoryQueryDetectedObjects
is using an invalid trailing comma syntax; change the generic declaration from
<T,> to <T> in the function signature (getCategoryQueryDetectedObjects) so the
generic is valid and Prettier/TS compile errors are resolved.
In `@src/pages/generate/hooks/useGenerateWarmup.ts`:
- Around line 29-31: Add a clear JSDoc above the useGenerateWarmupServer
function to state it is intentionally a no-op hook in server mode and to
document it as an extension point for future server-side warmup logic (e.g.,
cache preheat, background tasks); keep the current function signature
(useGenerateWarmupServer) and behavior (no-op / returns undefined or a noop
cleanup) so callers remain unchanged, and mention any expected future
responsibilities and where to add them.
- Around line 14-27: The catch in useGenerateWarmupClient silently swallows
errors from preloadONNXModel(OBJ365_MODEL_PATH); change the error handler to log
a warning so failures are visible: inside the useEffect where
preloadONNXModel(OBJ365_MODEL_PATH).catch(...) is called, replace the empty
catch with a handler that logs the error (e.g., console.warn or
processLogger.warn) including context like "warmup preload failed" and the error
object, keeping the rest of the hook (useEffect, dependency on location.pathname
and matching logic) unchanged.
| export const getCategoryQueryDetectedObjects = <T,>(detectedObjects: T[]) => | ||
| IS_CLIENT_DETECTION_ENABLED ? detectedObjects : undefined; | ||
|
|
||
| export const isCategoryQueryEnabled = ( | ||
| imageId: number | null, | ||
| detectedObjectsCount: number | ||
| ) => | ||
| imageId !== null && | ||
| (!IS_CLIENT_DETECTION_ENABLED || detectedObjectsCount > 0); | ||
|
|
||
| export const shouldShowDetectionPending = (detectedObjectsCount: number) => | ||
| IS_CLIENT_DETECTION_ENABLED && detectedObjectsCount === 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
constants/ 경로에 헬퍼 함수 3개가 포함되어 있어요.
getCategoryQueryDetectedObjects, isCategoryQueryEnabled, shouldShowDetectionPending는 상수가 아닌 런타임 헬퍼 함수예요. constants/ 디렉터리의 의미와 맞지 않으므로, 별도 유틸이나 훅 모듈로 분리하는 것을 고려해 보세요.
🧰 Tools
🪛 ESLint
[error] 11-11: Delete ,
(prettier/prettier)
🤖 Prompt for AI Agents
In `@src/pages/generate/constants/curationDetectionMode.ts` around lines 11 - 22,
These three exported runtime helper functions (getCategoryQueryDetectedObjects,
isCategoryQueryEnabled, shouldShowDetectionPending) should not live under
constants; move them into a more appropriate runtime utility or hook module
(e.g., src/utils/curationDetection.ts or src/hooks/useCurationDetection.ts),
update their imports where used, and keep their signatures and behavior
unchanged; ensure any file that imported from constants/curationDetectionMode.ts
now imports from the new module and delete the original file or replace it with
only true compile-time constants if needed.
| const useGenerateWarmupClient = () => { | ||
| const location = useLocation(); | ||
|
|
||
| useEffect(() => { | ||
| const pathname = location.pathname; | ||
| const shouldWarmup = GENERATE_WARMUP_PATHS.some( | ||
| (prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`) | ||
| ); | ||
|
|
||
| if (!shouldWarmup) return; | ||
|
|
||
| preloadONNXModel(OBJ365_MODEL_PATH).catch(() => undefined); | ||
| }, [location.pathname]); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
useGenerateWarmupClient 훅 구조가 적절해요.
경로 매칭 로직(pathname === prefix || pathname.startsWith(...))이 정확하고, useEffect 의존성 배열도 올바르게 구성되어 있어요.
한 가지 제안: Line 25에서 .catch(() => undefined)로 에러를 완전히 무시하고 있는데, 디버깅 시 warmup 실패 원인 파악이 어려울 수 있어요. 최소한 console.warn 수준의 로깅을 추가하면 운영 시 유용해요.
🔧 제안
- preloadONNXModel(OBJ365_MODEL_PATH).catch(() => undefined);
+ preloadONNXModel(OBJ365_MODEL_PATH).catch((e) => {
+ console.warn('[useGenerateWarmup] model preload failed:', e);
+ });🤖 Prompt for AI Agents
In `@src/pages/generate/hooks/useGenerateWarmup.ts` around lines 14 - 27, The
catch in useGenerateWarmupClient silently swallows errors from
preloadONNXModel(OBJ365_MODEL_PATH); change the error handler to log a warning
so failures are visible: inside the useEffect where
preloadONNXModel(OBJ365_MODEL_PATH).catch(...) is called, replace the empty
catch with a handler that logs the error (e.g., console.warn or
processLogger.warn) including context like "warmup preload failed" and the error
object, keeping the rest of the hook (useEffect, dependency on location.pathname
and matching logic) unchanged.
| const useGenerateWarmupServer = () => { | ||
| // 서버 모드 no-op 훅 | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
No-op 훅의 의도를 명확히 해두면 좋겠어요.
현재 주석이 한 줄이지만, 향후 서버 모드에서 다른 warmup 로직(예: 서버 캐시 프리히트)을 추가할 가능성이 있다면, JSDoc으로 확장 포인트를 남겨두는 것도 고려해 보세요.
🤖 Prompt for AI Agents
In `@src/pages/generate/hooks/useGenerateWarmup.ts` around lines 29 - 31, Add a
clear JSDoc above the useGenerateWarmupServer function to state it is
intentionally a no-op hook in server mode and to document it as an extension
point for future server-side warmup logic (e.g., cache preheat, background
tasks); keep the current function signature (useGenerateWarmupServer) and
behavior (no-op / returns undefined or a noop cleanup) so callers remain
unchanged, and mention any expected future responsibilities and where to add
them.
빌드 결과빌드 성공 🎊 |
📌 Summary
클라이언트 객체 추론 경로를 mode 기반으로 전환하고, preload/prefetch/warmup을 모드별 훅으로 분리해 OFF/ON 전환 비용을 낮췄습니다.
기본 모드는
server이며, 설정 시에만client모드로 전환됩니다.📄 Tasks
🔍 To Reviewer
detectedObjects없이도 안정적으로 동작하는 서버 계약 확인이 필요합니다.📸 Screenshot