diff --git a/src/app/preview/tech-stack/page.tsx b/src/app/preview/tech-stack/page.tsx
new file mode 100644
index 0000000..5d468e3
--- /dev/null
+++ b/src/app/preview/tech-stack/page.tsx
@@ -0,0 +1,106 @@
+import { backend, design, frontend } from '@/components/ui/Icon/iconRegistry';
+import React from 'react';
+
+export default function TechStackPage() {
+ return (
+
+ {/* Frontend Section */}
+
+ Frontend Technologies
+
+ {/* Core */}
+
+
Core
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Framework & Libraries */}
+
+
Framework & Libraries
+
+
+
+
+
+
+ {/* Mobile & Others */}
+
+
Mobile & Others
+
+
+
+
+
+
+
+
+
+
+
+ {/* Backend Section */}
+
+ Backend Technologies
+
+ {/* Language & Runtime */}
+
+
Language & Runtime
+
+
+
+
+
+
+
+
+
+ {/* Framework */}
+
+
Framework
+
+
+
+
+
+
+
+
+ {/* Database & Infrastructure */}
+
+
+ Database & Infrastructure
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Design Tools */}
+
+ Design Tools
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/ui/Icon/BaseIcon.tsx b/src/components/ui/Icon/BaseIcon.tsx
new file mode 100644
index 0000000..29b81e2
--- /dev/null
+++ b/src/components/ui/Icon/BaseIcon.tsx
@@ -0,0 +1,46 @@
+import { cn } from '@/util/cn';
+
+export interface BaseIconProps {
+ color?: string;
+ size?: number;
+ radius?: 'none' | 'sm' | 'md' | 'lg' | 'full';
+ className?: string;
+ path: string;
+ ariaLabel?: string;
+ title?: string;
+}
+
+export function BaseIcon({
+ color,
+ size = 24,
+ radius = 'none',
+ className,
+ path,
+ ariaLabel,
+ title,
+}: BaseIconProps) {
+ const radiusMap = {
+ none: 'rounded-none',
+ sm: 'rounded-sm',
+ md: 'rounded',
+ lg: 'rounded-lg',
+ full: 'rounded-full',
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/ui/Icon/IconData.ts b/src/components/ui/Icon/IconData.ts
new file mode 100644
index 0000000..8c2d4c3
--- /dev/null
+++ b/src/components/ui/Icon/IconData.ts
@@ -0,0 +1,268 @@
+import getPath from './getPath';
+
+export interface IconConfig {
+ name: string;
+ color: string;
+ path: string;
+ category: 'frontend' | 'backend' | 'design';
+}
+
+export const ICON_LIST: IconConfig[] = [
+ {
+ name: 'Javascript',
+ color: '#F7DF1E',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Typescript',
+ color: '#3178C6',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'React',
+ color: '#61DAFB',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Vue',
+ color: '#4FC08D',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Next',
+ color: '#000000',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Svelte',
+ color: '#FF3E00',
+ path: 'M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767 4.109 4.109 0 0 1-.703-3.107 3.898 3.898 0 0 1 .134-.522l.105-.321.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063-.02.208a1.253 1.253 0 0 0 .226.83 1.337 1.337 0 0 0 1.435.533 1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778 1.242 1.242 0 0 0-.211-.937 1.338 1.338 0 0 0-1.435-.533 1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499 4.44 4.44 0 0 1-4.765-1.766 4.108 4.108 0 0 1-.702-3.108 3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499 4.44 4.44 0 0 1 4.765 1.767 4.109 4.109 0 0 1 .703 3.107 3.943 3.943 0 0 1-.134.522l-.105.321-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 0 0-.226-.831 1.337 1.337 0 0 0-1.435-.532 1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778 1.24 1.24 0 0 0 .211.937 1.338 1.338 0 0 0 1.435.533 1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498 4.44 4.44 0 0 1 4.765 1.766 4.108 4.108 0 0 1 .702 3.108 3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295 6.753 6.753 0 0 0 .666 4.336 6.43 6.43 0 0 0-.96 2.396 6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295 6.756 6.756 0 0 0-.665-4.336 6.429 6.429 0 0 0 .958-2.396 6.831 6.831 0 0 0-1.167-5.168Z',
+ category: 'frontend',
+ },
+
+ {
+ name: 'Flutter',
+ color: '#02569B',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Swift',
+ color: '#F05138',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Kotlin',
+ color: '#7F52FF',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'ReactNative',
+ color: '#61DAFB',
+ path: 'M12 9.861A2.139 2.139 0 1 0 12 14.139 2.139 2.139 0 1 0 12 9.861zM6.008 16.255l-.472-.12C2.018 15.246 0 13.737 0 11.996s2.018-3.25 5.536-4.139l.472-.119.133.468a23.53 23.53 0 0 0 1.363 3.578l.101.213-.101.213a23.307 23.307 0 0 0-1.363 3.578l-.133.469zM5.317 8.95c-2.674.751-4.315 1.9-4.315 3.046 0 1.145 1.641 2.294 4.315 3.046a24.95 24.95 0 0 1 1.182-3.046A24.752 24.752 0 0 1 5.317 8.95zM17.992 16.255l-.133-.469a23.357 23.357 0 0 0-1.364-3.578l-.101-.213.101-.213a23.42 23.42 0 0 0 1.364-3.578l.133-.468.473.119c3.517.889 5.535 2.398 5.535 4.139s-2.018 3.25-5.535 4.139l-.473.12zm-.491-4.259c.48 1.039.877 2.06 1.182 3.046 2.675-.752 4.315-1.901 4.315-3.046 0-1.146-1.641-2.294-4.315-3.046a24.788 24.788 0 0 1-1.182 3.046zM5.31 8.945l-.133-.467C4.188 4.992 4.488 2.494 6 1.622c1.483-.856 3.864.155 6.359 2.716l.34.349-.34.349a23.552 23.552 0 0 0-2.422 2.967l-.135.193-.235.02a23.657 23.657 0 0 0-3.785.61l-.472.119zm1.896-6.63c-.268 0-.505.058-.705.173-.994.573-1.17 2.565-.485 5.253a25.122 25.122 0 0 1 3.233-.501 24.847 24.847 0 0 1 2.052-2.544c-1.56-1.519-3.037-2.381-4.095-2.381zM16.795 22.677c-.001 0-.001 0 0 0-1.425 0-3.255-1.073-5.154-3.023l-.34-.349.34-.349a23.53 23.53 0 0 0 2.421-2.968l.135-.193.234-.02a23.63 23.63 0 0 0 3.787-.609l.472-.119.134.468c.987 3.484.688 5.983-.824 6.854a2.38 2.38 0 0 1-1.205.308zm-4.096-3.381c1.56 1.519 3.037 2.381 4.095 2.381h.001c.267 0 .505-.058.704-.173.994-.573 1.171-2.566.485-5.254a25.02 25.02 0 0 1-3.234.501 24.674 24.674 0 0 1-2.051 2.545zM18.69 8.945l-.472-.119a23.479 23.479 0 0 0-3.787-.61l-.234-.02-.135-.193a23.414 23.414 0 0 0-2.421-2.967l-.34-.349.34-.349C14.135 1.778 16.515.767 18 1.622c1.512.872 1.812 3.37.824 6.855l-.134.468zM14.75 7.24c1.142.104 2.227.273 3.234.501.686-2.688.509-4.68-.485-5.253-.988-.571-2.845.304-4.8 2.208A24.849 24.849 0 0 1 14.75 7.24zM7.206 22.677A2.38 2.38 0 0 1 6 22.369c-1.512-.871-1.812-3.369-.823-6.854l.132-.468.472.119c1.155.291 2.429.496 3.785.609l.235.02.134.193a23.596 23.596 0 0 0 2.422 2.968l.34.349-.34.349c-1.898 1.95-3.728 3.023-5.151 3.023zm-1.19-6.427c-.686 2.688-.509 4.681.485 5.254.987.563 2.843-.305 4.8-2.208a24.998 24.998 0 0 1-2.052-2.545 24.976 24.976 0 0 1-3.233-.501zM12 16.878c-.823 0-1.669-.036-2.516-.106l-.235-.02-.135-.193a30.388 30.388 0 0 1-1.35-2.122 30.354 30.354 0 0 1-1.166-2.228l-.1-.213.1-.213a30.3 30.3 0 0 1 1.166-2.228c.414-.716.869-1.43 1.35-2.122l.135-.193.235-.02a29.785 29.785 0 0 1 5.033 0l.234.02.134.193a30.006 30.006 0 0 1 2.517 4.35l.101.213-.101.213a29.6 29.6 0 0 1-2.517 4.35l-.134.193-.234.02c-.847.07-1.694.106-2.517.106zm-2.197-1.084c1.48.111 2.914.111 4.395 0a29.006 29.006 0 0 0 2.196-3.798 28.585 28.585 0 0 0-2.197-3.798 29.031 29.031 0 0 0-4.394 0 28.477 28.477 0 0 0-2.197 3.798 29.114 29.114 0 0 0 2.197 3.798z',
+ category: 'frontend',
+ },
+ {
+ name: 'Unity',
+ color: '#FFFFFF',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Jest',
+ color: '#C21325',
+ path: getPath(
+ '',
+ ),
+ category: 'frontend',
+ },
+ {
+ name: 'Spring',
+ color: '#6DB33F',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Node',
+ color: '#5FA04E',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Nest',
+ color: '#E0234E',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Express',
+ color: '#000000',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Go',
+ color: '#00ADD8',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'C',
+ color: '#A8B9CC',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Python',
+ color: '#3776AB',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Django',
+ color: '#092E20',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'MySQL',
+ color: '#4479A1',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'MongoDB',
+ color: '#47A248',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'PHP',
+ color: '#777BB4',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'GraphQL',
+ color: '#E10098',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Firebase',
+ color: '#DD2C00',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'AWS',
+ color: '#FF9900',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Kubernetes',
+ color: '#326CE5',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Docker',
+ color: '#2496ED',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Git',
+ color: '#F05032',
+ path: getPath(
+ '',
+ ),
+ category: 'backend',
+ },
+ {
+ name: 'Java',
+ color: '#007396',
+ path: 'M8.851 18.56s-.917.534.653.714c1.902.218 2.874.187 4.969-.211 0 0 .552.346 1.321.646-4.699 2.013-10.633-.118-6.943-1.149M8.276 15.933s-1.028.761.542.924c2.032.209 3.636.227 6.413-.308 0 0 .384.389.987.602-5.679 1.661-12.007.13-7.942-1.218M13.116 11.475c1.158 1.333-.304 2.533-.304 2.533s2.939-1.518 1.589-3.418c-1.261-1.772-2.228-2.652 3.007-5.688 0-.001-8.216 2.051-4.292 6.573M19.33 20.504s.679.559-.747.991c-2.712.822-11.288 1.069-13.669.033-.856-.373.75-.89 1.254-.998.527-.114.828-.093.828-.093-.953-.671-6.156 1.317-2.643 1.887 9.58 1.553 17.462-.7 14.977-1.82M9.292 13.21s-4.362 1.036-1.544 1.412c1.189.159 3.561.123 5.77-.062 1.806-.152 3.618-.477 3.618-.477s-.637.272-1.098.587c-4.429 1.165-12.986.623-10.522-.568 2.082-1.006 3.776-.892 3.776-.892M17.116 17.584c4.503-2.34 2.421-4.589.968-4.285-.355.074-.515.138-.515.138s.132-.207.385-.297c2.875-1.011 5.086 2.981-.928 4.562 0-.001.07-.062.09-.118M14.401 0s2.494 2.494-2.365 6.33c-3.896 3.077-.888 4.832-.001 6.836-2.274-2.053-3.943-3.858-2.824-5.539 1.644-2.469 6.197-3.665 5.19-7.627M9.734 23.924c4.322.277 10.959-.153 11.116-2.198 0 0-.302.775-3.572 1.391-3.688.694-8.239.613-10.937.168 0 0 .553.457 3.393.639',
+ category: 'backend',
+ },
+ {
+ name: 'Figma',
+ color: '#F24E1E',
+ path: getPath(
+ '',
+ ),
+ category: 'design',
+ },
+ {
+ name: 'Zeplin',
+ color: '#FDBD39',
+ path: 'M12 0C5.352 0 0 5.352 0 12s5.352 12 12 12c6.648 0 12-5.352 12-12S18.648 0 12 0zm-.24 4.8h.48c4.08 0 7.44 3.36 7.44 7.44v.48c0 4.08-3.36 7.44-7.44 7.44h-.48c-4.08 0-7.44-3.36-7.44-7.44v-.48c0-4.08 3.36-7.44 7.44-7.44zM12 16.8c2.64 0 4.8-2.16 4.8-4.8 0-2.64-2.16-4.8-4.8-4.8-2.64 0-4.8 2.16-4.8 4.8 0 2.64 2.16 4.8 4.8 4.8z',
+ category: 'design',
+ },
+ {
+ name: 'Sketch',
+ color: '#F7B500',
+ path: getPath(
+ '',
+ ),
+ category: 'design',
+ },
+];
diff --git a/src/components/ui/Icon/getPath.ts b/src/components/ui/Icon/getPath.ts
new file mode 100644
index 0000000..a549fe8
--- /dev/null
+++ b/src/components/ui/Icon/getPath.ts
@@ -0,0 +1,4 @@
+export default function getPath(svgString: string): string {
+ const pathMatch = svgString.match(/d="([^"]+)"/);
+ return pathMatch ? pathMatch[1] : '';
+}
diff --git a/src/components/ui/Icon/iconRegistry.ts b/src/components/ui/Icon/iconRegistry.ts
new file mode 100644
index 0000000..06d2660
--- /dev/null
+++ b/src/components/ui/Icon/iconRegistry.ts
@@ -0,0 +1,47 @@
+import { createElement } from 'react';
+
+import { BaseIcon, BaseIconProps } from './BaseIcon';
+import { ICON_LIST, IconConfig } from './IconData';
+
+type IconProps = Omit;
+
+function createIconComponent(config: IconConfig) {
+ return function Icon(props: IconProps) {
+ return createElement(BaseIcon, {
+ ...props,
+ color: props.color ?? config.color,
+ path: config.path,
+ title: `${config.name} Icon`,
+ ariaLabel: config.name,
+ });
+ };
+}
+
+// 카테고리별로 아이콘 분류 및 컴포넌트 생성
+export const Icons = ICON_LIST.reduce<
+ Record JSX.Element>>
+>((acc, config) => {
+ const category = config.category;
+ const componentName = `${config.name}Icon`;
+
+ if (!acc[category]) {
+ acc[category] = {};
+ }
+
+ acc[category][componentName] = createIconComponent(config);
+ return acc;
+}, {});
+
+// 카테고리별 export
+export const { frontend, backend, design } = Icons;
+
+// 모든 아이콘 한번에 export
+export const AllIcons = Object.values(Icons).reduce<
+ Record JSX.Element>
+>(
+ (acc, categoryIcons) => ({
+ ...acc,
+ ...categoryIcons,
+ }),
+ {},
+);