Skip to content

[chore] ESLint 규칙 추가 및 수정#292

Merged
ff1451 merged 8 commits intodevelopfrom
291-chore-eslint-규칙-추가-및-수정-pr
Apr 22, 2026

Hidden character warning

The head ref may contain hidden characters: "291-chore-eslint-\uaddc\uce59-\ucd94\uac00-\ubc0f-\uc218\uc815-pr"
Merged

[chore] ESLint 규칙 추가 및 수정#292
ff1451 merged 8 commits intodevelopfrom
291-chore-eslint-규칙-추가-및-수정-pr

Conversation

@ff1451
Copy link
Copy Markdown
Collaborator

@ff1451 ff1451 commented Apr 22, 2026

✨ 요약

ESLint typed linting과 TanStack Query strict preset을 도입하고, no-void / import/no-cycle / 네이티브 브릿지 직접 접근 금지 / raw fetch 제한 규칙을 추가했습니다.
규칙 적용에 맞춰 route state 타입, query key 구성, 브릿지 접근 경로, Promise 처리 표현을 코드베이스 전반에서 정리했습니다.



😎 해결한 이슈



Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • API 응답 검증 강화로 토큰 갱신 및 데이터 조회 시 더 명확한 오류 메시지 제공
    • 필수 데이터 누락 시 상세한 오류 메시지로 문제 진단 개선
  • Chores

    • 코드 품질 및 타입 안정성 향상
    • 런타임 에러 처리 패턴 개선
    • 개발 환경 린팅 규칙 강화

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@ff1451 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 36 minutes and 49 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 36 minutes and 49 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d3fe7e6e-688f-48b5-8912-5a1a506e5dda

📥 Commits

Reviewing files that changed from the base of the PR and between 2897e07 and 82796e7.

📒 Files selected for processing (6)
  • eslint.config.js
  • package.json
  • src/components/notification/InboxNotificationLayer.tsx
  • src/main.tsx
  • src/pages/Manager/ManagedAccount/index.tsx
  • src/utils/ts/cookie.ts

Walkthrough

ESLint 규칙을 강화하고 런타임 타입 안전성을 개선하는 PR입니다. @tanstack/eslint-plugin-query 추가, TypeScript 타입 검증 강화(isRefreshTokenResponse, isApiErrorResponse), 네비게이션 상태 타입 통일(SmartBackState), Promise 처리 정규화(불필요한 void 제거), 함수 시그니처 개선(객체 기반 파라미터화), 네이티브 브릿지 추상화(hasNativeBridge()) 등을 포함합니다.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 '[chore] ESLint 규칙 추가 및 수정'은 ESLint 설정 변경이라는 주요 변경 사항을 명확하고 간결하게 요약하고 있습니다.
Linked Issues check ✅ Passed PR의 모든 주요 변경사항(ESLint 규칙 추가, type-safe 강화, Promise 처리 정리, 네이티브 브릿지 추상화 등)이 #291의 목적을 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 ESLint 규칙 적용 및 코드베이스 일관성 확보라는 명확한 목적 범위 내에 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 291-chore-eslint-규칙-추가-및-수정-pr

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 and usage tips.

@ff1451 ff1451 added the ⚙️ Setting 개발 환경 세팅 label Apr 22, 2026
@ff1451 ff1451 self-assigned this Apr 22, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (1)
eslint.config.js (1)

3-5: 🛠️ Refactor suggestion | 🟠 Major

eslint-plugin-react-xeslint-plugin-react-dom 플러그인을 설치하고 구성해야 합니다.

현재 설정은 기존의 eslint-plugin-react 기반이지만, 코딩 가이드라인에서는 modern eslint-react 에코시스템의 eslint-plugin-react-xeslint-plugin-react-dom을 flat config로 구성하도록 요구합니다. 이들은 React DOM 최적화 규칙과 최신 React 베스트 프랙티스를 제공합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` around lines 3 - 5, Replace the legacy eslint-plugin-react
setup with the modern flat-config plugins: install and import
"eslint-plugin-react-x" and "eslint-plugin-react-dom" instead of
"eslint-plugin-react", keep "eslint-plugin-react-hooks" and
"eslint-plugin-react-refresh", then update the flat config to register the new
plugins (e.g., the imported symbols replacing react) and enable the recommended
rule sets from "react-x" and "react-dom" (including React DOM optimization
rules); specifically, change the import lines (current react, reactHooks,
reactRefresh) to import reactX and reactDom, add those plugin references to the
exports/config registration, and migrate any react-specific rule names to the
equivalents provided by react-x/react-dom.
🧹 Nitpick comments (5)
src/types/navigation.ts (1)

1-8: backState 재귀 타입 고려

현재 backState{ from?: string }으로 제한되어 있어, 다단계 뒤로가기 체이닝(예: A → B → C에서 뒤로가기 시 B의 backPath/backState 전달)이 필요한 경우 타입이 막힐 수 있습니다. 필요 시 재귀 타입으로 확장 고려해보세요. 지금 사용처에서는 from만 쓰이므로 필수는 아닙니다.

♻️ 참고용 제안
 export interface SmartBackState {
   backPath?: string;
   backReplace?: boolean;
-  backState?: {
-    from?: string;
-  };
+  backState?: SmartBackState;
   from?: string;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/types/navigation.ts` around lines 1 - 8, SmartBackState currently defines
backState as a flat object ({ from?: string }) which blocks multi-level
back-chain data; change backState to a recursive type so it can optionally nest
another SmartBackState (e.g., backState?: SmartBackState | { from?: string } or
make backState?: SmartBackState) by updating the SmartBackState declaration and
any consumers (functions/types that construct or read backState) to accept the
recursive shape, ensuring existing usages that only read from are still
compatible.
src/pages/Chat/ChatRoomInfo.tsx (1)

242-242: onClick이 Promise를 반환합니다.

() => handleLeaveRoom()Promise<void>를 반환하므로 no-misused-promiseschecksVoidReturn 설정에 걸릴 수 있습니다. 블록 본문으로 감싸 Promise를 버리는 편이 안전합니다.

♻️ 제안
-              onClick={() => handleLeaveRoom()}
+              onClick={() => {
+                handleLeaveRoom();
+              }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/ChatRoomInfo.tsx` at line 242, The onClick currently returns a
Promise because it uses "() => handleLeaveRoom()", which triggers the
no-misused-promises checks; modify the handler so the click callback is a
block-bodied function that explicitly discards the Promise (e.g., call
handleLeaveRoom and void its result or await inside an async wrapper),
preventing a Promise from being returned from the onClick. Update the JSX where
onClick is set and ensure references to handleLeaveRoom remain unchanged.
package.json (1)

45-46: devDependencies 알파벳 순서.

@tanstack/eslint-plugin-query@ 스코프라 @vitejs/plugin-react 근처(또는 @tanstack류 위쪽)에 정렬되어야 합니다. 현재 eslint-plugin-react-refresh 바로 아래에 위치하여 정렬이 어긋납니다.

♻️ 제안
     "@sentry/vite-plugin": "^5.1.1",
+    "@tanstack/eslint-plugin-query": "^5.99.2",
     "@types/babel__core": "^7.20.5",
@@
     "eslint-plugin-react-refresh": "^0.4.24",
-    "@tanstack/eslint-plugin-query": "^5.99.2",
     "globals": "^16.5.0",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 45 - 46, The devDependencies are not
alphabetically ordered: "@tanstack/eslint-plugin-query" is placed after
"eslint-plugin-react-refresh" which breaks sorting for scoped packages; reorder
the entries so that scoped packages like "@tanstack/eslint-plugin-query" appear
in their correct alphabetical position (near other "@" scoped entries such as
"@vitejs/plugin-react" or above unscoped "eslint-plugin-react-refresh") by
moving the "@tanstack/eslint-plugin-query" line to the proper location in
package.json's devDependencies.
src/pages/Manager/ManagedAccount/index.tsx (1)

29-29: as 단언 대신 타입 가드 고려.

location.stateunknown이라 단순 as는 런타임에서 형태가 다를 경우 그대로 통과합니다. typed linting을 강화한 취지를 살리려면 작은 타입 가드(e.g. isEnableAfterSaveState)로 좁히는 편이 더 안전합니다. 현재는 optional 필드 하나라 영향이 작으니 선택 사항입니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Manager/ManagedAccount/index.tsx` at line 29, Replace the unsafe
cast of location.state to EnableAfterSaveState with a runtime type guard:
implement an isEnableAfterSaveState(value: unknown): value is
EnableAfterSaveState that checks the optional fields you expect, then set
navigationState by testing location.state with that guard (e.g., navigationState
= isEnableAfterSaveState(location.state) ? location.state : null) so the
narrowing is done safely at runtime instead of using a raw `as` assertion;
reference the symbols navigationState and EnableAfterSaveState and add the
isEnableAfterSaveState helper near this component.
eslint.config.js (1)

100-110: raw fetch 제한에 globalThis/self도 포함해 주세요.

현재 selector는 fetch()window.fetch()만 막아서 globalThis.fetch()self.fetch()로 우회할 수 있습니다.

🔒 제안 수정
         {
-          selector:
-            "CallExpression[callee.type='MemberExpression'][callee.object.type='Identifier'][callee.object.name='window'][callee.property.type='Identifier'][callee.property.name='fetch']",
+          selector:
+            "CallExpression[callee.type='MemberExpression'][callee.object.type='Identifier'][callee.object.name=/^(window|globalThis|self)$/][callee.property.type='Identifier'][callee.property.name='fetch']",
           message: 'fetch 직접 호출 대신 apiClient를 사용하세요. 예외가 필요한 경우 허용 파일에서만 사용하세요.',
         },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` around lines 100 - 110, The ESLint rule
'no-restricted-syntax' currently blocks direct fetch and window.fetch but allows
globalThis.fetch and self.fetch; update the rule (the 'no-restricted-syntax'
entry) to add selectors that match MemberExpression calls where the object is
globalThis or self (e.g.,
CallExpression[callee.type='MemberExpression'][callee.object.type='Identifier'][callee.object.name='globalThis'][callee.property.type='Identifier'][callee.property.name='fetch']
and the same for 'self') so those forms are also disallowed with the same
message as the existing window.fetch selector.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@eslint.config.js`:
- Around line 50-57: Enable the '@typescript-eslint/no-floating-promises' rule
by setting it to 'error' in the ESLint config so that unawaited Promises (e.g.,
calls like bootstrap();) are flagged; update the rules block that currently
contains '@typescript-eslint/no-non-null-assertion' and
'@typescript-eslint/no-misused-promises' to include
"@typescript-eslint/no-floating-promises": "error" (ensuring it aligns with the
existing 'no-void'/'no-void: error' usage if present).

In `@src/main.tsx`:
- Around line 19-20: bootstrap() can reject (dynamic import or root element
check) and needs an explicit rejection handler to avoid leaving the initial
screen blank; update the code that calls bootstrap() to append a .catch(...)
handler that logs the error (e.g., console.error or processLogger.error) and
displays/falls back to an error UI or mount a minimal fallback DOM message,
while noting startSessionRestore() / useAuthStore.getState().initialize()
already handles its own errors and does not need changes. Ensure you locate the
call to bootstrap() and add the .catch that handles/report the error and
prevents an unhandled rejection.

In `@src/pages/Manager/ManagedMemberList/index.tsx`:
- Line 163: The onSubmit prop expects a synchronous () => void but you are
passing the async Promise-returning roleManage.handleSubmit() directly; change
the prop to pass a non-async wrapper that calls roleManage.handleSubmit() and
handles the Promise (e.g., call it and attach a .catch to log/handle errors or
use void to ignore the returned Promise) so the type becomes () => void; update
the JSX where RoleManageModal is used (the onSubmit prop) to call
roleManage.handleSubmit() inside a plain arrow function and ensure any errors
are caught.

In `@src/pages/Notifications/index.tsx`:
- Around line 106-108: The catch block currently calls
queryClient.invalidateQueries(notificationQueryKeys.inbox.all()) without
awaiting or handling its returned Promise, which leaves a floating promise and
can trigger no-floating-promises lint errors or silent failures; update the
catch to either await queryClient.invalidateQueries(...) (i.e., make the
surrounding function async if needed) or explicitly swallow errors with
queryClient.invalidateQueries(...).catch(() => {}) to make intent clear, and
apply the same change to the identical pattern in
src/components/notification/InboxNotificationLayer.tsx so both uses of
queryClient.invalidateQueries and notificationQueryKeys.inbox.all() are handled
consistently.

In `@src/utils/ts/cookie.ts`:
- Around line 3-9: The cookie setter currently stores String(value) raw, which
breaks when the value contains characters like ";" or "="; update the code that
builds the cookie (where serializedValue is created and used) to use
encodeURIComponent(serializedValue) before assigning document.cookie, and update
the corresponding getCookie function to decode the stored value with
decodeURIComponent when returning it; ensure you use the same serializedValue
identifier and the getCookie function name so encoding/decoding pairs match.

---

Outside diff comments:
In `@eslint.config.js`:
- Around line 3-5: Replace the legacy eslint-plugin-react setup with the modern
flat-config plugins: install and import "eslint-plugin-react-x" and
"eslint-plugin-react-dom" instead of "eslint-plugin-react", keep
"eslint-plugin-react-hooks" and "eslint-plugin-react-refresh", then update the
flat config to register the new plugins (e.g., the imported symbols replacing
react) and enable the recommended rule sets from "react-x" and "react-dom"
(including React DOM optimization rules); specifically, change the import lines
(current react, reactHooks, reactRefresh) to import reactX and reactDom, add
those plugin references to the exports/config registration, and migrate any
react-specific rule names to the equivalents provided by react-x/react-dom.

---

Nitpick comments:
In `@eslint.config.js`:
- Around line 100-110: The ESLint rule 'no-restricted-syntax' currently blocks
direct fetch and window.fetch but allows globalThis.fetch and self.fetch; update
the rule (the 'no-restricted-syntax' entry) to add selectors that match
MemberExpression calls where the object is globalThis or self (e.g.,
CallExpression[callee.type='MemberExpression'][callee.object.type='Identifier'][callee.object.name='globalThis'][callee.property.type='Identifier'][callee.property.name='fetch']
and the same for 'self') so those forms are also disallowed with the same
message as the existing window.fetch selector.

In `@package.json`:
- Around line 45-46: The devDependencies are not alphabetically ordered:
"@tanstack/eslint-plugin-query" is placed after "eslint-plugin-react-refresh"
which breaks sorting for scoped packages; reorder the entries so that scoped
packages like "@tanstack/eslint-plugin-query" appear in their correct
alphabetical position (near other "@" scoped entries such as
"@vitejs/plugin-react" or above unscoped "eslint-plugin-react-refresh") by
moving the "@tanstack/eslint-plugin-query" line to the proper location in
package.json's devDependencies.

In `@src/pages/Chat/ChatRoomInfo.tsx`:
- Line 242: The onClick currently returns a Promise because it uses "() =>
handleLeaveRoom()", which triggers the no-misused-promises checks; modify the
handler so the click callback is a block-bodied function that explicitly
discards the Promise (e.g., call handleLeaveRoom and void its result or await
inside an async wrapper), preventing a Promise from being returned from the
onClick. Update the JSX where onClick is set and ensure references to
handleLeaveRoom remain unchanged.

In `@src/pages/Manager/ManagedAccount/index.tsx`:
- Line 29: Replace the unsafe cast of location.state to EnableAfterSaveState
with a runtime type guard: implement an isEnableAfterSaveState(value: unknown):
value is EnableAfterSaveState that checks the optional fields you expect, then
set navigationState by testing location.state with that guard (e.g.,
navigationState = isEnableAfterSaveState(location.state) ? location.state :
null) so the narrowing is done safely at runtime instead of using a raw `as`
assertion; reference the symbols navigationState and EnableAfterSaveState and
add the isEnableAfterSaveState helper near this component.

In `@src/types/navigation.ts`:
- Around line 1-8: SmartBackState currently defines backState as a flat object
({ from?: string }) which blocks multi-level back-chain data; change backState
to a recursive type so it can optionally nest another SmartBackState (e.g.,
backState?: SmartBackState | { from?: string } or make backState?:
SmartBackState) by updating the SmartBackState declaration and any consumers
(functions/types that construct or read backState) to accept the recursive
shape, ensuring existing usages that only read from are still compatible.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c6a67cff-854c-4ab7-b6a0-6a0d10b6c9f8

📥 Commits

Reviewing files that changed from the base of the PR and between c7586e4 and 2897e07.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by **
📒 Files selected for processing (37)
  • eslint.config.js
  • package.json
  • src/apis/auth/index.ts
  • src/apis/chat/queries.ts
  • src/apis/client.ts
  • src/apis/club/queries.ts
  • src/apis/notification/index.ts
  • src/components/common/ImageUploader/hooks/useImagePreparation.ts
  • src/components/layout/Header/components/ChatHeader.tsx
  • src/components/notification/InboxNotificationLayer.tsx
  • src/components/notification/hooks/useInboxNotificationStream.ts
  • src/constants/timer.ts
  • src/main.tsx
  • src/pages/Auth/SignUp/components/AgreementArrow.tsx
  • src/pages/Chat/ChatRoomInfo.tsx
  • src/pages/Chat/components/ChatRoomListItem.tsx
  • src/pages/Chat/hooks/useChat.ts
  • src/pages/Chat/hooks/useChatRoomScroll.ts
  • src/pages/Council/CouncilNotice/hooks/useCouncilNoticeDetail.ts
  • src/pages/Home/components/HomeClubSection.tsx
  • src/pages/Home/hooks/useInfiniteClubCarousel.ts
  • src/pages/Manager/ManagedAccount/index.tsx
  • src/pages/Manager/ManagedMemberList/hooks/useRoleManage.ts
  • src/pages/Manager/ManagedMemberList/index.tsx
  • src/pages/Manager/ManagedRecruitmentForm/index.tsx
  • src/pages/Manager/ManagedRecruitmentWrite/index.tsx
  • src/pages/Manager/types.ts
  • src/pages/Notifications/index.tsx
  • src/pages/Timer/hooks/useStudyTimer.ts
  • src/pages/Timer/index.tsx
  • src/pages/User/MyPage/index.tsx
  • src/stores/authStore.ts
  • src/types/navigation.ts
  • src/utils/hooks/useSmartBack.ts
  • src/utils/ts/cookie.ts
  • src/utils/ts/error/apiError.ts
  • src/utils/ts/nativeBridge.ts

Comment thread eslint.config.js
Comment on lines +50 to +57
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false,
},
],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd / && find . -name "eslint.config.js" -o -name "eslint.config.ts" 2>/dev/null | head -5

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 254


🏁 Script executed:

cat -n eslint.config.js | head -80

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 3425


🌐 Web query:

typescript-eslint no-floating-promises ignoreVoid option

💡 Result:

The @typescript-eslint/no-floating-promises rule includes an ignoreVoid option that determines whether to ignore void expressions prefixed to promises. When enabled (true), the rule does not report promises intentionally marked with the void operator, such as void someAsyncFn;. This is the default setting. Key details: - Default: true - Purpose: Allows explicit marking of intentionally unawaited promises using void, as a convenient alternative to ESLint disable comments. - Warning: Using void does not handle promise rejections at runtime; they remain unhandled, similar to disabling the rule. - Compatibility note: If using the no-void rule with allowAsStatement: true, void can be used in statements. - Configuration example: { "@typescript-eslint/no-floating-promises": ["error", { "ignoreVoid": true }] } This option is part of the rule's configuration object, alongside others like ignoreIIFE, checkThenables, allowForKnownSafeCalls, and allowForKnownSafePromises. The official documentation confirms this behavior and provides examples of valid code with { ignoreVoid: true }, such as void returnsPromise; and void Promise.reject('value');.

Citations:


no-floating-promises를 활성화하세요.

현재 설정에서는 bootstrap(); 같은 미처리 Promise가 그대로 통과됩니다. no-void: error와 함께 작동하려면 no-floating-promises를 다시 켜야 합니다.

수정 제안
-      '@typescript-eslint/no-floating-promises': 'off',
+      '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: false }],
📝 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
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false,
},
],
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: false }],
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false,
},
],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` around lines 50 - 57, Enable the
'@typescript-eslint/no-floating-promises' rule by setting it to 'error' in the
ESLint config so that unawaited Promises (e.g., calls like bootstrap();) are
flagged; update the rules block that currently contains
'@typescript-eslint/no-non-null-assertion' and
'@typescript-eslint/no-misused-promises' to include
"@typescript-eslint/no-floating-promises": "error" (ensuring it aligns with the
existing 'no-void'/'no-void: error' usage if present).

Comment thread src/main.tsx
onClose={roleManage.close}
onMemberClick={roleManage.handleMemberClick}
onSubmit={() => void roleManage.handleSubmit()}
onSubmit={() => roleManage.handleSubmit()}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: onSubmit prop contract and async handleSubmit return verification.
rg -n -C3 'onSubmit:\s*\(\)\s*=>\s*void|const handleSubmit\s*=\s*async|onSubmit=\{\(\)\s*=>\s*roleManage\.handleSubmit\(\)\}' src/pages/Manager/ManagedMemberList

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 3462


🏁 Script executed:

# Get full handleSubmit implementation
sed -n '97,120p' src/pages/Manager/ManagedMemberList/hooks/useRoleManage.ts

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 841


🏁 Script executed:

# Check how other onSubmit handlers are implemented in this file
grep -n "onSubmit=" src/pages/Manager/ManagedMemberList/index.tsx

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 222


🏁 Script executed:

# Check if there are other async functions passed to void callbacks
rg -n "onSubmit.*\(\)\s*=>\s*\{|handleSubmit|handleAddMember|handleImport" src/pages/Manager/ManagedMemberList --max-count 20

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 1231


🏁 Script executed:

# Get full useAddMember.ts handleSubmit to compare with async version
sed -n '18,35p' src/pages/Manager/ManagedMemberList/hooks/useAddMember.ts

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 452


🏁 Script executed:

# Get full useMemberSheetImport.ts handleSubmit
sed -n '70,90p' src/pages/Manager/ManagedMemberList/hooks/useMemberSheetImport.ts

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 617


🏁 Script executed:

# Get the complete async handleSubmit from useRoleManage to see all branches
sed -n '97,160p' src/pages/Manager/ManagedMemberList/hooks/useRoleManage.ts

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 2085


onSubmit 콜백의 타입 계약을 맞춰주세요.

RoleManageModalonSubmit() => void이지만, 현재는 async 함수인 roleManage.handleSubmit()이 반환하는 Promise<void>를 그대로 전달합니다. TypeScript 타입 검사 및 linting에서 문제가 될 수 있습니다.

수정 방법
-        onSubmit={() => roleManage.handleSubmit()}
+        onSubmit={() => {
+          void roleManage.handleSubmit();
+        }}

또는 catch 처리:

-        onSubmit={() => roleManage.handleSubmit()}
+        onSubmit={() => {
+          roleManage.handleSubmit().catch(() => {});
+        }}
📝 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
onSubmit={() => roleManage.handleSubmit()}
onSubmit={() => {
void roleManage.handleSubmit();
}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Manager/ManagedMemberList/index.tsx` at line 163, The onSubmit prop
expects a synchronous () => void but you are passing the async Promise-returning
roleManage.handleSubmit() directly; change the prop to pass a non-async wrapper
that calls roleManage.handleSubmit() and handles the Promise (e.g., call it and
attach a .catch to log/handle errors or use void to ignore the returned Promise)
so the type becomes () => void; update the JSX where RoleManageModal is used
(the onSubmit prop) to call roleManage.handleSubmit() inside a plain arrow
function and ensure any errors are caught.

Comment on lines 106 to 108
} catch {
void queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

invalidateQueries의 rejection이 무시됩니다.

void를 제거하면서 queryClient.invalidateQueries(...)가 반환하는 Promise가 그대로 catch 블록에 남게 됩니다. no-floating-promises가 활성화되어 있다면 린트에서 걸릴 수 있고, 실패 시 무응답으로 넘어가 디버깅이 어렵습니다. 명시적으로 await하거나 실패를 무시할 의도라면 .catch(() => {})를 붙이는 편이 의도가 분명합니다.

♻️ 제안
-    } catch {
-      queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
-    }
+    } catch {
+      await queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
+    }

동일 패턴이 src/components/notification/InboxNotificationLayer.tsx에도 있어 함께 일관되게 적용하시면 좋습니다.

📝 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
} catch {
void queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
}
} catch {
await queryClient.invalidateQueries({ queryKey: notificationQueryKeys.inbox.all() });
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Notifications/index.tsx` around lines 106 - 108, The catch block
currently calls queryClient.invalidateQueries(notificationQueryKeys.inbox.all())
without awaiting or handling its returned Promise, which leaves a floating
promise and can trigger no-floating-promises lint errors or silent failures;
update the catch to either await queryClient.invalidateQueries(...) (i.e., make
the surrounding function async if needed) or explicitly swallow errors with
queryClient.invalidateQueries(...).catch(() => {}) to make intent clear, and
apply the same change to the identical pattern in
src/components/notification/InboxNotificationLayer.tsx so both uses of
queryClient.invalidateQueries and notificationQueryKeys.inbox.all() are handled
consistently.

Comment thread src/utils/ts/cookie.ts Outdated
@ff1451 ff1451 merged commit c5ccbc9 into develop Apr 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚙️ Setting 개발 환경 세팅

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[chore] ESLint 규칙 추가 및 수정

1 participant