diff --git a/CLAUDE.md b/CLAUDE.md
index e5cb5a5..f3e975e 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -161,15 +161,27 @@ src/app/(page)/*/*.store.ts
`features` 폴더는 사용하지 않는다.
+### MUI 사용 허용 범위
+
+```txt
+허용:
+- 달력 / 날짜 선택 UI: src/components/calendar/ 내 래핑 컴포넌트
+- 피드백 UI (Toast/Snackbar): src/components/feedback/ 내 래핑 컴포넌트
+- 아이콘: @mui/icons-material — 감정일기(diary) 기능 제외 전체 허용
+
+금지:
+- 감정일기(diary) 기능 내 아이콘은 lucide-react 사용 유지
+- 전체 디자인 시스템을 MUI 기반으로 전환하지 않는다.
+- 여러 페이지 / 도메인에서 MUI 컴포넌트를 직접 import하지 않는다.
+- MUI ThemeProvider를 앱 전역에 적용하지 않는다.
+- 전체 스타일 기준은 SCSS / SCSS Module을 유지한다.
+```
+
### Calendar UI Rules
```txt
- 달력 UI는 MUI X Date Pickers 기반으로 구현한다.
-- MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다. 전체 디자인 시스템에 적용하지 않는다.
-- 전체 스타일 기준은 SCSS / SCSS Module을 유지한다.
- MUI 컴포넌트는 src/components/calendar/ 내 래핑 컴포넌트를 통해서만 사용한다.
-- 여러 페이지 / 도메인에서 MUI 컴포넌트를 직접 import하지 않는다.
-- 아이콘은 기존 lucide-react를 우선 사용한다.
- 달력 라이브러리는 래핑 컴포넌트 구조로 교체 가능성을 확보한다.
```
diff --git a/docs/PROJECT_DECISIONS.md b/docs/PROJECT_DECISIONS.md
index 1c8951e..a64d2e3 100644
--- a/docs/PROJECT_DECISIONS.md
+++ b/docs/PROJECT_DECISIONS.md
@@ -227,6 +227,6 @@ SUPABASE_SERVICE_ROLE_KEY는 서버 전용
- 전체 디자인 시스템은 SCSS / SCSS Module을 유지한다.
- MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다.
- MUI 컴포넌트는 src/components/calendar/ 내 래핑 컴포넌트를 통해서만 사용한다.
-- 아이콘은 기존 lucide-react를 우선 사용한다.
+- 아이콘은 @mui/icons-material을 사용한다. 단, 감정일기(diary) 기능 내 아이콘은 lucide-react를 유지한다.
- 달력 라이브러리는 래핑 컴포넌트 구조로 교체 가능성을 확보한다.
```
diff --git a/docs/TECH_STACK.md b/docs/TECH_STACK.md
index cc4a7b7..6a99164 100644
--- a/docs/TECH_STACK.md
+++ b/docs/TECH_STACK.md
@@ -39,8 +39,7 @@ dayjs
- 전체 디자인 시스템을 MUI 기반으로 전환하지 않는다.
- 기존 스타일 기준은 SCSS / SCSS Module을 유지한다.
-- 아이콘은 기존 `lucide-react` 사용을 우선한다.
-- `@mui/icons-material`은 현재 필수 설치 대상이 아니다.
+- 아이콘은 `@mui/icons-material`을 사용한다. 단, 감정일기(diary) 기능 내 아이콘은 `lucide-react`를 유지한다.
- 달력 라이브러리는 추후 변경 가능하다. 변경 가능성을 확보하기 위해 MUI 의존성은 Calendar 전용 컴포넌트와 날짜 유틸 영역에만 제한한다.
---
@@ -76,7 +75,8 @@ npm install
| `react-hook-form` | ^7.54.1 | 폼 상태 관리 |
| `@hookform/resolvers` | ^3.9.1 | React Hook Form + Zod 연동 |
| `zod` | ^3.23.8 | 스키마 유효성 검사 |
-| `lucide-react` | ^0.468.0 | 아이콘 라이브러리 |
+| `lucide-react` | ^0.468.0 | 아이콘 라이브러리 (감정일기 기능 전용 — 그 외는 @mui/icons-material 사용) |
+| `@mui/icons-material` | latest | MUI 아이콘 (감정일기 기능 제외 전체 사용) |
| `recharts` | ^3.0.0 | 차트 라이브러리 (통계 시각화) |
| `html-to-image` | ^1.11.11 | 판결 결과 카드 이미지 추출 |
| `sass` | ^1.83.0 | SCSS / SCSS Module 스타일링 |
diff --git a/docs/guides/CODING_CONVENTION.md b/docs/guides/CODING_CONVENTION.md
index 183d803..44dbf06 100644
--- a/docs/guides/CODING_CONVENTION.md
+++ b/docs/guides/CODING_CONVENTION.md
@@ -90,16 +90,18 @@ API 응답에 불필요한 민감 정보 포함 금지
## 7. MUI 사용 기준
-MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다.
+MUI는 아래 허용 범위 내에서만 사용한다.
```txt
허용 범위:
- src/components/calendar/ 내 래핑 컴포넌트에서만 MUI import 허용
+ src/components/calendar/ → MUI X Date Pickers (달력 / 날짜 선택 UI)
+ src/components/feedback/ → MUI Snackbar 등 (Toast 피드백 UI)
+ @mui/icons-material → 감정일기(diary) 기능 제외 전체 허용
금지 사항:
+ - 감정일기(diary) 기능 내 아이콘은 lucide-react 사용 유지
- 전체 디자인 시스템을 MUI 기반으로 전환하지 않는다
- 여러 페이지 / 도메인에서 MUI 컴포넌트를 직접 import하지 않는다
- - @mui/icons-material 사용 금지 (아이콘은 lucide-react 사용)
- MUI ThemeProvider를 앱 전역에 적용하지 않는다
```
@@ -114,7 +116,7 @@ MUI는 달력 / 날짜 선택 UI 전용으로만 사용한다.
래핑 컴포넌트 원칙:
```txt
-- 달력 UI는 src/components/calendar/ 내 래핑 컴포넌트로 제공한다
+- MUI 컴포넌트는 각 허용 폴더 내 래핑 컴포넌트를 통해서만 사용한다
- 래핑 컴포넌트를 통해 라이브러리 교체 가능성을 유지한다
- 래핑 컴포넌트 외부에서는 MUI 직접 의존을 갖지 않는다
```
diff --git a/package-lock.json b/package-lock.json
index a6b3aa8..271029e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"@emotion/styled": "^11.14.1",
"@google/generative-ai": "^0.21.0",
"@hookform/resolvers": "^3.9.1",
+ "@mui/icons-material": "^9.1.1",
"@mui/material": "^9.1.1",
"@mui/x-date-pickers": "^9.5.0",
"@prisma/client": "^6.0.0",
@@ -181,6 +182,29 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@emnapi/core": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
+ "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.2",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
+ "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@emnapi/wasi-threads": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
@@ -188,6 +212,7 @@
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"tslib": "^2.4.0"
}
@@ -250,7 +275,6 @@
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@@ -294,7 +318,6 @@
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@@ -1079,6 +1102,32 @@
"url": "https://opencollective.com/mui-org"
}
},
+ "node_modules/@mui/icons-material": {
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-9.1.1.tgz",
+ "integrity": "sha512-OXhm9DajemStb58AumM06DuPhHTa3XD36TFD4yf6WtJyNRO5DfEZbbnHlBg/US2Y2oOXwM/XurMTBOD6L/YYZw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.29.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@mui/material": "^9.1.1",
+ "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@mui/material": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-9.1.1.tgz",
@@ -1200,7 +1249,6 @@
"resolved": "https://registry.npmjs.org/@mui/system/-/system-9.1.1.tgz",
"integrity": "sha512-q+aqNa58QZUwmmyUvJKKrStrej+4BcWFw4M0Ug+zRylPIQgR64cqvBnE3QTfLZm4OXulydp8Hl3zwKxMayrdsA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.29.2",
"@mui/private-theming": "^9.1.1",
@@ -2292,7 +2340,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
"integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -2367,7 +2414,6 @@
"integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.61.0",
"@typescript-eslint/types": "8.61.0",
@@ -2982,7 +3028,6 @@
"integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3989,8 +4034,7 @@
"version": "1.11.21",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz",
"integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/debug": {
"version": "4.4.3",
@@ -4457,7 +4501,6 @@
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -4631,7 +4674,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -6128,7 +6170,6 @@
"integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
"devOptional": true,
"license": "MIT",
- "peer": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
@@ -6696,7 +6737,6 @@
"resolved": "https://registry.npmjs.org/next/-/next-15.5.19.tgz",
"integrity": "sha512-xNOW6tYshGX1/Oi3F8uuk4gpDeWsSUE/1Z0G5uUMekIxaQ0xc03UXd9II0VQHYMWviMeA0OHpJFAKsHf8bTYVg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@next/env": "15.5.19",
"@swc/helpers": "0.5.15",
@@ -7303,7 +7343,6 @@
"resolved": "https://registry.npmjs.org/preact/-/preact-10.29.2.tgz",
"integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==",
"license": "MIT",
- "peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
@@ -7366,7 +7405,6 @@
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
- "peer": true,
"dependencies": {
"@prisma/config": "6.19.3",
"@prisma/engines": "6.19.3"
@@ -7517,7 +7555,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz",
"integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -7527,7 +7564,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz",
"integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -7540,7 +7576,6 @@
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.79.0.tgz",
"integrity": "sha512-mhYp/MTmXvzYX6AJcJVko0rktoIhhmRnEouObj4wF5i/tCttgJvnp1+9wRkpITZjDTqpo4IOSJqu0dBlPlV/Lw==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18.0.0"
},
@@ -7556,15 +7591,13 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/react-redux": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz",
"integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
@@ -7647,8 +7680,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/redux-thunk": {
"version": "3.1.0",
@@ -7885,7 +7917,6 @@
"resolved": "https://registry.npmjs.org/sass/-/sass-1.101.0.tgz",
"integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"chokidar": "^5.0.0",
"immutable": "^5.1.5",
@@ -8562,7 +8593,6 @@
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -8736,7 +8766,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/package.json b/package.json
index 250db8e..7836406 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@emotion/styled": "^11.14.1",
"@google/generative-ai": "^0.21.0",
"@hookform/resolvers": "^3.9.1",
+ "@mui/icons-material": "^9.1.1",
"@mui/material": "^9.1.1",
"@mui/x-date-pickers": "^9.5.0",
"@prisma/client": "^6.0.0",
diff --git a/src/components/feedback/Toast.module.scss b/src/components/feedback/Toast.module.scss
index 65105f8..44a3e4b 100644
--- a/src/components/feedback/Toast.module.scss
+++ b/src/components/feedback/Toast.module.scss
@@ -2,12 +2,8 @@
@use '../../styles/abstracts/functions' as fn;
.toast {
- position: fixed;
- top: fn.r(20);
- left: 50%;
- transform: translateX(-50%);
- z-index: 9999;
- width: calc(100% - fn.r(32));
+ width: calc(100vw - fn.r(32));
+ max-width: calc(v.$container-max-width - fn.r(32));
padding: fn.r(14) fn.r(20);
background-color: v.$color-black-600;
color: var(--text-inverse);
@@ -17,11 +13,6 @@
font-weight: v.$font-weight-medium;
line-height: v.$line-height-body-s;
text-align: center;
- pointer-events: none;
word-break: keep-all;
overflow-wrap: break-word;
-
- &--hidden {
- display: none;
- }
}
diff --git a/src/components/feedback/Toast.tsx b/src/components/feedback/Toast.tsx
index c236dd0..a386434 100644
--- a/src/components/feedback/Toast.tsx
+++ b/src/components/feedback/Toast.tsx
@@ -1,18 +1,22 @@
'use client';
+import Snackbar from '@mui/material/Snackbar';
import { useToastStore } from '@/stores/toastStore';
import styles from './Toast.module.scss';
export default function Toast() {
- const { message, isVisible } = useToastStore();
+ const { message, isVisible, hide } = useToastStore();
return (
-
- {message}
-
+
+ {message}
+
+
);
}
diff --git a/src/components/layout/BottomNavigation.tsx b/src/components/layout/BottomNavigation.tsx
index f750dd4..237637c 100644
--- a/src/components/layout/BottomNavigation.tsx
+++ b/src/components/layout/BottomNavigation.tsx
@@ -2,14 +2,17 @@
import Link from 'next/link';
import { usePathname } from 'next/navigation';
-import { Home, BookOpenText, CalendarDays, User } from 'lucide-react';
+import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
+import GavelRoundedIcon from '@mui/icons-material/GavelRounded';
+import CalendarMonthRoundedIcon from '@mui/icons-material/CalendarMonthRounded';
+import PersonRoundedIcon from '@mui/icons-material/PersonRounded';
import styles from './BottomNavigation.module.scss';
const NAV_ITEMS = [
- { href: '/home', label: '홈', icon: Home },
- { href: '/records', label: '사건기록', icon: BookOpenText },
- { href: '/diary', label: '일기', icon: CalendarDays },
- { href: '/mypage', label: '마이페이지', icon: User },
+ { href: '/home', label: '홈', Icon: HomeRoundedIcon },
+ { href: '/records', label: '사건기록', Icon: GavelRoundedIcon },
+ { href: '/diary', label: '일기', Icon: CalendarMonthRoundedIcon },
+ { href: '/mypage', label: '마이페이지', Icon: PersonRoundedIcon },
] as const;
export default function BottomNavigation() {
@@ -18,7 +21,7 @@ export default function BottomNavigation() {
return (