diff --git a/public/icons/IcSorting.tsx b/public/icons/IcSorting.tsx
index ba3b7626..c5be40d6 100644
--- a/public/icons/IcSorting.tsx
+++ b/public/icons/IcSorting.tsx
@@ -11,7 +11,7 @@ function IcSorting({
width = 24,
height = 24,
isActive = false,
- color = '#111827',
+ color,
}: IcSortingProps) {
return (
);
diff --git a/src/components/sorting-button/SortingButton.stories.tsx b/src/components/sorting-button/SortingButton.stories.tsx
new file mode 100644
index 00000000..cbc1cafe
--- /dev/null
+++ b/src/components/sorting-button/SortingButton.stories.tsx
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/react';
+import SortingButton from './SortingButton';
+
+const meta = {
+ title: 'Components/SortingButton',
+ component: SortingButton,
+ parameters: {
+ componentSubtitle: '목록의 아이템들의 순서를 정렬하게 만드는 컴포넌트',
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const byDate: Story = {
+ args: {
+ variant: 'byDate',
+ onClickSorting: (e) => alert(e),
+ },
+};
+
+export const byDeadline: Story = {
+ args: {
+ variant: 'byDeadline',
+ onClickSorting: (e) => alert(e),
+ },
+};
diff --git a/src/components/sorting-button/SortingButton.test.tsx b/src/components/sorting-button/SortingButton.test.tsx
new file mode 100644
index 00000000..edb21c90
--- /dev/null
+++ b/src/components/sorting-button/SortingButton.test.tsx
@@ -0,0 +1,43 @@
+import { render, screen } from '@testing-library/react';
+import SortingButton from './SortingButton';
+import userEvent from '@testing-library/user-event';
+import '@testing-library/jest-dom';
+
+describe('SortingButton', () => {
+ const mockOnClickSorting = jest.fn();
+
+ it('마감임박순 Sorting Button 렌더링 확인', async () => {
+ render(
+ ,
+ );
+
+ const button = screen.getByRole('button');
+ expect(button).toBeInTheDocument();
+
+ //유저가 최초 클릭 시 최신순->마감임박 순으로 전환. 'DEADLINE'으로 onClickSorting 함수 호출
+ await userEvent.click(button);
+ expect(mockOnClickSorting).toHaveBeenCalledWith('DEADLINE');
+ //유저가 두번째 클릭 시 마감임박->최신순 순으로 전환. 'NEWEST'으로 onClickSorting 함수 호출
+ await userEvent.click(button);
+ expect(mockOnClickSorting).toHaveBeenCalledWith('NEWEST');
+ });
+
+ it('날짜순 SortingButton 렌더링 확인', async () => {
+ render(
+ ,
+ );
+
+ const button = screen.getByRole('button');
+ expect(button).toBeInTheDocument();
+
+ //유저가 최초 클릭 시 최신순->오래된 순으로 전환. 'OLDEST'으로 onClickSorting 함수 호출
+ await userEvent.click(button);
+ expect(mockOnClickSorting).toHaveBeenCalledWith('OLDEST');
+ //유저가 두번째 클릭 시 오래된 순->최신순 순으로 전환. 'NEWEST'으로 onClickSorting 함수 호출
+ await userEvent.click(button);
+ expect(mockOnClickSorting).toHaveBeenCalledWith('NEWEST');
+ });
+});
diff --git a/src/components/sorting-button/SortingButton.tsx b/src/components/sorting-button/SortingButton.tsx
new file mode 100644
index 00000000..68ffb7ad
--- /dev/null
+++ b/src/components/sorting-button/SortingButton.tsx
@@ -0,0 +1,57 @@
+import { useState } from 'react';
+import { IcSorting } from '../../../public/icons/index';
+
+interface SortingButtonProps {
+ variant: 'byDeadline' | 'byDate';
+ onClickSorting: (sortBy: string) => void;
+}
+
+function SortingButton({ variant, onClickSorting }: SortingButtonProps) {
+ const [isActive, setIsActive] = useState(false);
+
+ const onClick = (): void => {
+ let sortBy;
+ setIsActive(!isActive);
+ switch (variant) {
+ case 'byDeadline':
+ sortBy = isActive ? 'NEWEST' : 'DEADLINE';
+ break;
+
+ case 'byDate':
+ sortBy = isActive ? 'NEWEST' : 'OLDEST';
+ break;
+ }
+ onClickSorting(sortBy);
+ };
+
+ const renderLabel = () => {
+ switch (variant) {
+ case 'byDeadline':
+ return '마감임박순';
+
+ case 'byDate':
+ return isActive ? '오래된순' : '최신순';
+ }
+ };
+
+ return (
+
+ );
+}
+
+export default SortingButton;