diff --git a/src/frontend/apps/web/app/(main)/page.tsx b/src/frontend/apps/web/app/(main)/page.tsx
index d32bd1b0..ad066e56 100644
--- a/src/frontend/apps/web/app/(main)/page.tsx
+++ b/src/frontend/apps/web/app/(main)/page.tsx
@@ -11,9 +11,6 @@ export const metadata = {
export default function Page() {
return (
-
);
diff --git a/src/frontend/apps/web/package.json b/src/frontend/apps/web/package.json
index e4a70279..e5010dec 100644
--- a/src/frontend/apps/web/package.json
+++ b/src/frontend/apps/web/package.json
@@ -11,6 +11,7 @@
},
"dependencies": {
"@tanstack/react-query": "^5.64.2",
+ "@tanstack/react-table": "^8.20.6",
"@workspace/ui": "workspace:*",
"lucide-react": "0.473.0",
"next": "^14.2.23",
diff --git a/src/frontend/apps/web/src/features/stock/index.tsx b/src/frontend/apps/web/src/features/stock/index.tsx
index 9aa7a15f..9aff9863 100644
--- a/src/frontend/apps/web/src/features/stock/index.tsx
+++ b/src/frontend/apps/web/src/features/stock/index.tsx
@@ -1,2 +1 @@
-export { default as StockDetailLayout } from './ui/stock-detail-layout';
-export { default as StocksList } from './ui/stocks-list';
+export { StockDetailLayout, StocksList } from './ui';
diff --git a/src/frontend/apps/web/src/features/stock/model/index.ts b/src/frontend/apps/web/src/features/stock/model/index.ts
new file mode 100644
index 00000000..6925f3d6
--- /dev/null
+++ b/src/frontend/apps/web/src/features/stock/model/index.ts
@@ -0,0 +1,2 @@
+export { type Stock } from './stock.types';
+export { columns } from './stocks-table.columns';
diff --git a/src/frontend/apps/web/src/features/stock/model/stock.types.ts b/src/frontend/apps/web/src/features/stock/model/stock.types.ts
new file mode 100644
index 00000000..804e9ed1
--- /dev/null
+++ b/src/frontend/apps/web/src/features/stock/model/stock.types.ts
@@ -0,0 +1,8 @@
+export type Stock = {
+ id: string;
+ name: string;
+ currPrice: string;
+ fluctuation: string;
+ volume: string;
+ slug: string;
+};
diff --git a/src/frontend/apps/web/src/features/stock/model/stocks-table.columns.tsx b/src/frontend/apps/web/src/features/stock/model/stocks-table.columns.tsx
new file mode 100644
index 00000000..ac91ba7b
--- /dev/null
+++ b/src/frontend/apps/web/src/features/stock/model/stocks-table.columns.tsx
@@ -0,0 +1,61 @@
+import { ColumnDef } from '@tanstack/react-table';
+import { Stock } from './stock.types';
+import { Button } from '@workspace/ui/components';
+import { ArrowUpDown } from 'lucide-react';
+
+export const columns: ColumnDef[] = [
+ {
+ accessorKey: 'name',
+ header: () => 종목명
,
+ cell: ({ row }) => {row.getValue('name')}
,
+ },
+ {
+ id: 'currPrice',
+ accessorFn: (row) => parseFloat(row.currPrice),
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {
+ const price = parseFloat(row.getValue('currPrice'));
+ const formatted = new Intl.NumberFormat('en-US', {
+ style: 'decimal',
+ currency: 'KRW',
+ }).format(price);
+ return {`${formatted}원`}
;
+ },
+ },
+ {
+ id: 'fluctuation',
+ accessorFn: (row) => parseFloat(row.fluctuation),
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {row.getValue('fluctuation')}%
,
+ },
+ {
+ id: 'volume',
+ accessorFn: (row) => parseFloat(row.volume),
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {row.getValue('volume')}
,
+ },
+];
diff --git a/src/frontend/apps/web/src/features/stock/ui/index.ts b/src/frontend/apps/web/src/features/stock/ui/index.ts
new file mode 100644
index 00000000..9e04e67c
--- /dev/null
+++ b/src/frontend/apps/web/src/features/stock/ui/index.ts
@@ -0,0 +1,2 @@
+export { default as StockDetailLayout } from './stock-detail-layout';
+export { default as StocksList } from './stocks-list-table';
diff --git a/src/frontend/apps/web/src/features/stock/ui/stocks-list-table.tsx b/src/frontend/apps/web/src/features/stock/ui/stocks-list-table.tsx
new file mode 100644
index 00000000..4cf4e6c7
--- /dev/null
+++ b/src/frontend/apps/web/src/features/stock/ui/stocks-list-table.tsx
@@ -0,0 +1,108 @@
+'use client';
+
+import { SortingState, flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table';
+import { useState } from 'react';
+import { Stock, columns } from '../model';
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@workspace/ui/components';
+import { useRouter } from 'next/navigation';
+
+const Stockdata: Stock[] = [
+ {
+ id: '1',
+ name: '삼성전자',
+ currPrice: '53700',
+ fluctuation: '+0.00',
+ volume: '1000',
+ slug: 'samsung-electronics',
+ },
+ {
+ id: '2',
+ name: 'SK하이닉스',
+ currPrice: '221000',
+ fluctuation: '+0.68',
+ volume: '1000',
+ slug: 'sk-hynix',
+ },
+ {
+ id: '3',
+ name: '카카오',
+ currPrice: '35750',
+ fluctuation: '+0.00',
+ volume: '1000',
+ slug: 'kakao',
+ },
+ {
+ id: '4',
+ name: '네이버',
+ currPrice: '204000',
+ fluctuation: '-0.24',
+ volume: '1000',
+ slug: 'naver',
+ },
+ {
+ id: '5',
+ name: '한화에어로스페이스',
+ currPrice: '411500',
+ fluctuation: '+7.30',
+ volume: '1000',
+ slug: 'hanwha-aerospace',
+ },
+];
+
+const StocksListTable = () => {
+ const [sorting, setSorting] = useState([]);
+ const router = useRouter();
+
+ const table = useReactTable({
+ data: Stockdata,
+ columns,
+ onSortingChange: setSorting,
+ getCoreRowModel: getCoreRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ state: {
+ sorting,
+ },
+ });
+ return (
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ return {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())};
+ })}
+
+ ))}
+
+
+ {table.getRowModel().rows?.length ? (
+ table.getRowModel().rows.map((row) => (
+ {
+ router.push(`/${row.original.slug ?? ''}`);
+ }}
+ >
+ {row.getVisibleCells().map((cell) => (
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+ ))}
+
+ ))
+ ) : (
+
+
+ No results.
+
+
+ )}
+
+
+
+ );
+};
+export default StocksListTable;
diff --git a/src/frontend/apps/web/src/features/stock/ui/stocks-list.tsx b/src/frontend/apps/web/src/features/stock/ui/stocks-list.tsx
deleted file mode 100644
index 03e6242b..00000000
--- a/src/frontend/apps/web/src/features/stock/ui/stocks-list.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { DataTable } from '@workspace/ui/components';
-
-const StocksList = () => {
- const Stockdata = [
- {
- id: '1',
- name: '삼성전자',
- currPrice: '53700',
- fluctuation: '+0.00',
- volume: '1000',
- stockSlug: 'samsung-electronics',
- },
- {
- id: '2',
- name: 'SK하이닉스',
- currPrice: '221000',
- fluctuation: '+0.68',
- volume: '1000',
- stockSlug: 'sk-hynix',
- },
- {
- id: '3',
- name: '카카오',
- currPrice: '35750',
- fluctuation: '+0.00',
- volume: '1000',
- stockSlug: 'kakao',
- },
- {
- id: '4',
- name: '네이버',
- currPrice: '204000',
- fluctuation: '-0.24',
- volume: '1000',
- stockSlug: 'naver',
- },
- {
- id: '5',
- name: '한화에어로스페이스',
- currPrice: '411500',
- fluctuation: '+7.30',
- volume: '1000',
- stockSlug: 'hanwha-aerospace',
- },
- ];
- return (
-
-
-
- );
-};
-export default StocksList;
diff --git a/src/frontend/packages/ui/package.json b/src/frontend/packages/ui/package.json
index 2df7a6af..0bb5f18f 100644
--- a/src/frontend/packages/ui/package.json
+++ b/src/frontend/packages/ui/package.json
@@ -20,7 +20,6 @@
"@radix-ui/react-toggle": "^1.1.1",
"@radix-ui/react-toggle-group": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.7",
- "@tanstack/react-table": "^8.20.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "0.473.0",
diff --git a/src/frontend/packages/ui/src/components/DataTable/data-table.stories.tsx b/src/frontend/packages/ui/src/components/DataTable/data-table.stories.tsx
deleted file mode 100644
index 31f72e88..00000000
--- a/src/frontend/packages/ui/src/components/DataTable/data-table.stories.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { Meta, StoryObj } from '@storybook/react';
-import { DataTable, Stock } from './data-table';
-
-const meta: Meta = {
- title: 'Widget/DataTable',
- component: DataTable,
- parameters: {
- layout: 'centered',
- },
- tags: ['autodocs'],
-};
-export default meta;
-
-type Story = StoryObj;
-
-const sampleData: Stock[] = [
- {
- id: '1',
- name: 'Samsung',
- currPrice: '10000',
- fluctuation: '+0.1',
- volume: '1000',
- },
- {
- id: '2',
- name: 'Apple',
- currPrice: '20000',
- fluctuation: '+0.2',
- volume: '2000',
- },
- {
- id: '3',
- name: 'Google',
- currPrice: '30000',
- fluctuation: '-0.3',
- volume: '3000',
- },
-];
-
-export const Default: Story = {
- args: {
- data: sampleData,
- },
-};
diff --git a/src/frontend/packages/ui/src/components/DataTable/data-table.tsx b/src/frontend/packages/ui/src/components/DataTable/data-table.tsx
deleted file mode 100644
index cef02da7..00000000
--- a/src/frontend/packages/ui/src/components/DataTable/data-table.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-'use client';
-
-import * as React from 'react';
-import { ColumnDef, SortingState, flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table';
-import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../Table';
-import { Button } from '../Button';
-import { ArrowUpDown } from 'lucide-react';
-
-export type Stock = {
- id: string;
- name: string;
- currPrice: string;
- fluctuation: string;
- volume: string;
-};
-
-export const columns: ColumnDef[] = [
- {
- accessorKey: 'name',
- header: () => 종목명
,
- cell: ({ row }) => {row.getValue('name')}
,
- },
- {
- accessorKey: 'currPrice',
- header: ({ column }) => (
-
- ),
- cell: ({ row }) => {
- const price = parseFloat(row.getValue('currPrice'));
- const formatted = new Intl.NumberFormat('en-US', {
- style: 'decimal',
- currency: 'KRW',
- }).format(price);
- return {`${formatted}원`}
;
- },
- },
- {
- accessorKey: 'fluctuation',
- accessorFn: (row) => parseFloat(row.fluctuation),
- header: ({ column }) => (
-
- ),
- cell: ({ row }) => {row.getValue('fluctuation')}%
,
- },
- {
- accessorKey: 'volume',
- header: ({ column }) => (
-
- ),
- cell: ({ row }) => {row.getValue('volume')}
,
- },
-];
-
-export function DataTable({ data }: { data: Stock[] }) {
- const [sorting, setSorting] = React.useState([]);
-
- const table = useReactTable({
- data,
- columns,
- onSortingChange: setSorting,
- getCoreRowModel: getCoreRowModel(),
- getSortedRowModel: getSortedRowModel(),
- state: {
- sorting,
- },
- });
-
- return (
-
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => {
- return {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())};
- })}
-
- ))}
-
-
- {table.getRowModel().rows?.length ? (
- table.getRowModel().rows.map((row) => (
-
- {row.getVisibleCells().map((cell) => (
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
- ))}
-
- ))
- ) : (
-
-
- No results.
-
-
- )}
-
-
- );
-}
diff --git a/src/frontend/packages/ui/src/components/DataTable/index.ts b/src/frontend/packages/ui/src/components/DataTable/index.ts
deleted file mode 100644
index 28b5088c..00000000
--- a/src/frontend/packages/ui/src/components/DataTable/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { DataTable } from './data-table';
diff --git a/src/frontend/packages/ui/src/components/index.ts b/src/frontend/packages/ui/src/components/index.ts
index 64439139..44c7f0c5 100644
--- a/src/frontend/packages/ui/src/components/index.ts
+++ b/src/frontend/packages/ui/src/components/index.ts
@@ -2,7 +2,6 @@ export * from './Button';
export * from './Badge';
export * from './Textarea';
export * from './Table';
-export * from './DataTable';
export * from './ChatTextarea';
export * from './Toast';
export * from './Resizable';
diff --git a/src/frontend/pnpm-lock.yaml b/src/frontend/pnpm-lock.yaml
index 2e7c30f4..2d6a197f 100644
--- a/src/frontend/pnpm-lock.yaml
+++ b/src/frontend/pnpm-lock.yaml
@@ -32,6 +32,9 @@ importers:
'@tanstack/react-query':
specifier: ^5.64.2
version: 5.64.2(react@18.3.1)
+ '@tanstack/react-table':
+ specifier: ^8.20.6
+ version: 8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@workspace/ui':
specifier: workspace:*
version: link:../../packages/ui
@@ -158,9 +161,6 @@ importers:
'@radix-ui/react-tooltip':
specifier: ^1.1.7
version: 1.1.7(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@tanstack/react-table':
- specifier: ^8.20.6
- version: 8.20.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
class-variance-authority:
specifier: ^0.7.1
version: 0.7.1
@@ -5372,11 +5372,11 @@ snapshots:
'@tanstack/query-core': 5.64.2
react: 18.3.1
- '@tanstack/react-table@8.20.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@tanstack/react-table@8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/table-core': 8.20.5
- react: 19.0.0
- react-dom: 19.0.0(react@19.0.0)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
'@tanstack/table-core@8.20.5': {}