diff --git a/src/app/preview/input/page.tsx b/src/app/preview/input/page.tsx
new file mode 100644
index 0000000..2f9211e
--- /dev/null
+++ b/src/app/preview/input/page.tsx
@@ -0,0 +1,142 @@
+import { Input } from '@/components/ui/Input';
+
+export default function ButtonExamples() {
+ return (
+
+
Normal
+
large normal
+
+
+
+
+
large typing
+
+
+
+
+
large done
+
+
+
+
+
large error
+
+
+
+
+
large disable
+
+
+
+
+
small normal
+
+
+
+
+
small typing
+
+
+
+
+
small done
+
+
+
+
+
small error
+
+
+
+
+
small disable
+
+
+
+
+
Password
+
large normal
+
+
+
+
+
large typing
+
+
+
+
+
large done
+
+
+
+
+
large error
+
+
+
+
+
large disable
+
+
+
+
+
small normal
+
+
+
+
+
small typing
+
+
+
+
+
small done
+
+
+
+
+
small error
+
+
+
+
+
small disable
+
+
+
+
+
width 커스텀
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/ui/Input.tsx b/src/components/ui/Input.tsx
new file mode 100644
index 0000000..4b5067c
--- /dev/null
+++ b/src/components/ui/Input.tsx
@@ -0,0 +1,147 @@
+'use client';
+
+import { cn } from '@/util/cn';
+import { VariantProps, cva } from 'class-variance-authority';
+import { Eye, EyeOff } from 'lucide-react';
+import * as React from 'react';
+
+interface IInputProps
+ extends React.InputHTMLAttributes,
+ VariantProps {
+ /**
+ * 입력 필드의 상태 (기본값: `'default'`)
+ * - `'default'` : 기본 상태 (테두리 없음)
+ * - `'success'` : 성공 상태 (메인 컬러 테두리 적용)
+ */
+ state?: 'default' | 'success';
+ /**
+ * 입력 필드의 크기 (기본값: `'l'`)
+ * - `'s'` : 작은 크기 (36px)
+ * - `'l'` : 기본 크기 (50px)
+ */
+ inputSize?: 'l' | 's';
+ /**
+ * 에러 메시지 (에러 상태일 때 표시)
+ */
+ errorMessage?: string;
+}
+
+const inputVariants = cva(
+ 'box-border flex w-full rounded-md border-transparent bg-Cgray200 px-3 px-[16px] py-1 py-[14px] text-base text-Cgray700 caret-Cgray500 shadow-sm transition-colors placeholder:text-Cgray400 focus:outline-none focus-visible:outline-none disabled:cursor-not-allowed disabled:bg-disable disabled:text-disable_text md:text-sm',
+ {
+ variants: {
+ state: {
+ default: '',
+ success: 'border border-main',
+ },
+ inputSize: {
+ s: 'typo-button2 h-[36px]',
+ l: 'typo-button1 h-[50px] py-[10px]',
+ },
+ },
+ defaultVariants: {
+ inputSize: 'l',
+ },
+ },
+);
+
+const errorTextVariants = cva('px-[10px] text-warning', {
+ variants: {
+ inputSize: {
+ s: 'typo-caption2 mt-[8px]',
+ l: 'typo-caption1 mt-[10px]',
+ },
+ defaultVariants: {
+ inputSize: 'l',
+ },
+ },
+});
+
+/**
+ * `Input` 컴포넌트
+ *
+ * 기본적인 입력 필드로, 텍스트 및 비밀번호 입력을 지원하며,
+ * 에러 상태 및 성공 상태를 지정할 수 있습니다.
+ * 접근성을 위해 id가 필수적으로 필요합니다.
+ *
+ * @example
+ * // 기본 사용법
+ *
+ *
+ * @example
+ * // 에러 상태
+ *
+ *
+ * @example
+ * // 성공 상태
+ *
+ *
+ * @example
+ * // 비밀번호 입력 필드 (눈 아이콘 포함)
+ *
+ *
+ * @param {IInputProps} props - `Input` 컴포넌트의 속성
+ * @returns {JSX.Element} `Input` 요소
+ */
+const Input = React.forwardRef(
+ (
+ {
+ className,
+ type,
+ state = 'default',
+ errorMessage,
+ inputSize = 'l',
+ id,
+ ...props
+ },
+ ref,
+ ) => {
+ const [isVisible, setIsVisible] = React.useState(false);
+
+ return (
+
+
+
+
+
+ {errorMessage && (
+
+ {errorMessage}
+
+ )}
+
+ );
+ },
+);
+
+Input.displayName = 'Input';
+
+export { Input };