[FE-27] 웹 다크 모드 토글 배선 (W-TH)

작업 내용 (설계 의도)

변경 사항

웹 운영 포털은 app/globals.css.dark 토큰이 완비돼 있으나 토글이 배선돼 있지 않아 사실상 라이트만 사용 가능하다(라이트/다크 의무 미충족). .dark 클래스 토글을 최소 배선한다.

  • web/components/ui/ThemeToggle.tsx 신규 — document.documentElement.classList dark 토글, localStorage('theme') 영속, 시스템 기본(prefers-color-scheme) 초기값.
  • web/app/layout.tsx에 초기 테마 적용 인라인 스크립트(FOUC 방지) + 헤더/네비에 ThemeToggle 배치.
  • next-themes 미도입(레포 관례 — 최소 배선). 전역 UI 상태는 localStorage + classList만 사용.

이 티켓 완료 후에야 신규 웹 화면(운영시간·시설상품·슬롯)이 두 모드 모두 확인 가능 → 선행 배치. 롤백: ThemeToggle 미노출 + 스크립트 제거(토큰은 그대로).

의존

  • 없음 (wave 1, 선행)

다이어그램

클래스 의존

flowchart LR
    Toggle["components/ui/ThemeToggle.tsx"] --> Layout["app/layout.tsx"]
    Layout --> Docroot["document.documentElement.classList dark"]

테스트 케이스

  • 토글 클릭 시 <html>dark 클래스가 추가/제거된다
  • 선택한 모드가 localStorage에 저장되고 재마운트 시 복원된다
  • localStorage 미설정 시 prefers-color-scheme: dark를 초기값으로 반영한다
  • 다크 상태에서 시맨틱 클래스(bg-background)가 다크 토큰 값으로 렌더된다