로딩 중...
로딩 중...
카카오톡 공유하기 기능을 구현했는데 썸네일 이미지가 도통 나오지 않아 막막하셨나요? imageUrl에 URL을 정확히 넣었는데도 공유 미리보기에 이미지가 빠져 있다면, 원인은 카카오 내부 CDN 정책에 있습니다. 이 글에서 원인 분석부터 실전 코드까지 한번에 정리합니다.
![]()
카카오 sendDefault()의 imageUrl 필드에 외부 이미지 URL을 직접 넣으면 썸네일이 표시되지 않는 문제가 흔하게 발생합니다.
// ❌ 이렇게 하면 썸네일이 안 나옴
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: '공유 제목',
description: '공유 설명',
imageUrl: 'https://example.com/my-image.png', // ← 안 나옴!
link: { webUrl: 'https://example.com', mobileWebUrl: 'https://example.com' },
},
});
이미지 URL이 외부에서 접근 가능한 상태인데도 왜 안 나올까요?
카카오는 공유 미리보기 이미지를 자체 CDN(KAGE 서버,
k.kakaocdn.net)을 통해 제공합니다. 외부 URL을imageUrl에 직접 넣으면 카카오 서버가 이미지를 가져오지 못하거나, 가져왔더라도 KAGE에 올리는 과정이 실패해 썸네일이 비어있게 됩니다.
즉, 카카오 서버가 이미지를 직접 스크랩해서 자체 CDN에 올리는 과정이 실패하는 것이 근본 원인입니다.
카카오톡 공유하기 썸네일 문제의 해결책은 Kakao.Share.scrapImage()를 먼저 호출해 이미지를 KAGE 서버에 올린 뒤, 반환된 URL을 imageUrl에 넣는 것입니다.
// ✅ 해결: scrapImage → KAGE URL → sendDefault
const imageUrl = 'https://example.com/my-image.png';
// 1. 카카오 KAGE 서버에 이미지 업로드
const result = await Kakao.Share.scrapImage({ imageUrl });
const kageUrl = result.infos.original.url;
// → "http://k.kakaocdn.net/dn/xxxxx/kakaolink40_original.png"
// 2. KAGE URL로 공유
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: '공유 제목',
description: '공유 설명',
imageUrl: kageUrl, // ← KAGE URL 사용
link: { webUrl: 'https://example.com', mobileWebUrl: 'https://example.com' },
},
});
단 두 단계만 바꿨을 뿐인데, 카카오톡 공유하기 썸네일이 정상적으로 표시됩니다.
매번 공유할 때마다 scrapImage를 호출하면 불필요한 API 요청이 생깁니다. 아래처럼 캐싱 변수를 두면 한 번만 업로드하고 재사용할 수 있습니다.
let cachedKageUrl = null;
async function getKageImageUrl(imageUrl) {
if (cachedKageUrl) return cachedKageUrl;
try {
const result = await Kakao.Share.scrapImage({ imageUrl });
cachedKageUrl = result.infos.original.url;
return cachedKageUrl;
} catch (e) {
console.warn('scrapImage 실패:', e);
return imageUrl; // 실패 시 원본 URL 폴백
}
}
async function shareToKakao() {
const imageUrl = 'https://example.com/my-image.png';
const thumbUrl = await getKageImageUrl(imageUrl);
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: '공유 제목',
description: '공유 설명',
imageUrl: thumbUrl,
link: {
webUrl: 'https://example.com',
mobileWebUrl: 'https://example.com',
},
},
buttons: [
{
title: '자세히 보기',
link: {
webUrl: 'https://example.com',
mobileWebUrl: 'https://example.com',
},
},
],
});
}
카카오 SDK에는 이미지를 KAGE에 올리는 함수가 두 개 있어 혼동하기 쉽습니다.
| API | 입력 | 사용 상황 |
|---|---|---|
Kakao.Share.scrapImage({ imageUrl }) | URL 문자열 | 서버에 이미 있는 이미지를 KAGE에 업로드할 때 |
Kakao.Share.uploadImage({ file }) | File 객체 배열 | <input type="file">로 선택한 로컬 파일을 업로드할 때 |
// ✅ URL → KAGE 업로드
await Kakao.Share.scrapImage({ imageUrl: 'https://example.com/image.png' });
// ✅ 파일 input → KAGE 업로드
const files = document.getElementById('file-input').files;
await Kakao.Share.uploadImage({ file: files });
// ❌ uploadImage에 URL 문자열을 넣으면 동작 안 함
await Kakao.Share.uploadImage({ file: ['https://example.com/image.png'] }); // 실패
URL로 올릴 때는 scrapImage, 로컬 파일을 올릴 때는 uploadImage 라고 기억하면 됩니다.
Kakao.Share.sendDefault()는 카카오톡 앱을 통해 공유하는 API입니다.
PC 사용자를 위해 디바이스를 분기 처리하는 것이 좋습니다.
function isMobileDevice() {
return /Android|iPhone|iPad|iPod|webOS|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
);
}
async function handleKakaoShare(shareUrl) {
if (!isMobileDevice()) {
// PC: 클립보드에 URL 복사 후 안내
await navigator.clipboard.writeText(shareUrl);
alert('링크가 복사되었습니다. 카카오톡에 붙여넣기 해주세요!');
return;
}
// 모바일: 카카오 SDK로 공유
const thumbUrl = await getKageImageUrl('https://example.com/my-image.png');
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: '공유 제목',
description: '공유 설명',
imageUrl: thumbUrl,
link: { webUrl: shareUrl, mobileWebUrl: shareUrl },
},
});
}
썸네일이 계속 안 나온다면 아래 항목을 순서대로 확인하세요.
| 순서 | 확인 항목 | 설명 |
|---|---|---|
| 1 | scrapImage 사용 여부 | 외부 URL 직접 사용 불가. 반드시 scrapImage → KAGE URL 변환 |
| 2 | 이미지 URL이 HTTPS인지 | HTTP는 지원 안 됨 |
| 3 | 이미지 외부 접근 가능 여부 | curl -I <이미지URL>로 200 OK 확인 |
| 4 | 포트 80/443 여부 | 비표준 포트(8000, 3000 등)는 카카오 스크래퍼가 접근 불가 |
| 5 | 파일 크기 5MB 이하 | 초과 시 업로드 실패 |
| 6 | 카카오 개발자 콘솔 도메인 등록 | 앱 설정 → 플랫폼 → Web에 사이트 도메인 등록 필요 |
| 7 | localhost에서 테스트 여부 | 카카오 서버는 localhost 접근 불가. 프로덕션 이미지 URL 사용 |
[사진 추천: 카카오 개발자 콘솔(developers.kakao.com)에서 Web 플랫폼 도메인 등록 화면 캡처]
아래 스크립트를 브라우저 콘솔에 붙여넣으면 이미지 접근 → SDK 초기화 → scrapImage까지 단계별로 원인을 빠르게 파악할 수 있습니다.
(async () => {
const IMAGE_URL = 'https://example.com/my-image.png'; // ← 본인 이미지 URL
const KAKAO_KEY = 'your-kakao-js-key'; // ← 본인 앱 키
// 1. 이미지 접근 테스트
console.log('1. 이미지 접근 테스트');
try {
const res = await fetch(IMAGE_URL, { method: 'HEAD' });
console.log(' 상태:', res.status, '| Content-Type:', res.headers.get('content-type'));
} catch (e) {
console.error(' 이미지 접근 실패:', e.message);
}
// 2. SDK 초기화
if (!window.Kakao?.isInitialized()) {
if (!window.Kakao) {
await new Promise(r => {
const s = document.createElement('script');
s.src = 'https://t1.kakaocdn.net/kakao_js_sdk/2.7.4/kakao.min.js';
s.onload = r;
document.head.appendChild(s);
});
}
window.Kakao.init(KAKAO_KEY);
}
console.log('2. SDK 초기화:', Kakao.isInitialized());
// 3. scrapImage 테스트
console.log('3. scrapImage 테스트');
try {
const result = await Kakao.Share.scrapImage({ imageUrl: IMAGE_URL });
console.log(' KAGE URL:', result.infos.original.url);
} catch (e) {
console.error(' scrapImage 실패:', e);
}
})();
콘솔에서 각 단계 결과를 확인하면 어느 지점에서 막히는지 정확히 알 수 있습니다.
scrapImage를 다시 호출하면 새 KAGE URL이 발급됩니다cachedKageUrl 변수 등으로 캐싱하면 매번 업로드하지 않아도 됩니다A: 체크리스트 2~7번 항목을 확인하세요. 특히 이미지가 HTTPS인지, 표준 포트(80/443)를 사용하는지, 카카오 개발자 콘솔에 도메인이 등록되어 있는지를 우선 점검하세요. 브라우저 콘솔에서 진단 스크립트를 실행하면 어느 단계에서 실패하는지 바로 알 수 있습니다.
A: 불가능합니다. 카카오 서버는 localhost로 접근할 수 없기 때문에 scrapImage가 실패합니다. 개발 중에는 이미지 URL만 실제 서버(프로덕션 또는 스테이징)의 절대경로로 지정해 테스트하거나, ngrok 같은 터널링 도구로 로컬을 외부에 노출해야 합니다.
A: isMobileDevice() 등으로 PC/모바일을 분기 처리하여, PC 환경에서는 카카오 SDK 대신 클립보드 복사를 사용하면 됩니다. 위 예시 코드를 참고하세요.
A: 이미 서버에 올라가 있는 이미지를 URL로 KAGE에 올릴 때는 scrapImage({ imageUrl }), 사용자가 파일 선택기로 고른 로컬 파일을 KAGE에 올릴 때는 uploadImage({ file }) 을 사용합니다.
카카오톡 공유하기 썸네일이 안 나오는 핵심 원인은 외부 이미지 URL을 imageUrl에 직접 넣기 때문입니다. Kakao.Share.scrapImage()로 이미지를 카카오 KAGE 서버에 먼저 올리고, 반환된 URL을 사용하면 문제가 해결됩니다. 체크리스트와 진단 스크립트를 함께 활용하면 대부분의 상황에서 원인을 빠르게 찾을 수 있습니다.
카카오 SDK 관련 더 궁금한 점이 있다면 카카오톡 공유 JavaScript 공식 문서를 참고하세요.