HTML2Canvas로 결과 이미지 공유 기능 구현하기
웹 페이지를 이미지로 바꿔서 카카오톡에 공유하기
💭 공유 기능, 왜 필요했나
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단계: 캡처할 영역 지정하기
결과 페이지 전체가 아니라, **결과 헤더 + 그래프** 부분만 캡처하고 싶었습니다. 그래서 해당 영역을 `
<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로 직무 번아웃 테스트 데이터 시각화하기