์ปจํ
์คํธ ๋ธ๋ก
| Key |
Value |
| Category |
frontend |
| Checklist |
ISS-UI-R2 โ Uncaught promise rejections in event handlers |
| Priority |
P1 ๐ |
| Scan Date |
2026-04-16 |
| Flagged By |
@code-review |
์์ฝ
- WHAT:
handleSwitchConnection์ async ํจ์๋ก์ onClick/onKeyDown์ ๋ฐ๋ก ์ ๋ฌ๋จ. ๋ด๋ถ์์ ํธ์ถํ๋ switchConnection()์ด server action updateConnectionAction์ awaitํ์ง๋ง try/catch ์์
- WHY: ๋คํธ์ํฌ ์ฅ์ ๋๋ ์๋ฒ ์ก์
์คํจ ์ promise rejection์ด globalUnhandledRejection์ผ๋ก ๋น ์ง. UI๋ ์๋ฌด ํผ๋๋ฐฑ ์์ด ๋ฉ์ถ ๋ฏ ๋ณด์ด๊ณ , ์ฌ์ฉ์๋ ๊ณ์ ํด๋ฆญ ์๋ํ๋ฉฐ UX ์
ํ
- WHERE:
frontend/src/shared/components/settings/ConnectionList.tsx:106-121, :242 (ํธ๋ค๋ฌ ๋ฑ๋ก)
- SEVERITY: HIGH โ ์ฌ์ฉ์๊ฐ ์ฅ์ ๋ฅผ ์ธ์งํ์ง ๋ชปํ๊ณ ๋ฐ๋ณต ํด๋ฆญ โ ๋ฐ์ดํฐ ๋ถ์ผ์น ๊ฐ๋ฅ
Evidence
| # |
File |
Line |
Finding |
Flagged By |
Confidence |
| 1 |
frontend/src/shared/components/settings/ConnectionList.tsx |
106-121 |
handleSwitchConnection = async (connection) => { await switchConnection(connection.id) } โ try/catch ์์ |
@code-review |
High |
| 2 |
frontend/src/shared/components/settings/ConnectionList.tsx |
242 |
onClick={() => handleSwitchConnection(connection)} โ async ํจ์๋ฅผ ๋ฐ๋ก ํธ๋ค๋ฌ๋ก ์ ๋ฌ, rejection ๋ฌด์ |
@code-review |
High |
| 3 |
frontend/src/providers/AssistantConfig.tsx (์ฐธ๊ณ ) |
โ |
์ ์ฌ ํจํด ๋ค๋ฅธ ๊ณณ์๋ ์กด์ฌ โ ํ๋ก์ ํธ ์ ๋ฐ async ์๋ฌ ํธ๋ค๋ง ๋ถ์กฑ |
@code-review |
Medium |
์ํฅ ๋ถ์
์ํฅ ๋ฒ์
- ์ฐ๊ฒฐ ์ ํ ์๋ํ๋ ๋ชจ๋ ์ฌ์ฉ์
- LangGraph ์๋ฒ ์ฅ์ / ๋คํธ์ํฌ ๋ถ์์ ํ๊ฒฝ
์ฅ์ ์๋๋ฆฌ์ค
- ์ฌ์ฉ์๊ฐ Connection A์์ B๋ก ์ ํ ํด๋ฆญ
- ๋คํธ์ํฌ ์ผ์ ์ฅ์ ๋ก
updateConnectionAction throw
- UI๋ ์๋ฌด ํ์ ์์ด ๊ธฐ์กด Connection A ์ํ ์ ์ง
- ์ฌ์ฉ์๊ฐ B๋ก ์ ํ๋ ์ค ์๊ณ ์ฑํ
โ ์๋ชป๋ assistant์ ๋ฉ์์ง ์ ์ก
- ๋๋ ์ฌ์ฉ์๊ฐ ๋ฐ๋ณต ํด๋ฆญ โ ์ฌ๋ฌ transition ๋ ์ด์ค ์ปจ๋์
๊ธด๊ธ๋
- ๋คํธ์ํฌ ์ค๋ฅ๋ ์์ ๋ฐ์ ๊ฐ๋ฅํ ์ผ๋ฐ์ ์๋๋ฆฌ์ค
- ์ฌ์ผ๋ฐํธ ์คํจ๋ ๋๋ฒ๊น
์ด๋ ค์
์ ์ ํด๊ฒฐ ๋ฐฉ์
์ ๊ทผ ๋ฐฉ๋ฒ
handleSwitchConnection์ try/catch + ์ฌ์ฉ์ ํผ๋๋ฐฑ ์ถ๊ฐ:
const handleSwitchConnection = async (connection: Connection) => {
setIsSwitching(connection.id);
try {
await switchConnection(connection.id);
toast.success(\"Connection switched\");
} catch (error) {
console.error(\"[ConnectionList] switch failed\", error);
toast.error(\"Failed to switch connection. Please try again.\");
} finally {
setIsSwitching(null);
}
};
์ถ๊ฐ๋ก onClick ํธ๋ค๋ฌ ๋ด๋ถ์์ fire-and-forget์ ๋ช
์์ ์ผ๋ก:
onClick={() => { void handleSwitchConnection(connection); }}
์ ํ๋ก์ ํธ ๊ณตํต ํจํด์ผ๋ก useAsyncHandler ๋๋ safeAsync ์ ํธ์ ๋์
ํด ์ผ๊ด์ฑ ํ๋ณด ๊ณ ๋ ค.
๋์
- window.onunhandledrejection ๊ธ๋ก๋ฒ ์ฒ๋ฆฌ: ์ตํ์ ๋ณด๋ฃจ์ง๋ง context ์ ๋ณด ๋ถ์กฑ
- sonner/react-hot-toast ๊ฐ์ ์ ์ญ ์๋ฌ ํ ์คํธ: ์ด๋ฏธ ํ๋ก์ ํธ์ toast ์์คํ
์ด ์๋ค๋ฉด ํ์ฉ
์์ฉ ๊ธฐ์ค
์ฐธ์กฐ
- ๊ด๋ จ ํ์ผ:
frontend/src/shared/components/settings/ConnectionList.tsx
- Checklist ํญ๋ชฉ: ISS-UI-R2
- ๊ด๋ จ ์ด์: ์์
์ฌํ ๋ฐฉ๋ฒ
์ฌ์ ์กฐ๊ฑด
- dev ์๋ฒ ์คํ, ์ฐ๊ฒฐ 2๊ฐ ์ด์ ์ค์ ๋จ
๋จ๊ณ
- ๋คํธ์ํฌ throttling์ "offline"์ผ๋ก ์ค์ (DevTools > Network)
- ๋ค๋ฅธ ์ฐ๊ฒฐ๋ก ์ ํ ํด๋ฆญ
- ์๋ต ๊ด์ฐฐ
๊ธฐ๋ ๊ฒฐ๊ณผ
์๋ฌ ํ ์คํธ/๋ฉ์์ง ํ์ + ๋ฒํผ ๋ณต๊ตฌ
์ค์ ๊ฒฐ๊ณผ
UI ์ ์ง, ์๋ฌ ๋ฉ์์ง ์์, DevTools Console์ unhandled rejection
๊ด๋ จ ์ฝ๋ ์ปจํ
์คํธ
| File |
Role |
Relevance |
frontend/src/shared/components/settings/ConnectionList.tsx |
์ฐ๊ฒฐ ๊ด๋ฆฌ UI |
์์ ๋์ |
frontend/src/app/actions.ts |
updateConnectionAction server action |
์๋ฌ throw ์ฃผ์ฒด |
frontend/src/shared/hooks/useToast.ts ๋๋ ์ ์ฌ |
toast ์์คํ
|
ํ์ฉ |
Detected by oh-my-braincrew `omb:issue` scan
Category: frontend | Scan date: 2026-04-16
`omb-issue-scan category=frontend checklist=ISS-UI-R2`
์ปจํ ์คํธ ๋ธ๋ก
ISS-UI-R2โ Uncaught promise rejections in event handlers์์ฝ
handleSwitchConnection์asyncํจ์๋ก์onClick/onKeyDown์ ๋ฐ๋ก ์ ๋ฌ๋จ. ๋ด๋ถ์์ ํธ์ถํ๋switchConnection()์ด server actionupdateConnectionAction์ awaitํ์ง๋ง try/catch ์์frontend/src/shared/components/settings/ConnectionList.tsx:106-121,:242(ํธ๋ค๋ฌ ๋ฑ๋ก)Evidence
frontend/src/shared/components/settings/ConnectionList.tsxhandleSwitchConnection = async (connection) => { await switchConnection(connection.id) }โ try/catch ์์frontend/src/shared/components/settings/ConnectionList.tsxonClick={() => handleSwitchConnection(connection)}โ async ํจ์๋ฅผ ๋ฐ๋ก ํธ๋ค๋ฌ๋ก ์ ๋ฌ, rejection ๋ฌด์frontend/src/providers/AssistantConfig.tsx(์ฐธ๊ณ )์ํฅ ๋ถ์
์ํฅ ๋ฒ์
์ฅ์ ์๋๋ฆฌ์ค
updateConnectionActionthrow๊ธด๊ธ๋
์ ์ ํด๊ฒฐ ๋ฐฉ์
์ ๊ทผ ๋ฐฉ๋ฒ
handleSwitchConnection์ try/catch + ์ฌ์ฉ์ ํผ๋๋ฐฑ ์ถ๊ฐ:์ถ๊ฐ๋ก onClick ํธ๋ค๋ฌ ๋ด๋ถ์์ fire-and-forget์ ๋ช ์์ ์ผ๋ก:
์ ํ๋ก์ ํธ ๊ณตํต ํจํด์ผ๋ก
useAsyncHandler๋๋safeAsync์ ํธ์ ๋์ ํด ์ผ๊ด์ฑ ํ๋ณด ๊ณ ๋ ค.๋์
์์ฉ ๊ธฐ์ค
handleSwitchConnection์ try/catch ์ถ๊ฐisSwitchingstate๋ก ๋ฒํผ disabled ์ฒ๋ฆฌ (์ค๋ณต ํด๋ฆญ ๋ฐฉ์ง)cd frontend && pnpm test์ฐธ์กฐ
frontend/src/shared/components/settings/ConnectionList.tsx์ฌํ ๋ฐฉ๋ฒ
์ฌ์ ์กฐ๊ฑด
๋จ๊ณ
๊ธฐ๋ ๊ฒฐ๊ณผ
์๋ฌ ํ ์คํธ/๋ฉ์์ง ํ์ + ๋ฒํผ ๋ณต๊ตฌ
์ค์ ๊ฒฐ๊ณผ
UI ์ ์ง, ์๋ฌ ๋ฉ์์ง ์์, DevTools Console์ unhandled rejection
๊ด๋ จ ์ฝ๋ ์ปจํ ์คํธ
frontend/src/shared/components/settings/ConnectionList.tsxfrontend/src/app/actions.tsupdateConnectionActionserver actionfrontend/src/shared/hooks/useToast.ts๋๋ ์ ์ฌ