📸 바이럴

HTML2Canvas로 결과 이미지 공유 기능 구현하기

웹 페이지를 이미지로 바꿔서 카카오톡에 공유하기

📅 2026.02.15 ⏱️ 10분 읽기 👨‍💻 개발자

💭 공유 기능, 왜 필요했나

MBTI 검사 결과가 나왔을 때, 사용자들이 "이거 친구한테 보여주고 싶은데?" 하는 생각이 들게 만들고 싶었습니다. 그런데 단순히 링크만 공유하면 뭔가 심심하더군요.

그래서 생각한 게 **결과를 이미지로 만들어서 공유**하는 기능이었습니다. 카카오톡이나 인스타그램 스토리에 올리기 좋게, 예쁜 그래프와 결과를 한 장의 이미지로 만드는 거죠. 마치 인스타그램에서 보는 "나의 MBTI는?" 같은 이미지처럼요.

💡 이미지 공유의 장점

  • • 시각적으로 눈에 띄어서 클릭률 증가
  • • 카카오톡 미리보기에서 바로 보임
  • • 테스트 안 한 사람도 결과를 볼 수 있음
  • • 바이럴 효과 극대화

🔍 html2canvas 라이브러리 발견

처음에는 "웹 페이지를 어떻게 이미지로 만들지?" 고민이 많았습니다. Canvas API를 직접 사용해서 그래프를 그려야 하나? 싶었는데, 검색하다가 `html2canvas`라는 라이브러리를 발견했습니다.

html2canvas란?

HTML 요소를 Canvas로 렌더링해주는 JavaScript 라이브러리입니다. 복잡한 Canvas API를 몰라도 HTML을 그대로 이미지로 만들 수 있죠.

CDN으로 간단하게 추가:

<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>

💻 구현 과정

1단계: 캡처할 영역 지정하기

결과 페이지 전체가 아니라, **결과 헤더 + 그래프** 부분만 캡처하고 싶었습니다. 그래서 해당 영역을 `

`로 감싸고 ID를 부여했습니다.

<div id="share-capture-area">
    <!-- 결과 헤더 -->
    <div class="result-header">
        <h1>홍길동님의 MBTI는 INTJ입니다!</h1>
    </div>
    
    <!-- 성격 지표 그래프 -->
    <div class="dimension-bars">
        <!-- EI, SN, TF, JP 막대 그래프 -->
    </div>
</div>

💡 영역 선택 팁

너무 많은 내용을 담으면 이미지가 길어져서 공유할 때 불편합니다. 핵심만 담는 게 좋습니다. 저는 결과 타입 + 4가지 지표 그래프까지만 포함시켰습니다.

2단계: html2canvas로 이미지 생성

이제 "공유하기" 버튼을 누르면 해당 영역을 캡처하도록 만들었습니다.

async function shareResult() {
    // 1. 캡처할 영역 선택
    const captureArea = document.getElementById('share-capture-area');
    
    // 2. html2canvas로 캡처
    const canvas = await html2canvas(captureArea, {
        backgroundColor: '#f3f4f6',  // 배경색
        scale: 2,                     // 고해상도 (레티나 대응)
        logging: false,               // 콘솔 로그 끄기
        useCORS: true                 // 외부 이미지 허용
    });
    
    // 3. Canvas를 Blob으로 변환
    const blob = await new Promise(resolve => 
        canvas.toBlob(resolve, 'image/png')
    );
    
    // 4. File 객체 생성
    const file = new File([blob], 'mbti-result.png', { 
        type: 'image/png' 
    });
}

⚙️ 옵션 설명

  • scale: 2 - 고해상도 이미지 생성 (모바일 레티나 디스플레이 대응)
  • backgroundColor - 투명 배경 대신 색상 지정
  • useCORS - 외부 이미지(CDN 폰트 등) 로드 허용
  • logging: false - 개발자 도구 콘솔 깔끔하게 유지

3단계: Web Share API로 공유

이미지가 생성되었으니, 이제 실제로 공유할 차례입니다. 모바일에서는 Web Share API를 사용하면 카카오톡, 인스타그램 등 설치된 앱으로 바로 공유할 수 있습니다.

// Web Share API 지원 확인
if (navigator.share && navigator.canShare({ files: [file] })) {
    await navigator.share({
        title: 'MBTI 검사 결과',
        text: '홍길동님의 MBTI는 INTJ입니다! 🎉\\n\\n당신도 검사해보세요!',
        url: shareUrl,
        files: [file]  // 이미지 파일 첨부
    });
} else {
    // 대체 방법 실행
    fallbackShare();
}

✅ 모바일 (iOS/Android)

Web Share API 완벽 지원

  • → 카카오톡으로 공유
  • → 인스타그램 스토리
  • → 페이스북, 트위터
  • → 모든 공유 앱 선택 가능

💻 PC (대체 방법)

자동 다운로드 + 클립보드

  • → 이미지 자동 다운로드
  • → 공유 텍스트 복사
  • → 수동으로 붙여넣기

4단계: PC용 대체 방법 구현

PC에서는 Web Share API가 완벽하게 지원되지 않습니다. 그래서 대체 방법을 만들었습니다.

function fallbackShare(canvas, text, url) {
    // 1. 이미지 자동 다운로드
    const link = document.createElement('a');
    link.download = 'mbti-result.png';
    link.href = canvas.toDataURL('image/png');
    link.click();
    
    // 2. 공유 텍스트 클립보드 복사
    const shareText = \`\${text}\\n\\n결과 보기: \${url}\`;
    navigator.clipboard.writeText(shareText).then(() => {
        alert('✅ 이미지가 다운로드되었고, 공유 텍스트가 클립보드에 복사되었습니다!');
    });
}

🎨 예쁜 이미지 만들기

이미지 기능이 작동한다고 끝이 아닙니다. 공유할 가치가 있는 예쁜 이미지여야죠. 몇 가지 신경 쓴 부분들이 있습니다:

🎨 배경 그라데이션

단색 배경보다 그라데이션이 훨씬 고급스러워 보입니다

bg-gradient-to-r from-purple-600 to-indigo-600

📏 적절한 비율

너무 길면 SNS에 올릴 때 잘립니다. 정사각형에 가깝게 유지했습니다

✨ 고해상도

scale: 2 옵션으로 레티나 디스플레이에서도 선명하게

🔤 가독성

폰트 크기를 충분히 크게, 색상 대비도 높게 설정했습니다

⚠️ 겪은 문제들과 해결

문제 1: 그라데이션이 이미지에서 안 보임

처음에는 background-image로 그라데이션을 적용했는데, html2canvas가 인식을 못 했습니다.

해결:

Tailwind의 bg-gradient 클래스를 사용하니 정상적으로 캡처되었습니다.

문제 2: 외부 폰트가 깨짐

Google Fonts를 사용했는데, 이미지에서는 기본 폰트로 렌더링되었습니다.

해결:

useCORS: true 옵션을 추가하고, 폰트가 완전히 로드된 후에 캡처하도록 했습니다.

문제 3: 이미지 생성이 느림

복잡한 레이아웃은 캡처하는 데 2~3초 걸렸습니다.

해결:

로딩 인디케이터를 추가해서 사용자가 기다리는 것을 알 수 있게 했습니다.

📈 효과 측정

이미지 공유 기능을 추가한 후의 변화입니다:

Before vs After

링크만 공유 (Before)

  • • 클릭해야 결과 확인 가능
  • • 카카오톡에서 심심한 링크
  • • 관심 끌기 어려움

이미지 + 링크 (After)

  • • 바로 결과를 볼 수 있음
  • • 시각적으로 매력적
  • • 공유 의욕 증가

🎓 배운 점

  • 1️⃣ 라이브러리의 힘: html2canvas 없이 직접 구현했다면 몇 배는 오래 걸렸을 것입니다
  • 2️⃣ 브라우저 호환성: 모든 브라우저에서 완벽하게 작동하지 않으니 대체 방법이 필수입니다
  • 3️⃣ 사용자 경험: 공유 기능이 귀찮으면 아무도 안 씁니다. 최대한 간편하게 만들어야 합니다
  • 4️⃣ 바이럴의 중요성: 좋은 콘텐츠 + 쉬운 공유 = 자연스러운 확산

💡 마치며

이미지 공유 기능을 추가하면서 "바이럴"이란 게 단순히 운이 아니라, 설계할 수 있는 것임을 깨달았습니다. 사용자가 공유하고 싶게 만드는 것, 공유하기 쉽게 만드는 것, 공유했을 때 예쁘게 보이게 만드는 것. 이 모든 게 개발자의 역할이더군요.

다음에는 카카오톡 공유 API를 연동해서, 더 풍부한 링크 미리보기를 제공하고 싶습니다. 그리고 공유 횟수를 트래킹해서 어떤 MBTI 유형이 가장 많이 공유되는지도 분석해보고 싶어요.

📊

다음 글 예고

Chart.js로 직무 번아웃 테스트 데이터 시각화하기