diff --git a/package-lock.json b/package-lock.json index 4972f26..6573eb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "fp-ts": "^2.16.9", "io-ts": "^2.2.21", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "zod": "^3.23.8" }, "devDependencies": { "@eslint/js": "^9.9.0", @@ -3329,6 +3330,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 1975770..34b0140 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "fp-ts": "^2.16.9", "io-ts": "^2.2.21", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "zod": "^3.23.8" }, "devDependencies": { "@eslint/js": "^9.9.0", diff --git a/src/App.tsx b/src/App.tsx index 391eea5..2d1467d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,40 +1,26 @@ -import { useState, useEffect } from "react"; -import reactLogo from "./assets/react.svg"; -import viteLogo from "/vite.svg"; +import { useEffect } from "react"; +// import reactLogo from "./assets/react.svg"; +// import viteLogo from "/vite.svg"; import "./App.css"; -import { validateData } from "./test"; // test.ts 파일을 import +// import ButtonComponents from "./shared/components/button.components"; //원문 파일 +import ButtonComponents from "./shared/components/Button.components.test"; //Test 파일로 대체 +import { validateData } from "./test"; // test.ts 파일을 -function App() { - const [count, setCount] = useState(0); +const Button = ButtonComponents; +function App() { + // const [count, setCount] = useState(0); + // '#3d3da1' : '#5353ea' useEffect(() => { // 컴포넌트가 마운트될 때 test.ts의 validateData 함수 실행 validateData(); }, []); return ( - <> -
- - Vite logo - - - React logo - -
-

Vite + React

-
- -

- Edit src/App.tsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- +
+
test
+
); } diff --git a/src/shared/components/Button.components.test.tsx b/src/shared/components/Button.components.test.tsx new file mode 100644 index 0000000..da36cac --- /dev/null +++ b/src/shared/components/Button.components.test.tsx @@ -0,0 +1,73 @@ +import { useState } from "react"; +import Z from "zod"; + +//interface +//Zod about props +// 1. zod로 props 스키마 정의 +const buttonPropsSchema = Z.object({ //4. Error: 런타임 Props 검증, Parse 미사용으로 Error 발생 + EnterColor: Z.string(), + LeaveColor: Z.string(), +}) + +// 2. TypeScript 타입으로 추출 +type ButtonProps = Z.infer; + +// 2-1. 바로 타입만 추출하고 스키마 제거 +/** +type ButtonProps = z.infer< + z.object({ + EnterColor: z.string(), + LeaveColor: z.string(), + }) +>; +*/ +// 3. 컴포넌트에 타입 설정: FC Generics로 적용하지 않고 해당 Props에 Type을 적용 +// FC 사용방법은 PR Link 참고 +const ButtonComponents = (props:ButtonProps) => { + const [isHover, setHover] = useState(false); + + // 4-1. 직접적으로 Props 변수를 생성 + const { EnterColor, LeaveColor } = props; + + // 4-2. 런타임 Props 검증 + try { + buttonPropsSchema.parse(props); + console.log("Props validation successful"); // 유효성 검증이 성공하면 이 메시지가 출력됩니다. + } catch (err) { + console.error("Props validation failed", err); // 검증 실패 시 오류 메시지 출력 + } + + return ( +
+
+
{ + setHover(true); + }} + onMouseLeave={() => { + setHover(false); + }} + onClick={() => { + console.log('Button clicked'); + }} + role="button" // 접근성 향상 + > + Button +
+
+
+ ) +}; + +export default ButtonComponents; \ No newline at end of file diff --git a/src/shared/components/Button.components.tsx b/src/shared/components/Button.components.tsx new file mode 100644 index 0000000..901d32a --- /dev/null +++ b/src/shared/components/Button.components.tsx @@ -0,0 +1,67 @@ +import { useState } from "react"; +import Z from "zod"; + +//interface +//Zod about props +// 1. zod로 props 스키마 정의 +const buttonPropsSchema = Z.object({ //4. Error: 런타임 Props 검증, Parse 미사용으로 Error 발생 + EnterColor: Z.string(), + LeaveColor: Z.string(), +}) + +// 2. TypeScript 타입으로 추출 +type ButtonProps = Z.infer; + +// 2-1. 바로 타입만 추출하고 스키마 제거 +/** +type ButtonProps = z.infer< + z.object({ + EnterColor: z.string(), + LeaveColor: z.string(), + }) +>; +*/ +// 3. 컴포넌트에 타입 설정: FC Generics로 적용하지 않고 해당 Props에 Type을 적용 +// FC 사용방법은 PR Link 참고 +const ButtonComponents = (props:ButtonProps) => { + const [isHover, setHover] = useState(false); + +// 4-1. 직접적으로 Props 변수를 생성 + const { EnterColor, LeaveColor } = props; +// 4-2. 런타임 Props 검증 + buttonPropsSchema.parse(props); + + return ( +
+
+
{ + setHover(true); + }} + onMouseLeave={() => { + setHover(false); + }} + onClick={() => { + console.log('Button clicked'); + }} + role="button" // 접근성 향상 + > + Button +
+
+
+ ) +}; + +export default ButtonComponents; \ No newline at end of file