diff --git a/app/main/_components/ContactUserProfile.tsx b/app/main/_components/ContactUserProfile.tsx
deleted file mode 100644
index 212affa..0000000
--- a/app/main/_components/ContactUserProfile.tsx
+++ /dev/null
@@ -1,333 +0,0 @@
-import { Hobby, ProfileData } from "@/lib/types/profile";
-import Image from "next/image";
-import { ChevronDown, ChevronUp } from "lucide-react";
-import React, { useEffect, useRef, useState } from "react";
-
-/* ── 유틸 함수 ── */
-const getContactFrequencyLabel = (freq?: string) => {
- switch (freq) {
- case "FREQUENT":
- return "자주";
- case "NORMAL":
- return "보통";
- case "RARE":
- return "드물게";
- default:
- return freq || "보통";
- }
-};
-
-const getHobbyLabel = (hobbies?: (Hobby | string)[]) => {
- if (!hobbies || hobbies.length === 0) return "없음";
- const hobby = hobbies[0];
- return typeof hobby === "string" ? hobby : hobby.name;
-};
-
-const getAge = (birthDate?: string) => {
- if (!birthDate) return "?? ";
- return new Date().getFullYear() - new Date(birthDate).getFullYear() + 1;
-};
-
-/* ── 밑줄 값 텍스트 (반복 패턴) ── */
-const UnderlinedValue = ({ children }: { children: React.ReactNode }) => (
-
- {children}
-
-);
-
-const Label = ({ children }: { children: React.ReactNode }) => (
- {children}
-);
-
-/* ── 프로필 헤더 (이미지 + 닉네임 + 액션 아이콘) ── */
-const ProfileHeader = ({ profile }: { profile: ProfileData }) => (
-
- {/* 프로필 이미지 */}
-
-
- {/* 닉네임 */}
-
- 내가 뽑은 사람
-
- {profile.nickname || "익명"}
-
-
-
- {/* 액션 아이콘 */}
-
-
-);
-
-/* ── 나이 + 전공 ── */
-const ProfileStats = ({ profile }: { profile: ProfileData }) => (
-
-
- 나이
-
- {getAge(profile.birthDate)}
-
-
-
- 전공
-
- {profile.major || "미지정"}
-
-
-
-);
-
-/* ── 소개 텍스트 (MBTI, 연락빈도, 취미) ── */
-const ProfileIntro = ({ profile }: { profile: ProfileData }) => (
- <>
-
-
- {profile.mbti}
-
-
- {getContactFrequencyLabel(profile.contactFrequency)} ➡️
-
-
-
-
-
- {getHobbyLabel(profile.hobbies)}
-
-
- >
-);
-
-/* ── 라벨 + 밑줄 값 행 (반복 패턴 제거) ── */
-const IntroRow = ({
- label,
- value,
- suffix,
-}: {
- label: string;
- value: React.ReactNode;
- suffix?: string;
-}) => (
-
-
-
-
-
- {value}
-
-
- {suffix && (
-
- {suffix}
-
- )}
-
-
-);
-
-/* ── 펼치기 영역 (장점, 노래, 한마디) ── */
-const ExpandableDetails = ({
- profile,
- isExpanded,
-}: {
- profile: ProfileData;
- isExpanded: boolean;
-}) => (
-
-);
-
-/* ── 소셜 ID 표시 ── */
-const SocialIdDisplay = ({ profile }: { profile: ProfileData }) => {
- if (!profile.socialType || !profile.socialAccountId) return null;
-
- if (profile.socialType === "KAKAO") {
- return (
-
-
-
- {profile.socialAccountId}
-
-
- );
- }
- return (
- @{profile.socialAccountId}
- );
-};
-
-/* ── 메인 컴포넌트 ── */
-interface ContactUserProfileProps {
- profiles: ProfileData[];
-}
-
-const ContactUserProfile = ({ profiles }: ContactUserProfileProps) => {
- const [activeIndex, setActiveIndex] = useState(0);
- const [isExpanded, setIsExpanded] = useState(false);
- const scrollRef = useRef(null);
-
- useEffect(() => {
- const el = scrollRef.current;
- if (!el) return;
-
- const handleScroll = () => {
- const index = Math.round(el.scrollLeft / el.clientWidth);
- setActiveIndex(index);
- };
-
- el.addEventListener("scroll", handleScroll);
- return () => el.removeEventListener("scroll", handleScroll);
- }, []);
-
- if (!profiles || profiles.length === 0) return null;
-
- return (
-
-
- {/* 스와이프 카드 영역 */}
-
- {profiles.map((profile) => (
-
- ))}
-
-
- {/* 그라디언트 푸터 */}
-
-
-
- {/* 인디케이터 도트 (슬라이딩 트랙 방식) */}
- {profiles.length > 1 && (
-
- {/* 도트 5개 너비 (6px * 5 + 6px 간격 * 4 = 54px) */}
-
-
- {profiles.map((profile, i) => {
- // 현재 보여지는 5개 도트의 윈도우 범위 계산
- const windowStart = Math.max(
- 0,
- Math.min(profiles.length - 5, activeIndex - 2),
- );
- const windowEnd = windowStart + 4;
-
- // 윈도우 안에 있는지 확인
- const isVisible = i >= windowStart && i <= windowEnd;
- // 윈도우의 양 끝 도트인지 확인 (더 있다는 표시로 작게 만듦)
- const isEdge =
- (i === windowStart && i > 0) ||
- (i === windowEnd && i < profiles.length - 1);
-
- return (
-
- );
- })}
-
-
-
- )}
-
- );
-};
-
-export default ContactUserProfile;
diff --git a/app/main/_components/ProfileCard.tsx b/app/main/_components/ProfileCard.tsx
new file mode 100644
index 0000000..923c1da
--- /dev/null
+++ b/app/main/_components/ProfileCard.tsx
@@ -0,0 +1,256 @@
+"use client";
+
+import { Hobby, ProfileData } from "@/lib/types/profile";
+import Image from "next/image";
+import { Send } from "lucide-react";
+import React, { useRef } from "react";
+
+/* ── 유틸 함수 ── */
+const getContactFrequencyLabel = (freq?: string) => {
+ switch (freq) {
+ case "FREQUENT":
+ return "자주";
+ case "NORMAL":
+ return "보통";
+ case "RARE":
+ return "드물게";
+ default:
+ return freq || "보통";
+ }
+};
+
+const getAge = (birthDate?: string) => {
+ if (!birthDate) return "?? ";
+ return new Date().getFullYear() - new Date(birthDate).getFullYear() + 1;
+};
+
+/* ── 태그 컴포넌트 ── */
+const Tag = ({ text }: { text: string }) => (
+
+
+ {text}
+
+
+);
+
+/* ── 프로필 헤더 (이미지 + 닉네임 + 액션 아이콘) ── */
+const ProfileHeader = ({ profile }: { profile: ProfileData }) => (
+
+ {/* 프로필 이미지 (48x48 container, 44x44 image) */}
+
+
+ {/* 닉네임 */}
+
+ 내가 뽑은 사람
+
+ {profile.nickname || "익명"}
+
+
+
+
+
+
+
+
+);
+
+/* ── 나이 + MBTI + 연락빈도 ── */
+const ProfileStats = ({ profile }: { profile: ProfileData }) => (
+
+
+ 나이
+
+ {getAge(profile.birthDate)}
+
+
+
+ MBTI
+ {profile.mbti}
+
+
+
+ 연락빈도
+
+
+ {getContactFrequencyLabel(profile.contactFrequency)}
+
+
+
+);
+
+/* ── 확장 가능한 상세 정보 ── */
+const ProfileDetails = ({
+ profile,
+ isExpanded,
+}: {
+ profile: ProfileData;
+ isExpanded: boolean;
+}) => (
+ Click) 블러가 나중에 생기도록 delay 부여
+ transition: isExpanded
+ ? "max-height 500ms ease-in-out, mask-image 300ms ease-out, -webkit-mask-image 300ms ease-out"
+ : "max-height 500ms ease-in-out, mask-image 400ms ease-in 100ms, -webkit-mask-image 400ms ease-in 100ms",
+ }}
+ >
+ {/* 관심사 */}
+
+
관심사
+
+ {profile.hobbies && profile.hobbies.length > 0 ? (
+ profile.hobbies.map((hobby) => (
+
+ ))
+ ) : (
+
+ )}
+
+
+
+ {/* 장점 */}
+
+
장점
+
+ {profile.advantages && profile.advantages.length > 0 ? (
+ profile.advantages.map((adv) => )
+ ) : (
+
+ )}
+
+
+
+ {/* 좋아하는 노래 */}
+
+ 좋아하는 노래
+
+ {profile.favoriteSong || "아직 없어요!"}
+
+
+
+ {/* 나를 소개하는 한마디 */}
+
+ 나를 소개하는 한마디
+
+ {profile.intro || "잘 부탁드립니다!! 😆"}
+
+
+
+);
+
+/* ── 소셜 ID 표시 ── */
+const SocialIdDisplay = ({ profile }: { profile: ProfileData }) => {
+ if (!profile.socialType || !profile.socialAccountId) return null;
+
+ if (profile.socialType === "KAKAO") {
+ return (
+
+
+
+ {profile.socialAccountId}
+
+
+ );
+ }
+ return (
+
+ @{profile.socialAccountId}
+
+ );
+};
+
+/* ── 메인 프로필 카드 컴포넌트 ── */
+interface ProfileCardProps {
+ profile: ProfileData;
+}
+
+const ProfileCard = ({ profile }: ProfileCardProps) => {
+ const [isExpanded, setIsExpanded] = React.useState(false);
+ const touchStartTime = useRef(0);
+
+ const handleCardClick = () => {
+ const touchDuration = Date.now() - touchStartTime.current;
+ if (touchDuration < 200) {
+ setIsExpanded(!isExpanded);
+ }
+ };
+
+ return (
+
+ {/* 카드 본체 */}
+
(touchStartTime.current = Date.now())}
+ onMouseDown={() => (touchStartTime.current = Date.now())}
+ onClick={handleCardClick}
+ onKeyDown={(e) => {
+ if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
+ setIsExpanded(!isExpanded);
+ }
+ }}
+ className="flex w-full cursor-pointer flex-col items-center justify-start gap-3 p-4"
+ >
+
+
+
+
+
+ {/* 그라디언트 푸터 */}
+
+
+ );
+};
+
+export default ProfileCard;
diff --git a/app/main/_components/ProfileSlider.tsx b/app/main/_components/ProfileSlider.tsx
new file mode 100644
index 0000000..19592d1
--- /dev/null
+++ b/app/main/_components/ProfileSlider.tsx
@@ -0,0 +1,100 @@
+"use client";
+
+import { ProfileData } from "@/lib/types/profile";
+import React, { useEffect, useRef, useState } from "react";
+import ProfileCard from "./ProfileCard";
+
+/* ── 프로필 슬라이더 (스와이프 + 인디케이터) ── */
+interface ProfileSliderProps {
+ profiles: ProfileData[];
+}
+
+const ProfileSlider = ({ profiles }: ProfileSliderProps) => {
+ const [activeIndex, setActiveIndex] = useState(0);
+ const scrollRef = useRef(null);
+
+ useEffect(() => {
+ const el = scrollRef.current;
+ if (!el) return;
+
+ const handleScroll = () => {
+ const index = Math.round(el.scrollLeft / el.clientWidth);
+ setActiveIndex(index);
+ };
+
+ el.addEventListener("scroll", handleScroll);
+ return () => el.removeEventListener("scroll", handleScroll);
+ }, []);
+
+ if (!profiles || profiles.length === 0) return null;
+
+ return (
+
+ {/* 스와이프 카드 영역 */}
+
+ {profiles.map((profile) => (
+
+ ))}
+
+
+ {/* 인디케이터 도트 (슬라이딩 트랙 방식) */}
+ {profiles.length > 1 && (
+
+ {/* 도트 5개 너비 (6px * 5 + 6px 간격 * 4 = 54px) */}
+
+
+ {profiles.map((profile, i) => {
+ // 현재 보여지는 5개 도트의 윈도우 범위 계산
+ const windowStart = Math.max(
+ 0,
+ Math.min(profiles.length - 5, activeIndex - 2),
+ );
+ const windowEnd = windowStart + 4;
+
+ // 윈도우 안에 있는지 확인
+ const isVisible = i >= windowStart && i <= windowEnd;
+ // 윈도우의 양 끝 도트인지 확인 (더 있다는 표시로 작게 만듦)
+ const isEdge =
+ (i === windowStart && i > 0) ||
+ (i === windowEnd && i < profiles.length - 1);
+
+ return (
+
+ );
+ })}
+
+
+
+ )}
+
+ );
+};
+
+export default ProfileSlider;
diff --git a/app/main/_components/ScreenMainPage.tsx b/app/main/_components/ScreenMainPage.tsx
index cea1ced..9355ffa 100644
--- a/app/main/_components/ScreenMainPage.tsx
+++ b/app/main/_components/ScreenMainPage.tsx
@@ -10,7 +10,7 @@ import {
import BusinessInfo from "@/components/common/BusinessInfo";
import NoticeSection from "./NoticeSection";
-import ContactUserProfile from "./ContactUserProfile";
+import ProfileSlider from "./ProfileSlider";
import { ProfileData } from "@/lib/types/profile";
import ChargeRequestWaiting from "./ChargeRequestWaiting";
@@ -139,7 +139,7 @@ const ScreenMainPage = () => {
/>
)}
{/* */}
-
+