diff --git a/package.json b/package.json
index 86c8e93..a2dceda 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
},
"dependencies": {
"axios": "^1.6.8",
+ "html2canvas": "^1.4.1",
"react": "^18.2.0",
"react-cookie": "^7.1.4",
"react-dom": "^18.2.0",
diff --git a/src/assets/icons/change.svg b/src/assets/icons/change.svg
new file mode 100644
index 0000000..8d2343d
--- /dev/null
+++ b/src/assets/icons/change.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/assets/icons/download.svg b/src/assets/icons/download.svg
new file mode 100644
index 0000000..b1c0dee
--- /dev/null
+++ b/src/assets/icons/download.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/components/DefineResultPage/CardSection.tsx b/src/components/DefineResultPage/CardSection.tsx
new file mode 100644
index 0000000..876e8a0
--- /dev/null
+++ b/src/components/DefineResultPage/CardSection.tsx
@@ -0,0 +1,182 @@
+import { useRef, useState } from 'react';
+
+import html2canvas from 'html2canvas';
+import styled from 'styled-components';
+
+import { ReactComponent as ChangeIcon } from '@/assets/icons/change.svg';
+import { ReactComponent as DownloadIcon } from '@/assets/icons/download.svg';
+import { ReactComponent as KakaoIcon } from '@/assets/icons/kakaoIcon.svg';
+
+interface CardSectionProps {
+ piece: string;
+}
+
+export const CardSection = ({ piece }: CardSectionProps) => {
+ const [isFront, setIsFront] = useState(true);
+ const captureRef = useRef(null);
+
+ const handleSaveImage = () => {
+ if (!captureRef.current) return;
+
+ const capture = captureRef.current;
+
+ html2canvas(capture, { scrollY: -window.scrollY }).then((canvas) => {
+ const image = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
+ const link = document.createElement('a');
+ link.href = image;
+ link.download = `define-result-${isFront ? 'front' : 'back'}.jpg`;
+ link.click();
+ });
+ };
+
+ return (
+
+
+
+
+
setIsFront((prev) => !prev)}>
+
+
+
+
+
+
+
+
+ 카드에 마우스를 가져가 보세요!
+
+ );
+};
+
+const StyledCardSection = styled.section`
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ .notice {
+ text-align: center;
+ ${({ theme }) => theme.font.desktop.label1m};
+ color: ${({ theme }) => theme.color.primary700};
+ }
+`;
+
+// TODO: Change 버튼 클릭시 카드 앞뒤 돌아가는 애니메이션 추가
+
+const StyledImageContainer = styled.div`
+ width: 264px;
+ height: 426px;
+
+ position: relative;
+
+ img {
+ width: 100%;
+ height: 100%;
+ border-radius: 13px;
+ }
+
+ .hover-view {
+ visibility: hidden;
+
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-end;
+
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ width: 100%;
+ height: 100%;
+ padding: 20px;
+
+ border-radius: 13px;
+ background: ${({ theme }) => theme.color.bgModal};
+ filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.25));
+ backdrop-filter: blur(4px);
+
+ button {
+ color: white;
+ }
+ }
+
+ &:hover .hover-view {
+ visibility: visible;
+ }
+`;
+
+const StyledChangeButton = styled.button`
+ display: flex;
+ width: 48px;
+ height: 48px;
+ justify-content: center;
+ align-items: center;
+
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ background: rgba(255, 255, 255, 0.2);
+
+ &:hover {
+ background: rgba(255, 255, 255, 0.1);
+ }
+`;
+
+const StyleButtonContainer = styled.div`
+ width: 100%;
+
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ button {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ height: 48px;
+ padding: 8px 16px;
+ border-radius: 8px;
+
+ span {
+ ${({ theme }) => theme.font.desktop.label1m};
+ }
+ }
+
+ .download-button {
+ background: ${({ theme }) => theme.color.primary50};
+
+ span {
+ color: ${({ theme }) => theme.color.primary700};
+ }
+ }
+
+ .share-button {
+ background: #fee500;
+
+ span {
+ color: #191600;
+ }
+ }
+
+ div {
+ width: 24px;
+ }
+`;
diff --git a/yarn.lock b/yarn.lock
index 18c6d03..f3b5271 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1920,6 +1920,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+base64-arraybuffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
+ integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
+
boolbase@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
@@ -2092,6 +2097,13 @@ css-color-keywords@^1.0.0:
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==
+css-line-break@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
+ integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
+ dependencies:
+ utrie "^1.0.2"
+
css-select@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
@@ -2962,6 +2974,14 @@ hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
dependencies:
react-is "^16.7.0"
+html2canvas@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
+ integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
+ dependencies:
+ css-line-break "^2.1.0"
+ text-segmentation "^1.0.3"
+
ignore@^5.2.0, ignore@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
@@ -4116,6 +4136,13 @@ tapable@^2.2.0:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+text-segmentation@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
+ integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
+ dependencies:
+ utrie "^1.0.2"
+
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -4285,6 +4312,13 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
+utrie@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
+ integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
+ dependencies:
+ base64-arraybuffer "^1.0.2"
+
vite-plugin-svgr@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz#9f3bf5206b0ec510287e56d16f1915e729bb4e6b"