SCRUM-11021 | 커밋 수: 81개 | 기간: 2025.02 ~ 2025.03
문제상황
공유하기 기능이 여러 컴포넌트에 분산되어 있어 일관성이 부족했습니다. 리워드링크 기능을 신규로 도입해야 하는 요구사항이 있었고, 웹/앱/더보기 지원 여부에 따른 UI 분기가 복잡한 상황이었습니다.
주요 개선사항
SharePopup 컴포넌트를 통합하여 공유하기 로직을 중앙화했습니다. 리워드링크 안내, 적립금 조회, 설정 페이지를 구현했고, 단축 URL 적용 및 클립보드 복사 기능을 추가했습니다. Lottie 애니메이션을 적용하여 사용자 경험을 향상시켰습니다.
정량적 성과
공유하기 관련 컴포넌트를 3개에서 1개로 통합했습니다. 리워드링크 관련 신규 페이지를 4개 구현했으며, SharePopup 관련 테스트 코드를 추가했습니다.
| 항목 | 비교 | 값 (개) |
|---|---|---|
| 컴포넌트(Before) | 3 개 | |
| 컴포넌트(After) | 1 개 | |
| 신규 페이지 | 4 개 | |
| 커밋 수 | 81 개 |
비즈니스 임팩트
사용자의 공유 경험에서 일관성을 확보했습니다. 리워드링크를 통한 신규 마케팅 채널을 확보했으며, SNS 공유 시 단축 URL을 적용하여 사용자 경험을 개선했습니다.
공유 통합
3개 컴포넌트 → 1개 SharePopup
리워드링크
신규 마케팅 채널 4페이지
단축 URL
정규식 검증으로 불필요한 API 호출 방지
기술적 구현 상세
AS-IS (분산 공유)
장점
- 각 페이지 독립 동작
고려할 점
- 공유 로직 중복
- 단축 URL 불일치
- 리워드링크 추가 시 전체 수정 필요
TO-BE (SharePopup 통합)
장점
- 단일 컴포넌트로 공유 일원화
- 리워드링크 토글 내장
- 단축 URL 자동 처리
고려할 점
- SharePopup 복잡도 증가
AS-IS
기존에는 공유하기 기능이 여러 컴포넌트에 분산되어 있었습니다.
// 기존 구조 (더미 예시)
// 각 페이지마다 공유 로직이 중복
const shareToKakao = () => {
// 카카오 공유 로직
};
const shareToSms = () => {
// SMS 공유 로직
};
const copyToClipboard = () => {
// 클립보드 복사 로직
};
문제점:
공유 로직이 여러 컴포넌트에 중복되어 있었습니다. 단축 URL 생성 로직이 컴포넌트마다 불일치했고, 리워드링크 기능을 추가하려면 모든 컴포넌트를 수정해야 하는 구조였습니다.
TO-BE
SharePopup 컴포넌트로 통합하고, 리워드링크 섹션을 추가했습니다.
// 통합된 공유 인터페이스
interface ShareInfo {
title: string;
description: string;
imageUrl: string;
shareUrl: string;
shortUrl?: string;
rewardLinkEnabled?: boolean;
}
- 공유 트리거
- SharePopup 열기
- 리워드링크 토글
- 단축URL 생성
- 채널별 공유
핵심 구현
1. SharePopup 컴포넌트 통합
<!-- components/popup/SharePopup.vue -->
<script setup lang="ts">
import { useShare } from '@/hooks/common';
const props = defineProps<{
shareInfo: ShareInfo;
}>();
const { shareToKakao, shareToSms, copyUrl, getShortUrl } = useShare();
const handleShare = async (type: ShareType) => {
// 단축 URL 생성
const url = await getShortUrl(props.shareInfo.shareUrl);
switch (type) {
case 'kakao':
shareToKakao({ ...props.shareInfo, shareUrl: url });
break;
case 'sms':
shareToSms(url);
break;
case 'copy':
copyUrl(url);
break;
}
};
</script>
<template>
<div class="share-popup">
<RewardLinkSection v-if="shareInfo.rewardLinkEnabled" />
<div class="share-buttons">
<button @click="handleShare('kakao')">카카오톡</button>
<button @click="handleShare('sms')">문자</button>
<button @click="handleShare('copy')">URL 복사</button>
</div>
</div>
</template>
2. 리워드링크 섹션 구현
<!-- components/popup/RewardLinkSection.vue -->
<script setup lang="ts">
import { useBenefitStore } from '@/stores/modules/benefit';
const benefitStore = useBenefitStore();
const { rewardLinkInfo, isRewardLinkEnabled } = storeToRefs(benefitStore);
const toggleRewardLink = async (enabled: boolean) => {
await benefitStore.setRewardLinkEnabled(enabled);
};
</script>
<template>
<div class="reward-link-section">
<div class="info">
<p>리워드링크로 공유하면 적립금을 받을 수 있어요!</p>
</div>
<ToggleButton
:value="isRewardLinkEnabled"
@change="toggleRewardLink"
/>
</div>
</template>
3. 단축 URL 정규표현식 검증
// hooks/common.ts
export const useShare = () => {
const isShortUrl = (url: string): boolean => {
// 단축 URL 패턴 검증
const shortUrlPattern = /^https?:\/\/[a-z]+\.link\/[a-zA-Z0-9]+$/;
return shortUrlPattern.test(url);
};
const getShortUrl = async (url: string): Promise<string> => {
if (isShortUrl(url)) {
return url;
}
// 단축 URL API 호출
const response = await commonApi.createShortUrl(url);
return response.shortUrl;
};
return { getShortUrl, isShortUrl };
};
4. 리워드링크 적립금 조회 페이지
<!-- views/promotion/RewardLink.vue -->
<script setup lang="ts">
import { useBenefitStore } from '@/stores/modules/benefit';
import { LottieAnimation } from '@/components/common';
const benefitStore = useBenefitStore();
const { rewardHistory, totalReward } = storeToRefs(benefitStore);
// 고래 이미지 위치 계산 (최대 포인트 기준)
const whalePosition = computed(() => calculatePosition(totalReward.value));
</script>
<template>
<div class="reward-link-page">
<LottieAnimation :position="whalePosition" />
<!-- 총 적립금 표시 -->
<!-- 월별 요약 내역 -->
</div>
</template>
회고
잘한 점
공유하기 로직을 Composable로 추출하여 재사용성을 확보했습니다. 단축 URL 검증 로직을 정규표현식으로 구현하여 이미 단축된 URL에 대한 불필요한 API 호출을 방지했습니다. Lottie 애니메이션을 적용하여 리워드링크 페이지의 사용자 경험을 향상시켰습니다.
개선할 점
초기 설계 시 리워드링크 기능을 고려했다면 더 깔끔한 구조가 가능했을 것입니다. 또한 토글 버튼의 유효성 검사 로직에 대한 개선이 필요합니다.
배운 점
공유하기 기능의 플랫폼별 차이점(웹/앱/네이티브)을 체감했습니다. 단축 URL 서비스 연동 방법과 Lottie 애니메이션을 Vue 컴포넌트에 통합하는 방법을 익혔습니다.