Skip to content

๐ŸŸก[P2] fix(frontend): providers/Settings.tsx missing 'use client' directive despite using hooks + window/documentย #83

Description

@teddylee777

์ปจํ…์ŠคํŠธ ๋ธ”๋ก

Key Value
Category frontend
Checklist ISS-UI-R9 โ€” Use of window/document/localStorage without "use client" guard or SSR safety
Priority P2 ๐ŸŸก
Scan Date 2026-04-16
Flagged By @code-review

์š”์•ฝ

  • WHAT: frontend/src/providers/Settings.tsx๊ฐ€ useState, useEffect, document.documentElement, window.matchMedia๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ \"use client\" ๋””๋ ‰ํ‹ฐ๋ธŒ๊ฐ€ ์—†์Œ
  • WHY: ํ˜„์žฌ๋Š” MainLayoutClient(client component)์—์„œ๋งŒ import๋˜์–ด ๋™์ž‘ํ•˜์ง€๋งŒ, ํ–ฅํ›„ ๋‹ค๋ฅธ server component์—์„œ import ์‹œ SSR ํฌ๋ž˜์‹œ. Next.js 15 ์ปจ๋ฒค์…˜ ์œ„๋ฐ˜
  • WHERE: frontend/src/providers/Settings.tsx:1 (ํŒŒ์ผ ์ฒซ ์ค„์— \"use client\" ๋ˆ„๋ฝ)
  • SEVERITY: MEDIUM โ€” ์ž ์žฌ์  SSR ํฌ๋ž˜์‹œ + ์ฝ”๋“œ ์ปจ๋ฒค์…˜ ์œ„๋ฐ˜

Evidence

# File Line Finding Flagged By Confidence
1 frontend/src/providers/Settings.tsx 1 ํŒŒ์ผ ์ฒซ ์ค„ \"use client\" ๋””๋ ‰ํ‹ฐ๋ธŒ ๋ˆ„๋ฝ @code-review High
2 frontend/src/providers/Settings.tsx 109, 138, 151 document.documentElement.classList, window.matchMedia ์‚ฌ์šฉ โ€” client-only API @code-review High
3 frontend/src/providers/Settings.tsx 39 typeof window === \"undefined\" ์ฒดํฌ๋Š” ์ผ๋ถ€ ํ•จ์ˆ˜์—๋งŒ ์กด์žฌ, ๋ชจ๋“  hook callback์— ์ ์šฉ ์•ˆ๋จ @code-review Medium

์˜ํ–ฅ ๋ถ„์„

์˜ํ–ฅ ๋ฒ”์œ„

  • ํ–ฅํ›„ Settings provider๋ฅผ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ importํ•  ๋•Œ
  • Next.js 15์˜ ๋” ์—„๊ฒฉํ•œ RSC(React Server Components) ๊ฒ€์ฆ

์žฅ์•  ์‹œ๋‚˜๋ฆฌ์˜ค

  1. ๊ฐœ๋ฐœ์ž๊ฐ€ Settings provider๋ฅผ server component์ธ ์ƒˆ layout์—์„œ import
  2. SSR ์‹œ์ ์— document is not defined ์—๋Ÿฌ โ†’ ๋นŒ๋“œ/๋Ÿฐํƒ€์ž„ ํฌ๋ž˜์‹œ
  3. ๋˜๋Š” React 19 strict mode์—์„œ hooks ํ˜ธ์ถœ ์œ„์น˜ ๊ฒ€์ฆ ์‹คํŒจ

๊ธด๊ธ‰๋„

  • ์ฆ‰๊ฐ์  ์žฅ์•  ์—†์œผ๋‚˜ ์ปจ๋ฒค์…˜ ์œ„๋ฐ˜์€ ๋””๋ฒ„๊น… ์–ด๋ ค์šด ๋ฏธ๋ž˜ ๋ฒ„๊ทธ ์œ ๋ฐœ
  • ๋ช…์‹œ์  ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” ๋ฏธ๋ž˜ ์œ ์ง€๋ณด์ˆ˜์ž์—๊ฒŒ ์˜๋„ ์ „๋‹ฌ

์ œ์•ˆ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

์ ‘๊ทผ ๋ฐฉ๋ฒ•

ํŒŒ์ผ ์ตœ์ƒ๋‹จ์— ๋””๋ ‰ํ‹ฐ๋ธŒ ์ถ”๊ฐ€:

// frontend/src/providers/Settings.tsx
\"use client\";

import { ... } from \"...\";
// ... ๊ธฐ์กด ์ฝ”๋“œ

์ถ”๊ฐ€๋กœ ์ „ frontend/src/providers/ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ grepํ•˜์—ฌ ๋™์ผ ๋ˆ„๋ฝ ๊ฒ€์‚ฌ:

for f in frontend/src/providers/*.tsx frontend/src/providers/*.ts; do
  head -1 \"$f\" | grep -q '\"use client\"' || echo \"MISSING: $f\"
done

ESLint ๊ทœ์น™์œผ๋กœ ๊ฐ•์ œ:

// frontend/eslint.config.js
\"react/no-direct-document\": \"error\", // ๋˜๋Š” next.js์˜ client/server boundary ๊ทœ์น™ ํ™œ์šฉ

๋Œ€์•ˆ

  • module-level guard: if (typeof window === \"undefined\") return null ์ถ”๊ฐ€ โ†’ ๋™์ž‘์€ ํ•˜์ง€๋งŒ ๋””๋ ‰ํ‹ฐ๋ธŒ๊ฐ€ ๋” ๋ช…ํ™•
  • Server Component๋กœ ๋ฆฌํŒฉํ„ฐ: hooks ์‚ฌ์šฉ์œผ๋กœ ์ธํ•ด ๋ถˆ๊ฐ€๋Šฅ

์ˆ˜์šฉ ๊ธฐ์ค€

  • frontend/src/providers/Settings.tsx 1๋ฒˆ ์ค„์— \"use client\" ์ถ”๊ฐ€
  • frontend/src/providers/ ์ „์ฒด grep์œผ๋กœ ๋ˆ„๋ฝ 0๊ฑด ํ™•์ธ
  • cd frontend && pnpm build ํ†ต๊ณผ
  • ํ…Œ์ŠคํŠธ ์ปค๋งจ๋“œ: cd frontend && pnpm lint && pnpm tsc --noEmit

์ฐธ์กฐ

  • ๊ด€๋ จ ํŒŒ์ผ: frontend/src/providers/Settings.tsx
  • Checklist ํ•ญ๋ชฉ: ISS-UI-R9
  • Next.js: 'use client' directive
  • ๊ด€๋ จ ์ด์Šˆ: ์—†์Œ

์žฌํ˜„ ๋ฐฉ๋ฒ•

์‚ฌ์ „ ์กฐ๊ฑด

  • dev/build ํ™˜๊ฒฝ

๋‹จ๊ณ„

  1. head -1 frontend/src/providers/Settings.tsx๋กœ ์ฒซ ์ค„ ํ™•์ธ
  2. import ๊ฒ€์ƒ‰: grep -r \"from .*providers/Settings\" frontend/src/
  3. importํ•œ ๋ชจ๋“  ๊ณณ์ด client component์ธ์ง€ ํ™•์ธ

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ

\"use client\"๊ฐ€ ์ฒซ ์ค„

์‹ค์ œ ๊ฒฐ๊ณผ

import ๋ฌธ๋ถ€ํ„ฐ ์‹œ์ž‘ โ€” ๋””๋ ‰ํ‹ฐ๋ธŒ ์—†์Œ

๊ด€๋ จ ์ฝ”๋“œ ์ปจํ…์ŠคํŠธ

File Role Relevance
frontend/src/providers/Settings.tsx Settings context provider ์ˆ˜์ • ๋Œ€์ƒ
frontend/src/shared/components/layout/MainLayoutClient.tsx Settings provider import ์œ„์น˜ ํ˜„์žฌ client tree ๋ณด์žฅ

Detected by oh-my-braincrew `omb:issue` scan
Category: frontend | Scan date: 2026-04-16
`omb-issue-scan category=frontend checklist=ISS-UI-R9`

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:frontendfrontend domain scanomb-issue-scanDetected by omb:issue scanpriority:p2Medium โ€” fix if time permits

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions